diff --git a/.gitignore b/.gitignore index 46fafc7..d58a5ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ site .idea .DS_Store +deploy/logs diff --git a/deploy/README.md b/deploy/README.md new file mode 100644 index 0000000..758d790 --- /dev/null +++ b/deploy/README.md @@ -0,0 +1,70 @@ +# Deploy example + +In order to launch a local deployment of the platform, you can do the following: + +## Add Keycloak to the local hosts file + +In order for the Portal to connect to Keycloak correctly, they need to be added +to the local hosts file pointing to the local IP. +Open `/etc/hosts` and add them like so: + +``` +0.0.0.0 keycloak +0.0.0.0 portal +``` + +## Start the containers + +All the containers can be started and configured using the script included + +``` + ./deploy.sh +``` + +and for stopping the containers, there's another script for that as well + +``` + ./clean.sh +``` + +## Set up Keycloak from the Admin UI + +There's a few necessary steps to setup Keycloak to work with the Portal: + +1. Access the Admin UI from http://localhost:8080 +2. Login with the default admin user (USERNAME: admin, PASSWORD: password) +3. Under clients, find the admin-cli client. Under Service Account Roles, add + all the available unassigned roles to the client. +4. Under users, create a new user. Give it a username and email at least, and + set a password for it. Ensure to tick the box for verified email, and untick + the box for temporary password. Add the user to the groups + /EnvironmentManagement/Demo and Admin under the Town group. + +## Log into the Portal + +You can now log into the portal at http://localhost:8000 using the newly created +user. An example Device and Group has been created and filled with a basic +air quality attribute. + +## Send some data to the UL IoT Agent + +With the script send_payload_to_agent.sh you can send an air quality reading to +a device called Device. The script can be invoked as: + +``` + ./send_payload_to_agent.sh 51 +``` + +Where 51 is the air quality reading to send for example. You can see the changes +reflect onto the map in Grafana. + +## Log into Grafana + +The Grafana dashboards can be found at http://localhost:3000 . Login with the +default admin user (USERNAME: admin, PASSWORD: admin). An example dashboard +can be found under the general group showing a map with the example device for +air quality. It should appear as an icon in Switzerland. + +# Todo (next) +- Use newer keycloak and load scripts +- Use newer grafana diff --git a/deploy/clean.sh b/deploy/clean.sh new file mode 100755 index 0000000..b74136b --- /dev/null +++ b/deploy/clean.sh @@ -0,0 +1,2 @@ +#!/bin/bash +docker-compose down -v \ No newline at end of file diff --git a/deploy/update.sh b/deploy/crate-datasource/.gitattributes old mode 100644 new mode 100755 similarity index 100% rename from deploy/update.sh rename to deploy/crate-datasource/.gitattributes diff --git a/deploy/crate-datasource/.gitignore b/deploy/crate-datasource/.gitignore new file mode 100755 index 0000000..952eb7e --- /dev/null +++ b/deploy/crate-datasource/.gitignore @@ -0,0 +1,42 @@ +node_modules +npm-debug.log +coverage/ +.aws-config.json +awsconfig +/emails/dist +/public_gen +/tmp +vendor/phantomjs/phantomjs + +# Builded dist +# /dist + +# Test artifacts +/dist/test +/dist/spec + +docs/AWS_S3_BUCKET +docs/GIT_BRANCH +docs/VERSION +docs/GITCOMMIT +docs/changed-files +docs/changed-files + +# locally required config files +public/css/*.min.css + +# Editor junk +*.sublime-workspace +*.sublime-project +*.swp +.idea/ +*.iml + +/data/* +/bin/* + +conf/custom.ini +fig.yml +profile.cov +grafana +.notouch diff --git a/deploy/crate-datasource/.jscsrc b/deploy/crate-datasource/.jscsrc new file mode 100755 index 0000000..dcf694d --- /dev/null +++ b/deploy/crate-datasource/.jscsrc @@ -0,0 +1,13 @@ +{ + "disallowImplicitTypeConversion": ["string"], + "disallowKeywords": ["with"], + "disallowMultipleLineBreaks": true, + "disallowMixedSpacesAndTabs": true, + "disallowTrailingWhitespace": true, + "requireSpacesInFunctionExpression": { + "beforeOpeningCurlyBrace": true + }, + "disallowSpacesInsideArrayBrackets": true, + "disallowSpacesInsideParentheses": true, + "validateIndentation": 2 +} \ No newline at end of file diff --git a/deploy/crate-datasource/.jshintrc b/deploy/crate-datasource/.jshintrc new file mode 100755 index 0000000..300d6de --- /dev/null +++ b/deploy/crate-datasource/.jshintrc @@ -0,0 +1,46 @@ +{ + "browser": true, + + "bitwise":false, + "curly": true, + "eqnull": true, + "strict": true, + "module": true, + "devel": true, + "eqeqeq": true, + "forin": false, + "immed": true, + "supernew": true, + "expr": true, + "indent": 2, + "latedef": false, + "newcap": true, + "noarg": true, + "noempty": true, + "undef": true, + "boss": true, + "trailing": true, + "laxbreak": true, + "laxcomma": true, + "sub": true, + "unused": true, + "maxdepth": 6, + "maxlen": 140, + "esnext": true, + + "globals": { + "System": true, + "Promise": true, + "define": true, + "require": true, + "Chromath": false, + "setImmediate": true, + "expect": true, + "it": true, + "describe": true, + "sinon": true, + "module": true, + "beforeEach": true, + "inject": true + } +} diff --git a/deploy/crate-datasource/CHANGELOG.md b/deploy/crate-datasource/CHANGELOG.md new file mode 100755 index 0000000..4584f0f --- /dev/null +++ b/deploy/crate-datasource/CHANGELOG.md @@ -0,0 +1,49 @@ +# Change Log + + +## [Unreleased] + + +## [0.5.1] - 2017-04-05 +### Changed +- Use date_trunk() when interval set to second, minute, etc +- Override limit only for Raw agg queries. + + +## [0.5.0] - 2017-03-22 +### Added +- Checks schema and table (prevent queries to different source). + + +## [0.4.0] - 2017-03-19 +### Added +- 'Auto' (uses date_trunk()) and 'Auto (Grafana)' (uses floor()) time intervals. + +### Fixed +- 10K issue + +### Changed +- Use explicit aggregation by time interval based on floor() instead date_trunk() + +## [0.3.0] - 2017-03-02 +### Added +- Table mode support +- Ad-hoc filters support +- $timeFilter variable support +- Quote column names with capital letters [#28](https://github.com/raintank/crate-datasource/issues/28) +- Support GROUP BY in raw queries, issue [#30](https://github.com/raintank/crate-datasource/issues/30) + +### Fixed +- Schema queries (changed in Crate 1.0) + + +## [0.2.0] - 2016-11-29 +### Added +- Special "Raw" aggregation type [#9](https://github.com/raintank/crate-datasource/issues/9) +- Alias for each field in SELECT + + +## [0.1.0] - 2016-07-10 +- Initial release +- Implementation by [raintank](http://raintank.io) +- Documentation contributions from [Crate.io](https://crate.io) diff --git a/deploy/crate-datasource/Gruntfile.js b/deploy/crate-datasource/Gruntfile.js new file mode 100755 index 0000000..589d8ad --- /dev/null +++ b/deploy/crate-datasource/Gruntfile.js @@ -0,0 +1,121 @@ +module.exports = function(grunt) { + + require('load-grunt-tasks')(grunt); + + grunt.loadNpmTasks('grunt-execute'); + grunt.loadNpmTasks('grunt-contrib-clean'); + + grunt.initConfig({ + + clean: ["dist"], + + copy: { + src_to_dist: { + cwd: 'src', + expand: true, + src: ['**/*', '!**/*.js', '!**/*.scss'], + dest: 'dist' + }, + pluginDef: { + expand: true, + src: ['README.md'], + dest: 'dist' + } + }, + + watch: { + rebuild_all: { + files: ['src/**/*'], + tasks: ['watch-ts'], + options: {spawn: false} + } + }, + + typescript: { + build: { + src: ['dist/**/*.ts', "!src/spec/**/*", "!**/*.d.ts"], + dest: 'dist/', + options: { + module: 'system', //or commonjs + target: 'es3', //or es5 + rootDir: 'dist/', + keepDirectoryHierarchy: false, + declaration: true, + emitDecoratorMetadata: true, + experimentalDecorators: true, + sourceMap: true, + noImplicitAny: false, + } + }, + distTests: { + src: ['src/**/*.ts', "!src/spec/**/*", "!**/*.d.ts"], + dest: 'dist/test/', + options: { + module: 'commonjs', //or commonjs + target: 'es5', //or es5 + rootDir: 'src/', + sourceRoot: 'src/', + declaration: true, + emitDecoratorMetadata: true, + experimentalDecorators: true, + sourceMap: true, + noImplicitAny: false, + } + }, + // distTestsSpecs: { + // src: ['src/spec/**/*.ts'], + // dest: 'dist/test/', + // options: { + // module: 'commonjs', //or commonjs + // target: 'es5', //or es5 + // declaration: true, + // emitDecoratorMetadata: true, + // experimentalDecorators: true, + // sourceMap: true, + // noImplicitAny: false, + // } + // } + }, + + babel: { + options: { + sourceMap: true, + presets: ['es2015'] + }, + distTestsSpecsNoSystemJs: { + files: [{ + expand: true, + cwd: 'src/spec', + src: ['**/*.js'], + dest: 'dist/test/spec', + ext:'.js' + }] + } + }, + + mochaTest: { + test: { + options: { + reporter: 'spec' + }, + src: ['dist/test/spec/test-main.js', 'dist/test/spec/*_specs.js'] + } + } + }); + + grunt.registerTask('default', [ + 'clean', + 'copy', + 'typescript:build', + 'typescript:distTests', + 'babel', + 'mochaTest' + ]); + + grunt.registerTask('watch-ts', [ + 'clean', + 'copy:src_to_dist', + 'copy:pluginDef', + 'typescript:build' + ]); +}; diff --git a/deploy/crate-datasource/LICENSE b/deploy/crate-datasource/LICENSE new file mode 100755 index 0000000..8dada3e --- /dev/null +++ b/deploy/crate-datasource/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/deploy/crate-datasource/README.md b/deploy/crate-datasource/README.md new file mode 100755 index 0000000..062e9b7 --- /dev/null +++ b/deploy/crate-datasource/README.md @@ -0,0 +1,108 @@ +# Grafana Data Source Plugin for CrateDB + +[![Crate.io logo](https://raw.githubusercontent.com/raintank/crate-datasource/master/crate-logo.png)](https://crate.io) + + +## What Is CrateDB? +CrateDB is a SQL database that makes it simple to store and analyze +massive amounts of machine data in real-time. CrateDB customers have +reported improving predictive analytic query performance of machine +data by 20x more than MySQL, while reducing database hardware costs by +75%. + +Here’s how CrateDB makes this possible: + +- **Combining SQL & Search** into a single DBMS - allowing you to process any data structure...time series, geospatial, JSON, full-text, etc. +- **Distributed query innovations** - that deliver real-time SQL performance +- **An auto-scaling architecture** - grow CrateDB with less DBA expertise +- **Dynamic schemas, adhoc queries** - quickly adapt to data structure changes + +For these reasons and more, CrateDB is your perfect datasource for Grafana. + +## The CrateDB Datasource Plugin for Grafana + +### Features +Enables CrateDB clusters to act as data sources for your Grafana deployment, providing real-time analytical and time-series data with SQL. + +### Requirements +- **Grafana** > 3.x.x +- **CrateDB** - All stable versions are supported by this plugin + +### Setup +![](https://raw.githubusercontent.com/raintank/crate-datasource/master/src/img/crate-datasource-add-src.png) + + > The screenshot shows a connection to http://localhost:44200 which is a test database for the purpose of this tutorial. CrateDB's default binding is to http://localhost:4200. + +1. Click on the Grafana icon on the top left. +2. After the menu opened, you should see a link `Data Sources` below `Dashboards`. +3. Click `+ Add data source`. +4. Select `CrateDB` from the 'Type' dropdown. + +#### Cross-origin Resource Sharing (CORS) + +CrateDB supports [cross-origin resource sharing](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) and if Grafana is running on a different origin (e.g. another domain), it is required to configure CrateDB accordingly. For example by this is the minimum required configuration in your `crate.yml`: +``` +http.cors.enabled: true +http.cors.allow-origin: "http://mydomain.com" +``` +> Replace http://mydomain.com with the domain Grafana is running on, or use a "*" if it's OK to allow any domain to access CrateDB + +For further options look in [CrateDB's documentation](https://crate.io/docs/reference/en/latest/configuration.html#cross-origin-resource-sharing-cors) + +#### The CrateDB Data Source + +Name | Description +------------ | ------------- +Name | The data source name. +Default | Set this data source as default for new panels. + +##### HTTP Settings + +Name | Description +------------ | ------------- +Url | The URI to any node in your CrateDB cluster. +Access | Via Grafana backend (proxy) or directly from the browser (direct). +Basic Auth | Enable basic authentication (only available via NGINX proxy in CrateDB). +User | Not available in CrateDB. +Password | Not available in CrateDB. + +##### CrateDB Details + +These are specific settings for the CrateDB data source and it's required to set a fixed `schema`, `table`, and time series column per data source. + +Name | Description +------------ | ------------- +Schema | CrateDB schema to query from (defaults to `doc`). +Table | Table to retrieve the data from. Has to be available in the previously defined schema. +Time Column | Time series column, has to be of type `timestamp` in CrateDB. +Default grouping interval | The grouping resolution (can be changed by query). + +![](https://raw.githubusercontent.com/raintank/crate-datasource/master/src/img/crate-datasource-nonvalidation.png) + +> Grafana will not check (yet) if the `time column`, the `schema`, or the `table` exists. Be sure to double check these values to avoid running into problems later. + +### Querying CrateDB + +After adding a new dashboard and having the query editor open, define and run the queries you like - it's just like other SQL databases. For example we have added the [NYC yellow cab data set](http://www.nyc.gov/html/tlc/html/about/trip_record_data.shtml) in our cluster to show you something interesting! + +![](https://raw.githubusercontent.com/raintank/crate-datasource/master/src/img/crate-datasource-graph.png) + +> This graph shows the number of yellow cab pick ups between on a weekend in August 2013. + +### Debugging Queries + +Grafana runs queries almost immediately after change and it will also auto-complete columns or previous values. However, sometimes queries might still be invalid and Grafana will then show a small exclamation mark in the top corner of the graph. Clicking on it will give you the error message. + +![](https://raw.githubusercontent.com/raintank/crate-datasource/master/src/img/crate-datasource-error.png) + +The CrateDB data source for Grafana supports a great range of scalar functions and operators. To read more about them, install or scale a cluster, or even to contribute to Crate, please have a look at the [official Crate documentation](https://crate.io/docs) + +### License +- This plugins is made available under the terms of the [Apache License, Version 2.0](https://github.com/crate/crate-datasource/blob/master/LICENSE). + +## Getting Help + +- Read the CrateDB documentation [here](https://crate.io/docs) +- Issues with the Grafana plugin can be reported or discussed [here](https://github.com/raintank/crate-datasource/issues) +- Issues with CrateDB can be reported or discussed [here](https://github.com/crate/crate/issues) +- Join the CrateDB Community Slack channel [here](https://crate.io/docs/support/slackin/) diff --git a/deploy/crate-datasource/crate-logo.png b/deploy/crate-datasource/crate-logo.png new file mode 100755 index 0000000..22849e8 Binary files /dev/null and b/deploy/crate-datasource/crate-logo.png differ diff --git a/deploy/crate-datasource/dist/README.md b/deploy/crate-datasource/dist/README.md new file mode 100755 index 0000000..062e9b7 --- /dev/null +++ b/deploy/crate-datasource/dist/README.md @@ -0,0 +1,108 @@ +# Grafana Data Source Plugin for CrateDB + +[![Crate.io logo](https://raw.githubusercontent.com/raintank/crate-datasource/master/crate-logo.png)](https://crate.io) + + +## What Is CrateDB? +CrateDB is a SQL database that makes it simple to store and analyze +massive amounts of machine data in real-time. CrateDB customers have +reported improving predictive analytic query performance of machine +data by 20x more than MySQL, while reducing database hardware costs by +75%. + +Here’s how CrateDB makes this possible: + +- **Combining SQL & Search** into a single DBMS - allowing you to process any data structure...time series, geospatial, JSON, full-text, etc. +- **Distributed query innovations** - that deliver real-time SQL performance +- **An auto-scaling architecture** - grow CrateDB with less DBA expertise +- **Dynamic schemas, adhoc queries** - quickly adapt to data structure changes + +For these reasons and more, CrateDB is your perfect datasource for Grafana. + +## The CrateDB Datasource Plugin for Grafana + +### Features +Enables CrateDB clusters to act as data sources for your Grafana deployment, providing real-time analytical and time-series data with SQL. + +### Requirements +- **Grafana** > 3.x.x +- **CrateDB** - All stable versions are supported by this plugin + +### Setup +![](https://raw.githubusercontent.com/raintank/crate-datasource/master/src/img/crate-datasource-add-src.png) + + > The screenshot shows a connection to http://localhost:44200 which is a test database for the purpose of this tutorial. CrateDB's default binding is to http://localhost:4200. + +1. Click on the Grafana icon on the top left. +2. After the menu opened, you should see a link `Data Sources` below `Dashboards`. +3. Click `+ Add data source`. +4. Select `CrateDB` from the 'Type' dropdown. + +#### Cross-origin Resource Sharing (CORS) + +CrateDB supports [cross-origin resource sharing](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) and if Grafana is running on a different origin (e.g. another domain), it is required to configure CrateDB accordingly. For example by this is the minimum required configuration in your `crate.yml`: +``` +http.cors.enabled: true +http.cors.allow-origin: "http://mydomain.com" +``` +> Replace http://mydomain.com with the domain Grafana is running on, or use a "*" if it's OK to allow any domain to access CrateDB + +For further options look in [CrateDB's documentation](https://crate.io/docs/reference/en/latest/configuration.html#cross-origin-resource-sharing-cors) + +#### The CrateDB Data Source + +Name | Description +------------ | ------------- +Name | The data source name. +Default | Set this data source as default for new panels. + +##### HTTP Settings + +Name | Description +------------ | ------------- +Url | The URI to any node in your CrateDB cluster. +Access | Via Grafana backend (proxy) or directly from the browser (direct). +Basic Auth | Enable basic authentication (only available via NGINX proxy in CrateDB). +User | Not available in CrateDB. +Password | Not available in CrateDB. + +##### CrateDB Details + +These are specific settings for the CrateDB data source and it's required to set a fixed `schema`, `table`, and time series column per data source. + +Name | Description +------------ | ------------- +Schema | CrateDB schema to query from (defaults to `doc`). +Table | Table to retrieve the data from. Has to be available in the previously defined schema. +Time Column | Time series column, has to be of type `timestamp` in CrateDB. +Default grouping interval | The grouping resolution (can be changed by query). + +![](https://raw.githubusercontent.com/raintank/crate-datasource/master/src/img/crate-datasource-nonvalidation.png) + +> Grafana will not check (yet) if the `time column`, the `schema`, or the `table` exists. Be sure to double check these values to avoid running into problems later. + +### Querying CrateDB + +After adding a new dashboard and having the query editor open, define and run the queries you like - it's just like other SQL databases. For example we have added the [NYC yellow cab data set](http://www.nyc.gov/html/tlc/html/about/trip_record_data.shtml) in our cluster to show you something interesting! + +![](https://raw.githubusercontent.com/raintank/crate-datasource/master/src/img/crate-datasource-graph.png) + +> This graph shows the number of yellow cab pick ups between on a weekend in August 2013. + +### Debugging Queries + +Grafana runs queries almost immediately after change and it will also auto-complete columns or previous values. However, sometimes queries might still be invalid and Grafana will then show a small exclamation mark in the top corner of the graph. Clicking on it will give you the error message. + +![](https://raw.githubusercontent.com/raintank/crate-datasource/master/src/img/crate-datasource-error.png) + +The CrateDB data source for Grafana supports a great range of scalar functions and operators. To read more about them, install or scale a cluster, or even to contribute to Crate, please have a look at the [official Crate documentation](https://crate.io/docs) + +### License +- This plugins is made available under the terms of the [Apache License, Version 2.0](https://github.com/crate/crate-datasource/blob/master/LICENSE). + +## Getting Help + +- Read the CrateDB documentation [here](https://crate.io/docs) +- Issues with the Grafana plugin can be reported or discussed [here](https://github.com/raintank/crate-datasource/issues) +- Issues with CrateDB can be reported or discussed [here](https://github.com/crate/crate/issues) +- Join the CrateDB Community Slack channel [here](https://crate.io/docs/support/slackin/) diff --git a/deploy/crate-datasource/dist/config_ctrl.d.ts b/deploy/crate-datasource/dist/config_ctrl.d.ts new file mode 100755 index 0000000..f88c36f --- /dev/null +++ b/deploy/crate-datasource/dist/config_ctrl.d.ts @@ -0,0 +1,7 @@ +/// +export declare class CrateConfigCtrl { + static templateUrl: string; + current: any; + timeIntervals: any[]; + constructor($scope: any); +} diff --git a/deploy/crate-datasource/dist/config_ctrl.js b/deploy/crate-datasource/dist/config_ctrl.js new file mode 100755 index 0000000..fcc62d4 --- /dev/null +++ b/deploy/crate-datasource/dist/config_ctrl.js @@ -0,0 +1,30 @@ +/// +System.register([], function(exports_1) { + var CrateConfigCtrl; + return { + setters:[], + execute: function() { + CrateConfigCtrl = (function () { + function CrateConfigCtrl($scope) { + this.timeIntervals = [ + { name: 'Auto', value: 'auto' }, + { name: 'Auto (Grafana)', value: 'auto_gf' }, + { name: 'Second', value: 'second' }, + { name: 'Minute', value: 'minute' }, + { name: 'Hour', value: 'hour' }, + { name: 'Day', value: 'day' }, + { name: 'Week', value: 'week' }, + { name: 'Month', value: 'month' }, + { name: 'Quarter', value: 'quarter' }, + { name: 'Year', value: 'year' } + ]; + this.current.jsonData.timeInterval = this.current.jsonData.timeInterval || this.timeIntervals[1].value; + } + CrateConfigCtrl.templateUrl = 'partials/config.html'; + return CrateConfigCtrl; + })(); + exports_1("CrateConfigCtrl", CrateConfigCtrl); + } + } +}); +//# sourceMappingURL=config_ctrl.js.map \ No newline at end of file diff --git a/deploy/crate-datasource/dist/config_ctrl.js.map b/deploy/crate-datasource/dist/config_ctrl.js.map new file mode 100755 index 0000000..f40350d --- /dev/null +++ b/deploy/crate-datasource/dist/config_ctrl.js.map @@ -0,0 +1 @@ +{"version":3,"file":"config_ctrl.js","sourceRoot":"","sources":["config_ctrl.ts"],"names":["CrateConfigCtrl","CrateConfigCtrl.constructor"],"mappings":"AAAA,8CAA8C;;;;;;YAK9C;gBAiBEA,yBAAYA,MAAMA;oBAblBC,kBAAaA,GAAUA;wBACrBA,EAACA,IAAIA,EAAEA,MAAMA,EAAKA,KAAKA,EAAEA,MAAMA,EAACA;wBAChCA,EAACA,IAAIA,EAAEA,gBAAgBA,EAAKA,KAAKA,EAAEA,SAASA,EAACA;wBAC7CA,EAACA,IAAIA,EAAEA,QAAQA,EAAGA,KAAKA,EAAEA,QAAQA,EAACA;wBAClCA,EAACA,IAAIA,EAAEA,QAAQA,EAAGA,KAAKA,EAAEA,QAAQA,EAACA;wBAClCA,EAACA,IAAIA,EAAEA,MAAMA,EAAKA,KAAKA,EAAEA,MAAMA,EAACA;wBAChCA,EAACA,IAAIA,EAAEA,KAAKA,EAAMA,KAAKA,EAAEA,KAAKA,EAACA;wBAC/BA,EAACA,IAAIA,EAAEA,MAAMA,EAAKA,KAAKA,EAAEA,MAAMA,EAACA;wBAChCA,EAACA,IAAIA,EAAEA,OAAOA,EAAIA,KAAKA,EAAEA,OAAOA,EAACA;wBACjCA,EAACA,IAAIA,EAAEA,SAASA,EAAEA,KAAKA,EAAEA,SAASA,EAACA;wBACnCA,EAACA,IAAIA,EAAEA,MAAMA,EAAKA,KAAKA,EAAEA,MAAMA,EAACA;qBACjCA,CAACA;oBAGAA,IAAIA,CAACA,OAAOA,CAACA,QAAQA,CAACA,YAAYA,GAAGA,IAAIA,CAACA,OAAOA,CAACA,QAAQA,CAACA,YAAYA,IAAIA,IAAIA,CAACA,aAAaA,CAACA,CAACA,CAACA,CAACA,KAAKA,CAACA;gBACzGA,CAACA;gBAlBMD,2BAAWA,GAAGA,sBAAsBA,CAACA;gBAmB9CA,sBAACA;YAADA,CAACA,AApBD,IAoBC;YApBD,6CAoBC,CAAA"} \ No newline at end of file diff --git a/deploy/crate-datasource/dist/config_ctrl.ts b/deploy/crate-datasource/dist/config_ctrl.ts new file mode 100755 index 0000000..21b5221 --- /dev/null +++ b/deploy/crate-datasource/dist/config_ctrl.ts @@ -0,0 +1,26 @@ +/// + +import angular from 'angular'; +import _ from 'lodash'; + +export class CrateConfigCtrl { + static templateUrl = 'partials/config.html'; + current: any; + + timeIntervals: any[] = [ + {name: 'Auto', value: 'auto'}, + {name: 'Auto (Grafana)', value: 'auto_gf'}, + {name: 'Second', value: 'second'}, + {name: 'Minute', value: 'minute'}, + {name: 'Hour', value: 'hour'}, + {name: 'Day', value: 'day'}, + {name: 'Week', value: 'week'}, + {name: 'Month', value: 'month'}, + {name: 'Quarter', value: 'quarter'}, + {name: 'Year', value: 'year'} + ]; + + constructor($scope) { + this.current.jsonData.timeInterval = this.current.jsonData.timeInterval || this.timeIntervals[1].value; + } +} diff --git a/deploy/crate-datasource/dist/datasource.d.ts b/deploy/crate-datasource/dist/datasource.d.ts new file mode 100755 index 0000000..47b08fa --- /dev/null +++ b/deploy/crate-datasource/dist/datasource.d.ts @@ -0,0 +1,47 @@ +/// +import { CrateQueryBuilder } from './query_builder'; +export declare class CrateDatasource { + private $q; + private backendSrv; + private templateSrv; + private timeSrv; + type: string; + url: string; + name: string; + basicAuth: string; + withCredentials: boolean; + schema: string; + table: string; + defaultTimeColumn: string; + defaultGroupInterval: string; + checkQuerySource: boolean; + queryBuilder: CrateQueryBuilder; + CRATE_ROWS_LIMIT: number; + constructor(instanceSettings: any, $q: any, backendSrv: any, templateSrv: any, timeSrv: any); + query(options: any): any; + /** + * Required. + * Checks datasource and returns Crate cluster name and version or + * error details. + */ + testDatasource(): any; + metricFindQuery(query: string): any; + annotationQuery(options: any): any; + transformAnnotationResponse(options: any, data: any): any[]; + getTimeFilter(timeFrom: any, timeTo: any): string; + getTagKeys(options: any): any; + getTagValues(options: any): any; + setScopedVars(scopedVars: any): any; + /** + * Sends SQL query to Crate and returns result. + * @param {string} query SQL query string + * @param {any[]} args Optional query arguments + * @return + */ + _sql_query(query: string, args?: any[]): any; + checkSQLSource(query: any): void; + _request(method: string, url: string, data?: any): any; + _get(url?: string): any; + _post(url: string, data?: any): any; +} +export declare function convertToCrateInterval(grafanaInterval: any): any; diff --git a/deploy/crate-datasource/dist/datasource.js b/deploy/crate-datasource/dist/datasource.js new file mode 100755 index 0000000..332e1bd --- /dev/null +++ b/deploy/crate-datasource/dist/datasource.js @@ -0,0 +1,389 @@ +/// +System.register(['lodash', 'app/core/utils/datemath', './query_builder', './response_handler'], function(exports_1) { + var lodash_1, dateMath, query_builder_1, response_handler_1; + var CrateDatasource; + // Special value formatter for Crate. + function formatCrateValue(value) { + if (typeof value === 'string') { + return wrapWithQuotes(value); + } + else { + return value.map(function (v) { return wrapWithQuotes(v); }).join(', '); + } + } + function wrapWithQuotes(value) { + if (!isNaN(value) || + value.indexOf("'") != -1 || + value.indexOf('"') != -1) { + return value; + } + else { + return "'" + value + "'"; + } + } + function convertToCrateInterval(grafanaInterval) { + var crateIntervals = [ + { shorthand: 's', value: 'second' }, + { shorthand: 'm', value: 'minute' }, + { shorthand: 'h', value: 'hour' }, + { shorthand: 'd', value: 'day' }, + { shorthand: 'w', value: 'week' }, + { shorthand: 'M', value: 'month' }, + { shorthand: 'y', value: 'year' } + ]; + var intervalRegex = /([\d]*)([smhdwMy])/; + var parsedInterval = intervalRegex.exec(grafanaInterval); + var value = Number(parsedInterval[1]); + var unit = parsedInterval[2]; + var crateInterval = lodash_1["default"].find(crateIntervals, { 'shorthand': unit }); + return crateInterval ? crateInterval.value : undefined; + } + exports_1("convertToCrateInterval", convertToCrateInterval); + function crateToMsInterval(crateInterval) { + var intervals_s = { + 'year': 60 * 60 * 24 * 30 * 12, + 'quarter': 60 * 60 * 24 * 30 * 3, + 'month': 60 * 60 * 24 * 30, + 'week': 60 * 60 * 24 * 7, + 'day': 60 * 60 * 24, + 'hour': 60 * 60, + 'minute': 60, + 'second': 1 + }; + if (intervals_s[crateInterval]) { + return intervals_s[crateInterval] * 1000; // Return ms + } + else { + return undefined; + } + } + function getMinCrateInterval(ms) { + var seconds = ms / 1000; + if (seconds > 60 * 60 * 24 * 30 * 3) + return 'year'; + else if (seconds > 60 * 60 * 24 * 30) + return 'quarter'; + else if (seconds > 60 * 60 * 24 * 7) + return 'month'; + else if (seconds > 60 * 60 * 24) + return 'week'; + else if (seconds > 60 * 60) + return 'day'; + else if (seconds > 60) + return 'hour'; + else if (seconds > 1) + return 'second'; + else + return 'second'; + } + return { + setters:[ + function (lodash_1_1) { + lodash_1 = lodash_1_1; + }, + function (dateMath_1) { + dateMath = dateMath_1; + }, + function (query_builder_1_1) { + query_builder_1 = query_builder_1_1; + }, + function (response_handler_1_1) { + response_handler_1 = response_handler_1_1; + }], + execute: function() { + CrateDatasource = (function () { + function CrateDatasource(instanceSettings, $q, backendSrv, templateSrv, timeSrv) { + this.$q = $q; + this.backendSrv = backendSrv; + this.templateSrv = templateSrv; + this.timeSrv = timeSrv; + this.type = instanceSettings.type; + this.url = instanceSettings.url; + this.name = instanceSettings.name; + this.basicAuth = instanceSettings.basicAuth; + this.withCredentials = instanceSettings.withCredentials; + this.schema = instanceSettings.jsonData.schema; + this.table = instanceSettings.jsonData.table; + this.defaultTimeColumn = instanceSettings.jsonData.timeColumn; + this.defaultGroupInterval = instanceSettings.jsonData.timeInterval; + this.checkQuerySource = instanceSettings.jsonData.checkQuerySource; + this.$q = $q; + this.backendSrv = backendSrv; + this.templateSrv = templateSrv; + this.timeSrv = timeSrv; + this.queryBuilder = new query_builder_1.CrateQueryBuilder(this.schema, this.table, this.defaultTimeColumn, this.defaultGroupInterval, this.templateSrv); + this.CRATE_ROWS_LIMIT = 10000; + } + // Called once per panel (graph) + CrateDatasource.prototype.query = function (options) { + var _this = this; + var timeFrom = Math.ceil(dateMath.parse(options.range.from)); + var timeTo = Math.ceil(dateMath.parse(options.range.to)); + var timeFilter = this.getTimeFilter(timeFrom, timeTo); + var scopedVars = this.setScopedVars(options.scopedVars); + var queries = lodash_1["default"].map(options.targets, function (target) { + if (target.hide || (target.rawQuery && !target.query)) { + return []; + } + var query; + var rawAggQuery; + var queryTarget, rawAggTarget; + var getQuery; + var getRawAggQuery; + var getRawAggInterval; + var adhocFilters = _this.templateSrv.getAdhocFilters(_this.name); + if (target.rawQuery) { + query = target.query; + } + else { + var minInterval = Math.ceil((timeTo - timeFrom) / _this.CRATE_ROWS_LIMIT); + var maxLimit = timeTo - timeFrom; + var interval; + if (target.timeInterval === 'auto') { + interval = getMinCrateInterval(options.intervalMs); + } + else if (target.timeInterval === 'auto_gf') { + // Use intervalMs for panel, provided by Grafana + interval = options.intervalMs; + } + else { + interval = target.timeInterval; + } + // Split target into two queries (with aggs and raw data) + query = _this.queryBuilder.buildAggQuery(target, interval, adhocFilters); + queryTarget = lodash_1["default"].cloneDeep(target); + queryTarget.metricAggs = query_builder_1.getNotRawAggs(queryTarget.metricAggs); + rawAggQuery = _this.queryBuilder.buildRawAggQuery(target, 0, adhocFilters, maxLimit); + rawAggQuery = _this.templateSrv.replace(rawAggQuery, scopedVars, formatCrateValue); + rawAggTarget = lodash_1["default"].cloneDeep(target); + rawAggTarget.metricAggs = query_builder_1.getRawAggs(rawAggTarget.metricAggs); + } + query = _this.templateSrv.replace(query, scopedVars, formatCrateValue); + var queries = [ + { query: query, target: queryTarget }, + { query: rawAggQuery, target: rawAggTarget } + ]; + queries = lodash_1["default"].filter(queries, function (q) { + return q.query; + }); + return lodash_1["default"].map(queries, function (q) { + return _this._sql_query(q.query, [timeFrom, timeTo]) + .then(function (result) { + if (q.target) { + return response_handler_1["default"](q.target, result); + } + else { + return response_handler_1["default"](target, result); + } + }); + }); + }); + return this.$q.all(lodash_1["default"].flattenDepth(queries, 2)).then(function (result) { + return { + data: lodash_1["default"].flatten(result) + }; + }); + }; + /** + * Required. + * Checks datasource and returns Crate cluster name and version or + * error details. + */ + CrateDatasource.prototype.testDatasource = function () { + return this._get() + .then(function (response) { + if (response.$$status === 200) { + return { + status: "success", + message: "Cluster: " + response.cluster_name + + ", version: " + response.version.number, + title: "Success" + }; + } + }) + .catch(function (error) { + var message = error.statusText ? error.statusText + ': ' : ''; + if (error.data && error.data.error) { + message += error.data.error; + } + else if (error.data) { + message += error.data; + } + else { + message = "Can't connect to Crate instance"; + } + return { + status: "error", + message: message, + title: "Error" + }; + }); + }; + CrateDatasource.prototype.metricFindQuery = function (query) { + if (!query) { + return this.$q.when([]); + } + query = this.templateSrv.replace(query, null, formatCrateValue); + return this._sql_query(query).then(function (result) { + return lodash_1["default"].map(lodash_1["default"].flatten(result.rows), function (row) { + return { + text: row.toString(), + value: row + }; + }); + }); + }; + CrateDatasource.prototype.annotationQuery = function (options) { + var _this = this; + if (!options.annotation.query) { + return this.$q.reject({ + message: 'Query missing in annotation definition' + }); + } + var timeFrom = Math.ceil(dateMath.parse(options.range.from)); + var timeTo = Math.ceil(dateMath.parse(options.range.to)); + var timeFilter = this.getTimeFilter(timeFrom, timeTo); + var query = options.annotation.query.replace('$timeFilter', timeFilter); + query = this.templateSrv.replace(query, null, 'regex'); + var data = { + "stmt": query, + "args": [] + }; + return this._post('_sql', data).then(function (data) { + if (!data || !data.rows || !data.rows[0]) { + throw { message: 'No results' }; + } + return _this.transformAnnotationResponse(options, data); + }); + }; + CrateDatasource.prototype.transformAnnotationResponse = function (options, data) { + var list = []; + var titleCol = null; + var timeCol = null; + var tagsCol = []; + var textCol = null; + lodash_1["default"].each(data.cols, function (column, index) { + if (column === 'time') { + timeCol = index; + return; + } + if (column === 'sequence_number') { + return; + } + if (!titleCol) { + titleCol = index; + } + if (column === options.annotation.titleColumn) { + titleCol = index; + return; + } + if (lodash_1["default"].includes((options.annotation.tagsColumn || '').replace(' ', '').split(','), column)) { + tagsCol.push(index); + return; + } + if (column === options.annotation.textColumn) { + textCol = index; + return; + } + }); + lodash_1["default"].each(data.rows, function (value) { + var data = { + annotation: options.annotation, + time: +new Date(value[timeCol]), + title: value[titleCol], + // Remove empty values, then split in different tags for comma separated values + tags: lodash_1["default"].flatten(tagsCol + .filter(function (t) { + return value[t]; + }) + .map(function (t) { + return value[t].split(','); + })), + text: value[textCol] + }; + list.push(data); + }); + return list; + }; + CrateDatasource.prototype.getTimeFilter = function (timeFrom, timeTo) { + return this.defaultTimeColumn + " >= '" + timeFrom + "' and " + this.defaultTimeColumn + " <= '" + timeTo + "'"; + }; + CrateDatasource.prototype.getTagKeys = function (options) { + var query = this.queryBuilder.getColumnsQuery(); + return this.metricFindQuery(query); + }; + CrateDatasource.prototype.getTagValues = function (options) { + var range = this.timeSrv.timeRange(); + var query = this.queryBuilder.getValuesQuery(options.key, this.CRATE_ROWS_LIMIT, range); + return this.metricFindQuery(query); + }; + CrateDatasource.prototype.setScopedVars = function (scopedVars) { + scopedVars.crate_schema = { text: this.schema, value: "\"" + this.schema + "\"" }; + scopedVars.crate_table = { text: this.table, value: "\"" + this.table + "\"" }; + var crate_source = "\"" + this.schema + "\".\"" + this.table + "\""; + scopedVars.crate_source = { text: crate_source, value: crate_source }; + return scopedVars; + }; + /** + * Sends SQL query to Crate and returns result. + * @param {string} query SQL query string + * @param {any[]} args Optional query arguments + * @return + */ + CrateDatasource.prototype._sql_query = function (query, args) { + if (args === void 0) { args = []; } + var data = { + "stmt": query, + "args": args + }; + if (this.checkQuerySource) { + // Checks schema and table and throw error if it different from configured in data source + this.checkSQLSource(query); + } + return this._post('_sql', data); + }; + CrateDatasource.prototype.checkSQLSource = function (query) { + var source_pattern = /.*[Ff][Rr][Oo][Mm]\s"?([^\.\s\"]*)"?\.?"?([^\.\s\"]*)"?/; + var match = query.match(source_pattern); + var schema = match[1]; + var table = match[2]; + if (schema !== this.schema || table !== this.table) { + throw { message: "Schema and table should be " + this.schema + "." + this.table }; + } + }; + CrateDatasource.prototype._request = function (method, url, data) { + var options = { + url: this.url + "/" + url, + method: method, + data: data, + headers: { + "Content-Type": "application/json" + } + }; + if (this.basicAuth || this.withCredentials) { + options["withCredentials"] = true; + } + if (this.basicAuth) { + options.headers["Authorization"] = this.basicAuth; + } + return this.backendSrv.datasourceRequest(options) + .then(function (response) { + response.data.$$status = response.status; + response.data.$$config = response.config; + return response.data; + }); + }; + CrateDatasource.prototype._get = function (url) { + if (url === void 0) { url = ""; } + return this._request('GET', url); + }; + CrateDatasource.prototype._post = function (url, data) { + return this._request('POST', url, data); + }; + return CrateDatasource; + })(); + exports_1("CrateDatasource", CrateDatasource); + } + } +}); +//# sourceMappingURL=datasource.js.map \ No newline at end of file diff --git a/deploy/crate-datasource/dist/datasource.js.map b/deploy/crate-datasource/dist/datasource.js.map new file mode 100755 index 0000000..fe572ea --- /dev/null +++ b/deploy/crate-datasource/dist/datasource.js.map @@ -0,0 +1 @@ +{"version":3,"file":"datasource.js","sourceRoot":"","sources":["datasource.ts"],"names":["formatCrateValue","wrapWithQuotes","convertToCrateInterval","crateToMsInterval","getMinCrateInterval","CrateDatasource","CrateDatasource.constructor","CrateDatasource.query","CrateDatasource.testDatasource","CrateDatasource.metricFindQuery","CrateDatasource.annotationQuery","CrateDatasource.transformAnnotationResponse","CrateDatasource.getTimeFilter","CrateDatasource.getTagKeys","CrateDatasource.getTagValues","CrateDatasource.setScopedVars","CrateDatasource._sql_query","CrateDatasource.checkSQLSource","CrateDatasource._request","CrateDatasource._get","CrateDatasource._post"],"mappings":"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AMA,CAACA,CAACA,CAACA,KAAKA,CAACA;wBACjBA,CAACA,CAACA,CAACA;wBAEHA,MAAMA,CAACA,mBAACA,CAACA,GAAGA,CAACA,OAAOA,EAAEA,UAAAA,CAACA;4BACrBA,MAAMA,CAACA,KAAIA,CAACA,UAAUA,CAACA,CAACA,CAACA,KAAKA,EAAEA,CAACA,QAAQA,EAAEA,MAAMA,CAACA,CAACA;iCAChDA,IAAIA,CAACA,UAAAA,MAAMA;gCACVA,EAAEA,CAACA,CAACA,CAACA,CAACA,MAAMA,CAACA,CAACA,CAACA;oCACbA,MAAMA,CAACA,6BAAcA,CAACA,CAACA,CAACA,MAAMA,EAAEA,MAAMA,CAACA,CAACA;gCAC1CA,CAACA;gCAACA,IAAIA,CAACA,CAACA;oCACNA,MAAMA,CAACA,6BAAcA,CAACA,MAAMA,EAAEA,MAAMA,CAACA,CAACA;gCACxCA,CAACA;4BACHA,CAACA,CAACA,CAACA;wBACPA,CAACA,CAACA,CAAAA;oBACJA,CAACA,CAACA,CAACA;oBACHA,MAAMA,CAACA,IAAIA,CAACA,EAAEA,CAACA,GAAGA,CAACA,mBAACA,CAACA,YAAYA,CAACA,OAAOA,EAAEA,CAACA,CAACA,CAACA,CAACA,IAAIA,CAACA,UAAAA,MAAMA;wBACxDA,MAAMA,CAACA;4BACLA,IAAIA,EAAEA,mBAACA,CAACA,OAAOA,CAACA,MAAMA,CAACA;yBACxBA,CAACA;oBACJA,CAACA,CAACA,CAACA;gBACLA,CAACA;gBAEDF;;;;mBAIGA;gBACHA,wCAAcA,GAAdA;oBACEG,MAAMA,CAACA,IAAIA,CAACA,IAAIA,EAAEA;yBACjBA,IAAIA,CAACA,UAAAA,QAAQA;wBACZA,EAAEA,CAACA,CAACA,QAAQA,CAACA,QAAQA,KAAKA,GAAGA,CAACA,CAACA,CAACA;4BAC9BA,MAAMA,CAACA;gCACLA,MAAMA,EAAEA,SAASA;gCACjBA,OAAOA,EAAEA,WAAWA,GAAGA,QAAQA,CAACA,YAAYA;oCAC1CA,aAAaA,GAAGA,QAAQA,CAACA,OAAOA,CAACA,MAAMA;gCACzCA,KAAKA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"} \ No newline at end of file diff --git a/deploy/crate-datasource/dist/datasource.ts b/deploy/crate-datasource/dist/datasource.ts new file mode 100755 index 0000000..ef777e4 --- /dev/null +++ b/deploy/crate-datasource/dist/datasource.ts @@ -0,0 +1,425 @@ +/// + +import _ from 'lodash'; +import * as dateMath from 'app/core/utils/datemath'; +import moment from 'moment'; +import {CrateQueryBuilder, getEnabledAggs, getRawAggs, getNotRawAggs} from './query_builder'; +import handleResponse from './response_handler'; + +export class CrateDatasource { + type: string; + url: string; + name: string; + basicAuth: string; + withCredentials: boolean; + schema: string; + table: string; + defaultTimeColumn: string; + defaultGroupInterval: string; + checkQuerySource: boolean; + queryBuilder: CrateQueryBuilder; + CRATE_ROWS_LIMIT: number; + + + constructor(instanceSettings, + private $q, + private backendSrv, + private templateSrv, + private timeSrv) { + + this.type = instanceSettings.type; + this.url = instanceSettings.url; + this.name = instanceSettings.name; + this.basicAuth = instanceSettings.basicAuth; + this.withCredentials = instanceSettings.withCredentials; + this.schema = instanceSettings.jsonData.schema; + this.table = instanceSettings.jsonData.table; + this.defaultTimeColumn = instanceSettings.jsonData.timeColumn; + this.defaultGroupInterval = instanceSettings.jsonData.timeInterval; + this.checkQuerySource = instanceSettings.jsonData.checkQuerySource; + + this.$q = $q; + this.backendSrv = backendSrv; + this.templateSrv = templateSrv; + this.timeSrv = timeSrv; + + this.queryBuilder = new CrateQueryBuilder(this.schema, + this.table, + this.defaultTimeColumn, + this.defaultGroupInterval, + this.templateSrv); + + this.CRATE_ROWS_LIMIT = 10000; + } + + // Called once per panel (graph) + query(options) { + let timeFrom = Math.ceil(dateMath.parse(options.range.from)); + let timeTo = Math.ceil(dateMath.parse(options.range.to)); + let timeFilter = this.getTimeFilter(timeFrom, timeTo); + let scopedVars = this.setScopedVars(options.scopedVars); + + let queries = _.map(options.targets, target => { + if (target.hide || (target.rawQuery && !target.query)) { return []; } + + let query: string; + let rawAggQuery: string; + let queryTarget, rawAggTarget; + let getQuery: any; + let getRawAggQuery: any; + let getRawAggInterval: any; + let adhocFilters = this.templateSrv.getAdhocFilters(this.name); + + if (target.rawQuery) { + query = target.query; + } else { + let minInterval = Math.ceil((timeTo - timeFrom) / this.CRATE_ROWS_LIMIT); + let maxLimit = timeTo - timeFrom; + let interval; + + if (target.timeInterval === 'auto') { + interval = getMinCrateInterval(options.intervalMs); + } else if (target.timeInterval === 'auto_gf') { + // Use intervalMs for panel, provided by Grafana + interval = options.intervalMs; + } else { + interval = target.timeInterval; + } + + // Split target into two queries (with aggs and raw data) + query = this.queryBuilder.buildAggQuery(target, interval, adhocFilters); + queryTarget = _.cloneDeep(target); + queryTarget.metricAggs = getNotRawAggs(queryTarget.metricAggs); + + rawAggQuery = this.queryBuilder.buildRawAggQuery(target, 0, adhocFilters, maxLimit); + rawAggQuery = this.templateSrv.replace(rawAggQuery, scopedVars, formatCrateValue); + rawAggTarget = _.cloneDeep(target); + rawAggTarget.metricAggs = getRawAggs(rawAggTarget.metricAggs); + } + + query = this.templateSrv.replace(query, scopedVars, formatCrateValue); + + let queries = [ + {query: query, target: queryTarget}, + {query: rawAggQuery, target: rawAggTarget} + ]; + queries = _.filter(queries, q => { + return q.query; + }); + + return _.map(queries, q => { + return this._sql_query(q.query, [timeFrom, timeTo]) + .then(result => { + if (q.target) { + return handleResponse(q.target, result); + } else { + return handleResponse(target, result); + } + }); + }) + }); + return this.$q.all(_.flattenDepth(queries, 2)).then(result => { + return { + data: _.flatten(result) + }; + }); + } + + /** + * Required. + * Checks datasource and returns Crate cluster name and version or + * error details. + */ + testDatasource() { + return this._get() + .then(response => { + if (response.$$status === 200) { + return { + status: "success", + message: "Cluster: " + response.cluster_name + + ", version: " + response.version.number, + title: "Success" + }; + } + }) + .catch(error => { + let message = error.statusText ? error.statusText + ': ' : ''; + if (error.data && error.data.error) { + message += error.data.error; + } else if (error.data) { + message += error.data; + } else { + message = "Can't connect to Crate instance"; + } + return { + status: "error", + message: message, + title: "Error" + }; + }); + } + + metricFindQuery(query: string) { + if (!query) { + return this.$q.when([]); + } + + query = this.templateSrv.replace(query, null, formatCrateValue); + return this._sql_query(query).then(result => { + return _.map(_.flatten(result.rows), row => { + return { + text: row.toString(), + value: row + }; + }); + }); + } + + annotationQuery(options) { + if (!options.annotation.query) { + return this.$q.reject({ + message: 'Query missing in annotation definition', + }); + } + let timeFrom = Math.ceil(dateMath.parse(options.range.from)); + let timeTo = Math.ceil(dateMath.parse(options.range.to)); + var timeFilter = this.getTimeFilter(timeFrom, timeTo); + var query = options.annotation.query.replace('$timeFilter', timeFilter); + query = this.templateSrv.replace(query, null, 'regex'); + + let data = { + "stmt": query, + "args": [] + }; + + return this._post('_sql', data).then(data => { + if (!data || !data.rows || !data.rows[0]) { + throw { message: 'No results' }; + } + return this.transformAnnotationResponse(options, data); + }); + } + + transformAnnotationResponse(options, data){ + var list = []; + var titleCol = null; + var timeCol = null; + var tagsCol = []; + var textCol = null; + + _.each(data.cols, (column, index) => { + if (column === 'time') { + timeCol = index; + return; + } + if (column === 'sequence_number') { + return; + } + if (!titleCol) { + titleCol = index; + } + if (column === options.annotation.titleColumn) { + titleCol = index; + return; + } + if (_.includes((options.annotation.tagsColumn || '').replace(' ', '').split(','), column)) { + tagsCol.push(index); + return; + } + if (column === options.annotation.textColumn) { + textCol = index; + return; + } + }); + + + + _.each(data.rows, value => { + var data = { + annotation: options.annotation, + time: +new Date(value[timeCol]), + title: value[titleCol], + // Remove empty values, then split in different tags for comma separated values + tags: _.flatten( + tagsCol + .filter(function(t) { + return value[t]; + }) + .map(function(t) { + return value[t].split(','); + }) + ), + text: value[textCol], + }; + + list.push(data); + }); + + return list; + + } + + getTimeFilter(timeFrom, timeTo) { + return this.defaultTimeColumn + " >= '" + timeFrom + "' and " + this.defaultTimeColumn + " <= '" + timeTo + "'"; + } + + getTagKeys(options) { + let query = this.queryBuilder.getColumnsQuery(); + return this.metricFindQuery(query); + } + + getTagValues(options) { + let range = this.timeSrv.timeRange(); + let query = this.queryBuilder.getValuesQuery(options.key, this.CRATE_ROWS_LIMIT, range); + return this.metricFindQuery(query); + } + + setScopedVars(scopedVars) { + scopedVars.crate_schema = {text: this.schema, value: `"${this.schema}"`}; + scopedVars.crate_table = {text: this.table, value: `"${this.table}"`}; + + let crate_source = `"${this.schema}"."${this.table}"`; + scopedVars.crate_source = {text: crate_source, value: crate_source}; + + return scopedVars; + } + + /** + * Sends SQL query to Crate and returns result. + * @param {string} query SQL query string + * @param {any[]} args Optional query arguments + * @return + */ + _sql_query(query: string, args: any[] = []) { + let data = { + "stmt": query, + "args": args + }; + + if (this.checkQuerySource) { + // Checks schema and table and throw error if it different from configured in data source + this.checkSQLSource(query); + } + + return this._post('_sql', data); + } + + checkSQLSource(query) { + let source_pattern = /.*[Ff][Rr][Oo][Mm]\s"?([^\.\s\"]*)"?\.?"?([^\.\s\"]*)"?/; + let match = query.match(source_pattern); + let schema = match[1]; + let table = match[2]; + if (schema !== this.schema || table !== this.table) { + throw { message: `Schema and table should be ${this.schema}.${this.table}` }; + } + } + + _request(method: string, url: string, data?: any) { + let options = { + url: this.url + "/" + url, + method: method, + data: data, + headers: { + "Content-Type": "application/json" + } + }; + + if (this.basicAuth || this.withCredentials) { + options["withCredentials"] = true; + } + if (this.basicAuth) { + options.headers["Authorization"] = this.basicAuth; + } + + return this.backendSrv.datasourceRequest(options) + .then(response => { + response.data.$$status = response.status; + response.data.$$config = response.config; + return response.data; + }); + } + + _get(url = "") { + return this._request('GET', url); + } + + _post(url: string, data?: any) { + return this._request('POST', url, data); + } +} + +// Special value formatter for Crate. +function formatCrateValue(value) { + if (typeof value === 'string') { + return wrapWithQuotes(value); + } else { + return value.map(v => wrapWithQuotes(v)).join(', '); + } +} + +function wrapWithQuotes(value) { + if (!isNaN(value) || + value.indexOf("'") != -1 || + value.indexOf('"') != -1) { + return value; + } else { + return "'" + value + "'"; + } +} + +export function convertToCrateInterval(grafanaInterval) { + let crateIntervals = [ + {shorthand: 's', value: 'second'}, + {shorthand: 'm', value: 'minute'}, + {shorthand: 'h', value: 'hour'}, + {shorthand: 'd', value: 'day'}, + {shorthand: 'w', value: 'week'}, + {shorthand: 'M', value: 'month'}, + {shorthand: 'y', value: 'year'} + ]; + let intervalRegex = /([\d]*)([smhdwMy])/; + let parsedInterval = intervalRegex.exec(grafanaInterval); + let value = Number(parsedInterval[1]); + let unit = parsedInterval[2]; + let crateInterval = _.find(crateIntervals, {'shorthand': unit}); + return crateInterval ? crateInterval.value : undefined; +} + +function crateToMsInterval(crateInterval: string) { + let intervals_s = { + 'year': 60 * 60 * 24 * 30 * 12, + 'quarter': 60 * 60 * 24 * 30 * 3, + 'month': 60 * 60 * 24 * 30, + 'week': 60 * 60 * 24 * 7, + 'day': 60 * 60 * 24, + 'hour': 60 * 60, + 'minute': 60, + 'second': 1 + }; + + if (intervals_s[crateInterval]) { + return intervals_s[crateInterval] * 1000; // Return ms + } else { + return undefined; + } +} + +function getMinCrateInterval(ms) { + let seconds = ms / 1000; + if (seconds > 60 * 60 * 24 * 30 * 3) + return 'year'; + else if (seconds > 60 * 60 * 24 * 30) // TODO: check defenition of month interval + return 'quarter'; + else if (seconds > 60 * 60 * 24 * 7) + return 'month'; + else if (seconds > 60 * 60 * 24) + return 'week'; + else if (seconds > 60 * 60) + return 'day'; + else if (seconds > 60) + return 'hour'; + else if (seconds > 1) + return 'second'; + else + return 'second'; +} diff --git a/deploy/crate-datasource/dist/img/crate-datasource-add-src.png b/deploy/crate-datasource/dist/img/crate-datasource-add-src.png new file mode 100755 index 0000000..0d2c4e4 Binary files /dev/null and b/deploy/crate-datasource/dist/img/crate-datasource-add-src.png differ diff --git a/deploy/crate-datasource/dist/img/crate-datasource-error.png b/deploy/crate-datasource/dist/img/crate-datasource-error.png new file mode 100755 index 0000000..40f9a8b Binary files /dev/null and b/deploy/crate-datasource/dist/img/crate-datasource-error.png differ diff --git a/deploy/crate-datasource/dist/img/crate-datasource-graph.png b/deploy/crate-datasource/dist/img/crate-datasource-graph.png new file mode 100755 index 0000000..6d7b735 Binary files /dev/null and b/deploy/crate-datasource/dist/img/crate-datasource-graph.png differ diff --git a/deploy/crate-datasource/dist/img/crate-datasource-nonvalidation.png b/deploy/crate-datasource/dist/img/crate-datasource-nonvalidation.png new file mode 100755 index 0000000..3fade94 Binary files /dev/null and b/deploy/crate-datasource/dist/img/crate-datasource-nonvalidation.png differ diff --git a/deploy/crate-datasource/dist/img/crate_logo.png b/deploy/crate-datasource/dist/img/crate_logo.png new file mode 100755 index 0000000..0a34a15 Binary files /dev/null and b/deploy/crate-datasource/dist/img/crate_logo.png differ diff --git a/deploy/crate-datasource/dist/module.d.ts b/deploy/crate-datasource/dist/module.d.ts new file mode 100755 index 0000000..c844c58 --- /dev/null +++ b/deploy/crate-datasource/dist/module.d.ts @@ -0,0 +1,10 @@ +import { CrateDatasource } from './datasource'; +import { CrateDatasourceQueryCtrl } from './query_ctrl'; +import { CrateConfigCtrl } from './config_ctrl'; +declare class CrateQueryOptionsCtrl { + static templateUrl: string; +} +declare class CrateAnnotationsQueryCtrl { + static templateUrl: string; +} +export { CrateDatasource as Datasource, CrateDatasourceQueryCtrl as QueryCtrl, CrateConfigCtrl as ConfigCtrl, CrateQueryOptionsCtrl as QueryOptionsCtrl, CrateAnnotationsQueryCtrl as AnnotationsQueryCtrl }; diff --git a/deploy/crate-datasource/dist/module.js b/deploy/crate-datasource/dist/module.js new file mode 100755 index 0000000..73c24dc --- /dev/null +++ b/deploy/crate-datasource/dist/module.js @@ -0,0 +1,36 @@ +System.register(['./datasource', './query_ctrl', './config_ctrl'], function(exports_1) { + var datasource_1, query_ctrl_1, config_ctrl_1; + var CrateQueryOptionsCtrl, CrateAnnotationsQueryCtrl; + return { + setters:[ + function (datasource_1_1) { + datasource_1 = datasource_1_1; + }, + function (query_ctrl_1_1) { + query_ctrl_1 = query_ctrl_1_1; + }, + function (config_ctrl_1_1) { + config_ctrl_1 = config_ctrl_1_1; + }], + execute: function() { + CrateQueryOptionsCtrl = (function () { + function CrateQueryOptionsCtrl() { + } + CrateQueryOptionsCtrl.templateUrl = 'partials/query.options.html'; + return CrateQueryOptionsCtrl; + })(); + CrateAnnotationsQueryCtrl = (function () { + function CrateAnnotationsQueryCtrl() { + } + CrateAnnotationsQueryCtrl.templateUrl = 'partials/annotations.editor.html'; + return CrateAnnotationsQueryCtrl; + })(); + exports_1("Datasource", datasource_1.CrateDatasource); + exports_1("QueryCtrl", query_ctrl_1.CrateDatasourceQueryCtrl); + exports_1("ConfigCtrl", config_ctrl_1.CrateConfigCtrl); + exports_1("QueryOptionsCtrl", CrateQueryOptionsCtrl); + exports_1("AnnotationsQueryCtrl", CrateAnnotationsQueryCtrl); + } + } +}); +//# sourceMappingURL=module.js.map \ No newline at end of file diff --git a/deploy/crate-datasource/dist/module.js.map b/deploy/crate-datasource/dist/module.js.map new file mode 100755 index 0000000..b98c4b4 --- /dev/null +++ b/deploy/crate-datasource/dist/module.js.map @@ -0,0 +1 @@ +{"version":3,"file":"module.js","sourceRoot":"","sources":["module.ts"],"names":["CrateQueryOptionsCtrl","CrateQueryOptionsCtrl.constructor","CrateAnnotationsQueryCtrl","CrateAnnotationsQueryCtrl.constructor"],"mappings":";;;;;;;;;;;;;;;YAIA;gBAAAA;gBAEAC,CAACA;gBADQD,iCAAWA,GAAGA,6BAA6BA,CAACA;gBACrDA,4BAACA;YAADA,CAACA,AAFD,IAEC;YAED;gBAAAE;gBAEAC,CAACA;gBADQD,qCAAWA,GAAGA,kCAAkCA,CAACA;gBAC1DA,gCAACA;YAADA,CAACA,AAFD,IAEC;YAGoB,qDAAU;YACD,6DAAS;YAClB,sDAAU;YACJ,oDAAgB;YACZ,4DAAoB"} \ No newline at end of file diff --git a/deploy/crate-datasource/dist/module.ts b/deploy/crate-datasource/dist/module.ts new file mode 100755 index 0000000..b1b9b40 --- /dev/null +++ b/deploy/crate-datasource/dist/module.ts @@ -0,0 +1,19 @@ +import {CrateDatasource} from './datasource'; +import {CrateDatasourceQueryCtrl} from './query_ctrl'; +import {CrateConfigCtrl} from './config_ctrl'; + +class CrateQueryOptionsCtrl { + static templateUrl = 'partials/query.options.html'; +} + +class CrateAnnotationsQueryCtrl { + static templateUrl = 'partials/annotations.editor.html'; +} + +export { + CrateDatasource as Datasource, + CrateDatasourceQueryCtrl as QueryCtrl, + CrateConfigCtrl as ConfigCtrl, + CrateQueryOptionsCtrl as QueryOptionsCtrl, + CrateAnnotationsQueryCtrl as AnnotationsQueryCtrl, +}; diff --git a/deploy/crate-datasource/dist/partials/annotations.editor.html b/deploy/crate-datasource/dist/partials/annotations.editor.html new file mode 100755 index 0000000..81f3baf --- /dev/null +++ b/deploy/crate-datasource/dist/partials/annotations.editor.html @@ -0,0 +1,24 @@ + +
+
+ +
+
+ +
Field mappings If your query returns more than one field you need to specify the column names below. An annotation event is composed of a title, tags, and an additional text field.
+
+
+
+ Title + +
+
+ Text + +
+
+ Tags + +
+
+
diff --git a/deploy/crate-datasource/dist/partials/config.html b/deploy/crate-datasource/dist/partials/config.html new file mode 100755 index 0000000..60a7192 --- /dev/null +++ b/deploy/crate-datasource/dist/partials/config.html @@ -0,0 +1,50 @@ + + + +

Crate details

+ +
+
+
+ Schema + + +
+ +
+ Table + + +
+
+ + + + +
+ Time column + + +
+ +
+ Default grouping interval + +
+ +
diff --git a/deploy/crate-datasource/dist/partials/query.editor.html b/deploy/crate-datasource/dist/partials/query.editor.html new file mode 100755 index 0000000..f5d3c87 --- /dev/null +++ b/deploy/crate-datasource/dist/partials/query.editor.html @@ -0,0 +1,149 @@ + + + +
+ + +
+ + +
+ +
+
+ +
+
+ +
+ +
+ +
+
+ + +
+ +
+
+
+
+ +
+ +
+ +
+ +
+ + + + +
+ +
+ + + +
+ + + +
+ + +
+
+ +
+
+ +
+
+ + +
+
+ + + +
+
+
+
+
+ +
+
+ Group By time Interval + +
+
+ +
+ +
+
+
+
+
+
+
+
diff --git a/deploy/crate-datasource/dist/partials/query.options.html b/deploy/crate-datasource/dist/partials/query.options.html new file mode 100755 index 0000000..e69de29 diff --git a/deploy/crate-datasource/dist/plugin.json b/deploy/crate-datasource/dist/plugin.json new file mode 100755 index 0000000..7396d85 --- /dev/null +++ b/deploy/crate-datasource/dist/plugin.json @@ -0,0 +1,36 @@ +{ + "name": "Crate", + "id": "crate-datasource", + "type": "datasource", + + "partials": { + "config": "public/app/plugins/datasource/crate/partials/config.html" + }, + + "metrics": true, + "annotations": true, + "alerting": true, + + "info": { + "description": "Crate SQL Database datasource", + "author": { + "name": "Crate.IO", + "url": "https://crate.io" + }, + "logos": { + "small": "img/crate_logo.png", + "large": "img/crate_logo.png" + }, + "links": [ + {"name": "GitHub", "url": "https://github.com/raintank/crate-datasource"}, + {"name": "MIT License", "url": "https://github.com/raintank/crate-datasource/blob/master/LICENSE"} + ], + "version": "0.5.2", + "updated": "2018-03-12" + }, + + "dependencies": { + "grafanaVersion": "3.x.x", + "plugins": [] + } +} diff --git a/deploy/crate-datasource/dist/query_builder.d.ts b/deploy/crate-datasource/dist/query_builder.d.ts new file mode 100755 index 0000000..c2a8104 --- /dev/null +++ b/deploy/crate-datasource/dist/query_builder.d.ts @@ -0,0 +1,40 @@ +/// +export declare class CrateQueryBuilder { + private templateSrv; + schema: string; + table: string; + defaultTimeColumn: string; + defaultGroupInterval: string; + constructor(schema: string, table: string, defaultTimeColumn: string, defaultGroupInterval: string, templateSrv: any); + /** + * Builds Crate SQL query from given target object. + * @param {any} target Target object. + * @param {number} groupInterval Interval for grouping values. + * @param {string} defaultAgg Default aggregation for values. + * @return {string} SQL query. + */ + build(target: any, groupInterval?: number, adhocFilters?: any[], limit?: number, defaultAgg?: string): string; + buildAggQuery(target: any, groupInterval?: number, adhocFilters?: any[], limit?: number): string; + buildRawAggQuery(target: any, groupInterval?: number, adhocFilters?: any[], limit?: number): string; + renderAdhocFilters(filters: any): any; + /** + * Builds SQL query for getting available columns from table. + * @return {string} SQL query. + */ + getColumnsQuery(): string; + getNumericColumnsQuery(): string; + /** + * Builds SQL query for getting unique values for given column. + * @param {string} column Column name + * @param {number} limit Optional. Limit number returned values. + */ + getValuesQuery(column: string, limit?: number, timeRange?: any): string; + private renderMetricAggs(metricAggs, withAlias?); + private renderWhereClauses(whereClauses); + private containsVariable(str); +} +export declare function getSchemas(): string; +export declare function getTables(schema: any): string; +export declare function getEnabledAggs(metricAggs: any): any; +export declare function getRawAggs(metricAggs: any): any; +export declare function getNotRawAggs(metricAggs: any): any; diff --git a/deploy/crate-datasource/dist/query_builder.js b/deploy/crate-datasource/dist/query_builder.js new file mode 100755 index 0000000..101fb91 --- /dev/null +++ b/deploy/crate-datasource/dist/query_builder.js @@ -0,0 +1,396 @@ +/// +System.register(['lodash'], function(exports_1) { + var lodash_1; + var MAX_LIMIT, DEFAULT_LIMIT, CrateQueryBuilder; + function getSchemas() { + var query = "SELECT schema_name " + + "FROM information_schema.schemata " + + "WHERE schema_name NOT IN ('information_schema', 'blob', 'sys', 'pg_catalog') " + + "ORDER BY 1"; + return query; + } + exports_1("getSchemas", getSchemas); + function getTables(schema) { + var query = "SELECT table_name " + + "FROM information_schema.tables " + + "WHERE table_schema='" + schema + "' " + + "ORDER BY 1"; + return query; + } + exports_1("getTables", getTables); + function quoteColumn(column) { + if (isWithUpperCase(column)) { + return '\"' + column + '\"'; + } + else { + return column; + } + } + function quoteValue(value) { + value = value.trim(); + var match = value.match(/^'?([^']*)'?$/); + if (match[1]) { + value = match[1]; + } + else { + return value; + } + if (!isNaN(Number(value))) { + return value; + } + else { + return "'" + value + "'"; + } + } + function isWithUpperCase(str) { + return str.toLowerCase() !== str; + } + function aggregateMetrics(metricAggs, aggType) { + var aggs = lodash_1["default"].cloneDeep(metricAggs); + return lodash_1["default"].map(aggs, function (agg) { + if (agg.type === 'raw') { + agg.type = aggType; + return agg; + } + else { + return agg; + } + }); + } + function getEnabledAggs(metricAggs) { + return lodash_1["default"].filter(metricAggs, function (agg) { + return !agg.hide; + }); + } + exports_1("getEnabledAggs", getEnabledAggs); + function getRawAggs(metricAggs) { + return lodash_1["default"].filter(metricAggs, { type: 'raw' }); + } + exports_1("getRawAggs", getRawAggs); + function getNotRawAggs(metricAggs) { + return lodash_1["default"].filter(metricAggs, function (agg) { + return agg.type !== 'raw'; + }); + } + exports_1("getNotRawAggs", getNotRawAggs); + return { + setters:[ + function (lodash_1_1) { + lodash_1 = lodash_1_1; + }], + execute: function() { + // Maximum LIMIT value + MAX_LIMIT = 100000; + DEFAULT_LIMIT = 10000; + CrateQueryBuilder = (function () { + function CrateQueryBuilder(schema, table, defaultTimeColumn, defaultGroupInterval, templateSrv) { + this.templateSrv = templateSrv; + this.schema = schema; + this.table = table; + this.defaultTimeColumn = defaultTimeColumn; + this.defaultGroupInterval = defaultGroupInterval; + this.templateSrv = templateSrv; + } + /** + * Builds Crate SQL query from given target object. + * @param {any} target Target object. + * @param {number} groupInterval Interval for grouping values. + * @param {string} defaultAgg Default aggregation for values. + * @return {string} SQL query. + */ + CrateQueryBuilder.prototype.build = function (target, groupInterval, adhocFilters, limit, defaultAgg) { + if (groupInterval === void 0) { groupInterval = 0; } + if (adhocFilters === void 0) { adhocFilters = []; } + if (limit === void 0) { limit = DEFAULT_LIMIT; } + if (defaultAgg === void 0) { defaultAgg = 'avg'; } + var query; + var timeExp; + var timeColumn = quoteColumn(this.defaultTimeColumn); + var aggs = getEnabledAggs(target.metricAggs); + var rawAggs = getRawAggs(aggs); + if (!aggs.length) { + return null; + } + if (groupInterval) { + // Manually aggregate by time interval, ie "SELECT floor(ts/10)*10 as time ..." + timeExp = "floor(" + timeColumn + "/" + groupInterval + ")*" + groupInterval; + aggs = aggregateMetrics(aggs, 'avg'); + } + else { + timeExp = timeColumn; + } + // SELECT + var renderedAggs = this.renderMetricAggs(aggs); + query = "SELECT " + timeExp + " as time, " + renderedAggs; + // Add GROUP BY columns to SELECT statement. + if (target.groupByColumns && target.groupByColumns.length) { + query += ", " + target.groupByColumns.join(', '); + } + query += (" FROM \"" + this.schema + "\".\"" + this.table + "\"") + + (" WHERE " + timeColumn + " >= ? AND " + timeColumn + " <= ?"); + // WHERE + if (target.whereClauses && target.whereClauses.length) { + query += " AND " + this.renderWhereClauses(target.whereClauses); + } + // Add ad-hoc filters + if (adhocFilters.length > 0) { + query += " AND " + this.renderAdhocFilters(adhocFilters); + } + // GROUP BY + query += " GROUP BY time"; + if (!groupInterval && rawAggs.length) { + query += ", " + this.renderMetricAggs(rawAggs, false); + } + if (target.groupByColumns && target.groupByColumns.length) { + query += ", " + target.groupByColumns.join(', '); + } + // If GROUP BY specified, sort also by selected columns + query += " ORDER BY time"; + if (target.groupByColumns && target.groupByColumns.length) { + query += ", " + target.groupByColumns.join(', '); + } + query += " ASC"; + return query; + }; + CrateQueryBuilder.prototype.buildAggQuery = function (target, groupInterval, adhocFilters, limit) { + if (groupInterval === void 0) { groupInterval = 0; } + if (adhocFilters === void 0) { adhocFilters = []; } + var query; + var timeExp; + var timeColumn = quoteColumn(this.defaultTimeColumn); + var aggs = getEnabledAggs(target.metricAggs); + aggs = getNotRawAggs(aggs); + if (!aggs.length) { + return null; + } + if (!groupInterval) { + groupInterval = 1; + } + if (typeof groupInterval === 'number') { + // Manually aggregate by time interval, ie "SELECT floor(ts/10)*10 as time ..." + timeExp = "floor(" + timeColumn + "/" + groupInterval + ")*" + groupInterval; + } + else { + // Use built-in date_trunc() function + timeExp = "date_trunc('" + groupInterval + "', " + timeColumn + ")"; + } + // SELECT + var renderedAggs = this.renderMetricAggs(aggs); + query = "SELECT " + timeExp + " as time, " + renderedAggs; + // Add GROUP BY columns to SELECT statement. + if (target.groupByColumns && target.groupByColumns.length) { + query += ", " + target.groupByColumns.join(', '); + } + // FROM + query += " FROM \"" + this.schema + "\".\"" + this.table + "\""; + // WHERE + query += " WHERE " + timeColumn + " >= ? AND " + timeColumn + " <= ?"; + if (target.whereClauses && target.whereClauses.length) { + query += " AND " + this.renderWhereClauses(target.whereClauses); + } + // Add ad-hoc filters + if (adhocFilters.length > 0) { + query += " AND " + this.renderAdhocFilters(adhocFilters); + } + // GROUP BY + query += " GROUP BY time"; + if (target.groupByColumns && target.groupByColumns.length) { + query += ", " + target.groupByColumns.join(', '); + } + // If GROUP BY specified, sort also by selected columns + query += " ORDER BY time"; + if (target.groupByColumns && target.groupByColumns.length) { + query += ", " + target.groupByColumns.join(', '); + } + query += " ASC"; + if (limit && limit > DEFAULT_LIMIT) { + limit = Math.min(limit, MAX_LIMIT); + query += " LIMIT " + limit; + } + return query; + }; + CrateQueryBuilder.prototype.buildRawAggQuery = function (target, groupInterval, adhocFilters, limit) { + if (groupInterval === void 0) { groupInterval = 0; } + if (adhocFilters === void 0) { adhocFilters = []; } + var query; + var timeExp; + var timeColumn = quoteColumn(this.defaultTimeColumn); + var aggs = getEnabledAggs(target.metricAggs); + var rawAggs = getRawAggs(aggs); + if (!rawAggs.length) { + return null; + } + // SELECT + var renderedAggs = this.renderMetricAggs(rawAggs); + query = "SELECT " + timeColumn + " as time, " + renderedAggs; + // Add GROUP BY columns to SELECT statement. + if (target.groupByColumns && target.groupByColumns.length) { + query += ", " + target.groupByColumns.join(', '); + } + query += (" FROM \"" + this.schema + "\".\"" + this.table + "\"") + + (" WHERE " + timeColumn + " >= ? AND " + timeColumn + " <= ?"); + // WHERE + if (target.whereClauses && target.whereClauses.length) { + query += " AND " + this.renderWhereClauses(target.whereClauses); + } + // Add ad-hoc filters + if (adhocFilters.length > 0) { + query += " AND " + this.renderAdhocFilters(adhocFilters); + } + // GROUP BY + query += " GROUP BY time"; + query += ", " + this.renderMetricAggs(rawAggs, false); + if (target.groupByColumns && target.groupByColumns.length) { + query += ", " + target.groupByColumns.join(', '); + } + // If GROUP BY specified, sort also by selected columns + query += " ORDER BY time"; + if (target.groupByColumns && target.groupByColumns.length) { + query += ", " + target.groupByColumns.join(', '); + } + query += " ASC"; + if (limit) { + limit = Math.min(limit, MAX_LIMIT); + query += " LIMIT " + limit; + } + return query; + }; + CrateQueryBuilder.prototype.renderAdhocFilters = function (filters) { + var conditions = lodash_1["default"].map(filters, function (tag, index) { + var filter_str = ""; + var condition = tag.condition || 'AND'; + var key = quoteColumn(tag.key); + var operator = tag.operator; + var value = quoteValue(tag.value); + if (index > 0) { + filter_str = condition + " "; + } + if (operator === '=~') { + operator = '~'; + } + filter_str += key + " " + operator + " " + value; + return filter_str; + }); + return conditions.join(' '); + }; + /** + * Builds SQL query for getting available columns from table. + * @return {string} SQL query. + */ + CrateQueryBuilder.prototype.getColumnsQuery = function () { + var query = "SELECT column_name " + + "FROM information_schema.columns " + + "WHERE table_schema = '" + this.schema + "' " + + "AND table_name = '" + this.table + "' " + + "ORDER BY 1"; + return query; + }; + CrateQueryBuilder.prototype.getNumericColumnsQuery = function () { + return "SELECT column_name " + + "FROM information_schema.columns " + + "WHERE table_schema = '" + this.schema + "' " + + "AND table_name = '" + this.table + "' " + + "AND data_type in ('integer', 'long', 'short', 'double', 'float', 'byte') " + + "ORDER BY 1"; + }; + /** + * Builds SQL query for getting unique values for given column. + * @param {string} column Column name + * @param {number} limit Optional. Limit number returned values. + */ + CrateQueryBuilder.prototype.getValuesQuery = function (column, limit, timeRange) { + var timeColumn = quoteColumn(this.defaultTimeColumn); + var query = ("SELECT DISTINCT " + column + " ") + + ("FROM \"" + this.schema + "\".\"" + this.table + "\""); + if (timeRange) { + var timeFrom = timeRange.from.valueOf(); + var timeTo = timeRange.to.valueOf(); + query += " WHERE " + timeColumn + " >= " + timeFrom + " AND " + timeColumn + " <= " + timeTo; + } + if (limit) { + query += " LIMIT " + limit; + } + return query; + }; + CrateQueryBuilder.prototype.renderMetricAggs = function (metricAggs, withAlias) { + if (withAlias === void 0) { withAlias = true; } + var enabledAggs = lodash_1["default"].filter(metricAggs, function (agg) { + return !agg.hide; + }); + var renderedAggs = lodash_1["default"].map(enabledAggs, function (agg) { + var alias = ''; + if (agg.alias && withAlias) { + alias = ' AS \"' + agg.alias + '\"'; + } + var column = quoteColumn(agg.column); + if (agg.type === 'count_distinct') { + return "count(distinct " + column + ")" + alias; + } + else if (agg.type === 'raw') { + return column + alias; + } + else { + return agg.type + "(" + column + ")" + alias; + } + }); + if (renderedAggs.length) { + return renderedAggs.join(', '); + } + else { + return ""; + } + }; + CrateQueryBuilder.prototype.renderWhereClauses = function (whereClauses) { + var _this = this; + var renderedClauses = lodash_1["default"].map(whereClauses, function (clauseObj, index) { + var rendered = ""; + if (index !== 0) { + rendered += clauseObj.condition + " "; + } + // Quote arguments as required by the operator and value type + var rendered_value; + var value = clauseObj.value; + if (clauseObj.operator.toLowerCase() === 'in') { + // Handle IN operator. Split comma-separated values. + // "42, 10, a" => 42, 10, 'a' + rendered_value = '(' + lodash_1["default"].map(value.split(','), function (v) { + v = v.trim(); + if (!isNaN(v) || _this.containsVariable(v)) { + return v; + } + else { + return "'" + v + "'"; + } + }).join(', ') + ')'; + } + else { + rendered_value = lodash_1["default"].map(value.split(','), function (v) { + v = v.trim(); + if (!isNaN(v) || _this.containsVariable(v)) { + return v; + } + else { + return "'" + v + "'"; + } + }).join(', '); + } + rendered += clauseObj.column + ' ' + clauseObj.operator + ' ' + rendered_value; + return rendered; + }); + return renderedClauses.join(' '); + }; + // Check for template variables + CrateQueryBuilder.prototype.containsVariable = function (str) { + var variables = lodash_1["default"].map(this.templateSrv.variables, 'name'); + return lodash_1["default"].some(variables, function (variable) { + var pattern = new RegExp('\\$' + variable); + return pattern.test(str); + }); + }; + return CrateQueryBuilder; + })(); + exports_1("CrateQueryBuilder", CrateQueryBuilder); + } + } +}); +//# sourceMappingURL=query_builder.js.map \ No newline at end of file diff --git a/deploy/crate-datasource/dist/query_builder.js.map b/deploy/crate-datasource/dist/query_builder.js.map new file mode 100755 index 0000000..d2bb5b4 --- /dev/null +++ b/deploy/crate-datasource/dist/query_builder.js.map @@ -0,0 +1 @@ +{"version":3,"file":"query_builder.js","sourceRoot":"","sources":["query_builder.ts"],"names":["getSchemas","getTables","quoteColumn","quoteValue","isWithUpperCase","aggregateMetrics","getEnabledAggs","getRawAggs","getNotRawAggs","CrateQueryBuilder","CrateQueryBuilder.constructor","CrateQueryBuilder.build","CrateQueryBuilder.buildAggQuery","CrateQueryBuilder.buildRawAggQuery","CrateQueryBuilder.renderAdhocFilters","CrateQueryBuilder.getColumnsQuery","CrateQueryBuilder.getNumericColumnsQuery","CrateQueryBuilder.getValuesQuery","CrateQueryBuilder.renderMetricAggs","CrateQueryBuilder.renderWhereClauses","CrateQueryBuilder.containsVariable"],"mappings":"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AACA,CAACA,KAAKA,KAAKA,CAACA,CAACA,CAACA,CAACA;4BAChBA,QAAQA,IAAIA,SAASA,CAACA,SAASA,GAAGA,GAAGA,CAACA;wBACxCA,CAACA;wBAEDA,6DAA6DA;wBAC7DA,IAAIA,cAAsBA,CAACA;wBAC3BA,IAAIA,KAAKA,GAAGA,SAASA,CAACA,KAAKA,CAACA;wBAC5BA,EAAEA,CAACA,CAACA,SAASA,CAACA,QAAQA,CAACA,WAAWA,EAAEA,KAAKA,IAAIA,CAACA,CAACA,CAACA;4BAC9CA,oDAAoDA;4BACpDA,6BAA6BA;4BAC7BA,cAAcA,GAAGA,GAAGA,GAAGA,mBAACA,CAACA,GAAGA,CAACA,KAAKA,CAACA,KAAKA,CAACA,GAAGA,CAACA,EAAEA,UAAAA,CAACA;gCAC9CA,CAACA,GAAGA,CAACA,CAACA,IAAIA,EAAEA,CAACA;gCACbA,EAAEA,CAACA,CAACA,CAACA,KAAKA,CAACA,CAACA,CAACA,IAAIA,KAAIA,CAACA,gBAAgBA,CAACA,CAACA,CAACA,CAACA,CAACA,CAACA;oCAC1CA,MAAMA,CAACA,CAACA,CAACA;gCACXA,CAACA;gCAACA,IAAIA,CAACA,CAACA;oCACNA,MAAMA,CAACA,GAAGA,GAAGA,CAACA,GAAGA,GAAGA,CAACA;gCACvBA,CAACA;4BACHA,CAACA,CAACA,CAACA,IAAIA,CAACA,IAAIA,CAACA,GAAGA,GAAGA,CAACA;wBACtBA,CAACA;wBAACA,IAAIA,CAACA,CAACA;4BACNA,cAAcA,GAAGA,mBAACA,CAACA,GAAGA,CAACA,KAAKA,CAACA,KAAKA,CAACA,GAAGA,CAACA,EAAEA,UAAAA,CAACA;gCACxCA,CAACA,GAAGA,CAACA,CAACA,IAAIA,EAAEA,CAACA;gCACbA,EAAEA,CAACA,CAACA,CAACA,KAAKA,CAACA,CAACA,CAACA,IAAIA,KAAIA,CAACA,gBAAgBA,CAACA,CAACA,CAACA,CAACA,CAACA,CAACA;oCAC1CA,MAAMA,CAACA,CAACA,CAACA;gCACXA,CAACA;gCAACA,IAAIA,CAACA,CAACA;oCACNA,MAAMA,CAACA,GAAGA,GAAGA,CAACA,GAAGA,GAAGA,CAACA;gCACvBA,CAACA;4BACHA,CAACA,CAACA,CAACA,IAAIA,CAACA,IAAIA,CAACA,CAACA;wBAChBA,CAACA;wBACDA,QAAQA,IAAIA,SAASA,CAACA,MAAMA,GAAGA,GAAGA,GAAGA,SAASA,CAACA,QAAQA,GAAGA,GAAGA,GAAGA,cAAcA,CAACA;wBAC/EA,MAAMA,CAACA,QAAQA,CAACA;oBAClBA,CAACA,CAACA,CAACA;oBACHA,MAAMA,CAACA,eAAeA,CAACA,IAAIA,CAACA,GAAGA,CAACA,CAACA;gBACnCA,CAACA;gBAEDV,+BAA+BA;gBACvBA,4CAAgBA,GAAxBA,UAAyBA,GAAWA;oBAClCW,IAAIA,SAASA,GAAGA,mBAACA,CAACA,GAAGA,CAACA,IAAIA,CAACA,WAAWA,CAACA,SAASA,EAAEA,MAAMA,CAACA,CAACA;oBAC1DA,MAAMA,CAACA,mBAACA,CAACA,IAAIA,CAACA,SAASA,EAAEA,UAAAA,QAAQA;wBAC/BA,IAAIA,OAAOA,GAAGA,IAAIA,MAAMA,CAACA,KAAKA,GAAGA,QAAQA,CAACA,CAACA;wBAC3CA,MAAMA,CAACA,OAAOA,CAACA,IAAIA,CAACA,GAAGA,CAACA,CAACA;oBAC3BA,CAACA,CAACA,CAACA;gBACLA,CAACA;gBACHX,wBAACA;YAADA,CAACA,AAxVD,IAwVC;YAxVD,iDAwVC,CAAA"} \ No newline at end of file diff --git a/deploy/crate-datasource/dist/query_builder.ts b/deploy/crate-datasource/dist/query_builder.ts new file mode 100755 index 0000000..2aeda51 --- /dev/null +++ b/deploy/crate-datasource/dist/query_builder.ts @@ -0,0 +1,425 @@ +/// + +import _ from 'lodash'; + +// Maximum LIMIT value +let MAX_LIMIT = 100000; +let DEFAULT_LIMIT = 10000; + +export class CrateQueryBuilder { + schema: string; + table: string; + defaultTimeColumn: string; + defaultGroupInterval: string; + + constructor(schema: string, + table: string, + defaultTimeColumn: string, + defaultGroupInterval: string, + private templateSrv) { + this.schema = schema; + this.table = table; + this.defaultTimeColumn = defaultTimeColumn; + this.defaultGroupInterval = defaultGroupInterval; + this.templateSrv = templateSrv; + } + + /** + * Builds Crate SQL query from given target object. + * @param {any} target Target object. + * @param {number} groupInterval Interval for grouping values. + * @param {string} defaultAgg Default aggregation for values. + * @return {string} SQL query. + */ + build(target: any, groupInterval = 0, adhocFilters = [], limit = DEFAULT_LIMIT, defaultAgg='avg') { + let query: string; + let timeExp: string; + + let timeColumn = quoteColumn(this.defaultTimeColumn); + let aggs = getEnabledAggs(target.metricAggs); + let rawAggs = getRawAggs(aggs); + + if (!aggs.length) { return null; } + + if (groupInterval) { + // Manually aggregate by time interval, ie "SELECT floor(ts/10)*10 as time ..." + timeExp = `floor(${timeColumn}/${groupInterval})*${groupInterval}`; + aggs = aggregateMetrics(aggs, 'avg'); + } else { + timeExp = timeColumn; + } + + // SELECT + let renderedAggs = this.renderMetricAggs(aggs); + query = "SELECT " + timeExp + " as time, " + renderedAggs; + + // Add GROUP BY columns to SELECT statement. + if (target.groupByColumns && target.groupByColumns.length) { + query += ", " + target.groupByColumns.join(', '); + } + query += ` FROM "${this.schema}"."${this.table}"` + + ` WHERE ${timeColumn} >= ? AND ${timeColumn} <= ?`; + + // WHERE + if (target.whereClauses && target.whereClauses.length) { + query += " AND " + this.renderWhereClauses(target.whereClauses); + } + + // Add ad-hoc filters + if (adhocFilters.length > 0) { + query += " AND " + this.renderAdhocFilters(adhocFilters); + } + + // GROUP BY + query += " GROUP BY time"; + if (!groupInterval && rawAggs.length) { + query += ", " + this.renderMetricAggs(rawAggs, false); + } + + if (target.groupByColumns && target.groupByColumns.length) { + query += ", " + target.groupByColumns.join(', '); + } + + // If GROUP BY specified, sort also by selected columns + query += " ORDER BY time"; + if (target.groupByColumns && target.groupByColumns.length) { + query += ", " + target.groupByColumns.join(', '); + } + query += " ASC"; + + return query; + } + + buildAggQuery(target: any, groupInterval = 0, adhocFilters = [], limit?: number) { + let query: string; + let timeExp: string; + + let timeColumn = quoteColumn(this.defaultTimeColumn); + let aggs = getEnabledAggs(target.metricAggs); + aggs = getNotRawAggs(aggs); + + if (!aggs.length) { return null; } + + if (!groupInterval) { + groupInterval = 1; + } + + if (typeof groupInterval === 'number') { + // Manually aggregate by time interval, ie "SELECT floor(ts/10)*10 as time ..." + timeExp = `floor(${timeColumn}/${groupInterval})*${groupInterval}`; + } else { + // Use built-in date_trunc() function + timeExp = `date_trunc('${groupInterval}', ${timeColumn})`; + } + + // SELECT + let renderedAggs = this.renderMetricAggs(aggs); + query = `SELECT ${timeExp} as time, ${renderedAggs}`; + + // Add GROUP BY columns to SELECT statement. + if (target.groupByColumns && target.groupByColumns.length) { + query += ", " + target.groupByColumns.join(', '); + } + + // FROM + query += ` FROM "${this.schema}"."${this.table}"`; + + // WHERE + query += ` WHERE ${timeColumn} >= ? AND ${timeColumn} <= ?`; + if (target.whereClauses && target.whereClauses.length) { + query += " AND " + this.renderWhereClauses(target.whereClauses); + } + + // Add ad-hoc filters + if (adhocFilters.length > 0) { + query += " AND " + this.renderAdhocFilters(adhocFilters); + } + + // GROUP BY + query += " GROUP BY time"; + + if (target.groupByColumns && target.groupByColumns.length) { + query += ", " + target.groupByColumns.join(', '); + } + + // If GROUP BY specified, sort also by selected columns + query += " ORDER BY time"; + if (target.groupByColumns && target.groupByColumns.length) { + query += ", " + target.groupByColumns.join(', '); + } + query += " ASC"; + + if (limit && limit > DEFAULT_LIMIT) { + limit = Math.min(limit, MAX_LIMIT); + query += ` LIMIT ${limit}`; + } + + return query; + } + + buildRawAggQuery(target: any, groupInterval = 0, adhocFilters = [], limit?: number) { + let query: string; + let timeExp: string; + + let timeColumn = quoteColumn(this.defaultTimeColumn); + let aggs = getEnabledAggs(target.metricAggs); + let rawAggs = getRawAggs(aggs); + + if (!rawAggs.length) { return null; } + + // SELECT + let renderedAggs = this.renderMetricAggs(rawAggs); + query = "SELECT " + timeColumn + " as time, " + renderedAggs; + + // Add GROUP BY columns to SELECT statement. + if (target.groupByColumns && target.groupByColumns.length) { + query += ", " + target.groupByColumns.join(', '); + } + query += ` FROM "${this.schema}"."${this.table}"` + + ` WHERE ${timeColumn} >= ? AND ${timeColumn} <= ?`; + + // WHERE + if (target.whereClauses && target.whereClauses.length) { + query += " AND " + this.renderWhereClauses(target.whereClauses); + } + + // Add ad-hoc filters + if (adhocFilters.length > 0) { + query += " AND " + this.renderAdhocFilters(adhocFilters); + } + + // GROUP BY + query += " GROUP BY time"; + query += ", " + this.renderMetricAggs(rawAggs, false); + + if (target.groupByColumns && target.groupByColumns.length) { + query += ", " + target.groupByColumns.join(', '); + } + + // If GROUP BY specified, sort also by selected columns + query += " ORDER BY time"; + if (target.groupByColumns && target.groupByColumns.length) { + query += ", " + target.groupByColumns.join(', '); + } + query += " ASC"; + + if (limit) { + limit = Math.min(limit, MAX_LIMIT); + query += ` LIMIT ${limit}`; + } + + return query; + } + + renderAdhocFilters(filters) { + let conditions = _.map(filters, (tag, index) => { + let filter_str = ""; + let condition = tag.condition || 'AND'; + let key = quoteColumn(tag.key); + let operator = tag.operator; + let value = quoteValue(tag.value); + + if (index > 0) { + filter_str = `${condition} `; + } + + if (operator === '=~') { + operator = '~'; + } + + filter_str += `${key} ${operator} ${value}` + return filter_str; + }); + return conditions.join(' '); + } + + /** + * Builds SQL query for getting available columns from table. + * @return {string} SQL query. + */ + getColumnsQuery() { + let query = "SELECT column_name " + + "FROM information_schema.columns " + + "WHERE table_schema = '" + this.schema + "' " + + "AND table_name = '" + this.table + "' " + + "ORDER BY 1"; + return query; + } + + getNumericColumnsQuery() { + return "SELECT column_name " + + "FROM information_schema.columns " + + "WHERE table_schema = '" + this.schema + "' " + + "AND table_name = '" + this.table + "' " + + "AND data_type in ('integer', 'long', 'short', 'double', 'float', 'byte') " + + "ORDER BY 1"; + } + + /** + * Builds SQL query for getting unique values for given column. + * @param {string} column Column name + * @param {number} limit Optional. Limit number returned values. + */ + getValuesQuery(column: string, limit?: number, timeRange?) { + let timeColumn = quoteColumn(this.defaultTimeColumn); + let query = `SELECT DISTINCT ${column} ` + + `FROM "${this.schema}"."${this.table}"`; + + if (timeRange) { + let timeFrom = timeRange.from.valueOf(); + let timeTo = timeRange.to.valueOf(); + query += ` WHERE ${timeColumn} >= ${timeFrom} AND ${timeColumn} <= ${timeTo}`; + } + + if (limit) { + query += ` LIMIT ${limit}`; + } + return query; + } + + private renderMetricAggs(metricAggs: any, withAlias=true): string { + let enabledAggs = _.filter(metricAggs, (agg) => { + return !agg.hide; + }); + + let renderedAggs = _.map(enabledAggs, (agg) => { + let alias = ''; + if (agg.alias && withAlias) { + alias = ' AS \"' + agg.alias + '\"'; + } + + let column = quoteColumn(agg.column); + if (agg.type === 'count_distinct') { + return "count(distinct " + column + ")" + alias; + } else if (agg.type === 'raw') { + return column + alias; + } else { + return agg.type + "(" + column + ")" + alias; + } + }); + + if (renderedAggs.length) { + return renderedAggs.join(', '); + } else { + return ""; + } + } + + private renderWhereClauses(whereClauses): string { + let renderedClauses = _.map(whereClauses, (clauseObj, index) => { + let rendered = ""; + if (index !== 0) { + rendered += clauseObj.condition + " "; + } + + // Quote arguments as required by the operator and value type + let rendered_value: string; + let value = clauseObj.value; + if (clauseObj.operator.toLowerCase() === 'in') { + // Handle IN operator. Split comma-separated values. + // "42, 10, a" => 42, 10, 'a' + rendered_value = '(' + _.map(value.split(','), v => { + v = v.trim(); + if (!isNaN(v) || this.containsVariable(v)) { + return v; + } else { + return "'" + v + "'"; + } + }).join(', ') + ')'; + } else { + rendered_value = _.map(value.split(','), v => { + v = v.trim(); + if (!isNaN(v) || this.containsVariable(v)) { + return v; + } else { + return "'" + v + "'"; + } + }).join(', '); + } + rendered += clauseObj.column + ' ' + clauseObj.operator + ' ' + rendered_value; + return rendered; + }); + return renderedClauses.join(' '); + } + + // Check for template variables + private containsVariable(str: string): boolean { + let variables = _.map(this.templateSrv.variables, 'name'); + return _.some(variables, variable => { + let pattern = new RegExp('\\$' + variable); + return pattern.test(str); + }); + } +} + +export function getSchemas() { + var query = "SELECT schema_name " + + "FROM information_schema.schemata " + + "WHERE schema_name NOT IN ('information_schema', 'blob', 'sys', 'pg_catalog') " + + "ORDER BY 1"; + return query; +} + +export function getTables(schema) { + var query = "SELECT table_name " + + "FROM information_schema.tables " + + "WHERE table_schema='" + schema + "' " + + "ORDER BY 1"; + return query; +} + +function quoteColumn(column: string): string { + if (isWithUpperCase(column)) { + return '\"' + column + '\"'; + } else { + return column; + } +} + +function quoteValue(value: string): string { + value = value.trim(); + let match = value.match(/^'?([^']*)'?$/); + if (match[1]) { + value = match[1]; + } else { + return value; + } + + if (!isNaN(Number(value))) { + return value; + } else { + return "'" + value + "'"; + } +} + +function isWithUpperCase(str: string): boolean { + return str.toLowerCase() !== str; +} + +function aggregateMetrics(metricAggs: any, aggType: string) { + let aggs = _.cloneDeep(metricAggs); + return _.map(aggs, agg => { + if (agg.type === 'raw') { + agg.type = aggType; + return agg; + } else { + return agg; + } + }); +} + +export function getEnabledAggs(metricAggs) { + return _.filter(metricAggs, (agg) => { + return !agg.hide; + }); +} + +export function getRawAggs(metricAggs) { + return _.filter(metricAggs, {type: 'raw'}); +} + +export function getNotRawAggs(metricAggs) { + return _.filter(metricAggs, agg => { + return agg.type !== 'raw'; + }); +} diff --git a/deploy/crate-datasource/dist/query_ctrl.d.ts b/deploy/crate-datasource/dist/query_ctrl.d.ts new file mode 100755 index 0000000..8f92cf0 --- /dev/null +++ b/deploy/crate-datasource/dist/query_ctrl.d.ts @@ -0,0 +1,48 @@ +/// +import { QueryCtrl } from './sdk/sdk'; +import { CrateQueryBuilder } from './query_builder'; +export declare class CrateDatasourceQueryCtrl extends QueryCtrl { + private $q; + private uiSegmentSrv; + private templateSrv; + static templateUrl: string; + crateQueryBuilder: CrateQueryBuilder; + groupBySegments: any; + whereSegments: any; + removeWhereSegment: any; + operators: any; + timeIntervals: any[]; + resultFormats: any[]; + constructor($scope: any, $injector: any, $q: any, uiSegmentSrv: any, templateSrv: any); + crateQuery(query: any, args?: any[]): any; + getCollapsedText(): string; + onChangeInternal(): void; + groupBySegmentChanged(segment: any, index: any): void; + onGroupByAliasChange(index: any): void; + onAggTypeChange(): void; + addMetricAgg(): void; + removeMetricAgg(index: any): void; + toggleShowMetric(agg: any): void; + toggleEditorMode(): void; + getColumns(allValue?: boolean, onlyNumeric?: boolean): any; + getGroupByColumns(): any; + getValues(column: any, limit?: number): any; + getColumnsOrValues(segment: any, index: any): any; + getMetricAggTypes(): ({ + text: string; + value: string; + allValue: boolean; + } | { + text: string; + value: string; + allValue: boolean; + anyDataType: boolean; + })[]; + getMetricAggDef(aggType: any): any; + whereSegmentUpdated(segment: any, index: any): void; + buildWhereSegments(whereClauses: any): void; + buildWhereClauses(): void; + fixSegments(segments: any): void; + transformToSegments(results: any, addTemplateVars?: boolean): any; + updateGroupByAliases(): void; +} diff --git a/deploy/crate-datasource/dist/query_ctrl.js b/deploy/crate-datasource/dist/query_ctrl.js new file mode 100755 index 0000000..8ed995f --- /dev/null +++ b/deploy/crate-datasource/dist/query_ctrl.js @@ -0,0 +1,313 @@ +/// +System.register(['angular', 'lodash', './sdk/sdk', './query_builder', './query_def'], function(exports_1) { + var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; + var angular_1, lodash_1, sdk_1, query_builder_1, query_def_1; + var CrateDatasourceQueryCtrl; + return { + setters:[ + function (angular_1_1) { + angular_1 = angular_1_1; + }, + function (lodash_1_1) { + lodash_1 = lodash_1_1; + }, + function (sdk_1_1) { + sdk_1 = sdk_1_1; + }, + function (query_builder_1_1) { + query_builder_1 = query_builder_1_1; + }, + function (query_def_1_1) { + query_def_1 = query_def_1_1; + }], + execute: function() { + CrateDatasourceQueryCtrl = (function (_super) { + __extends(CrateDatasourceQueryCtrl, _super); + function CrateDatasourceQueryCtrl($scope, $injector, $q, uiSegmentSrv, templateSrv) { + _super.call(this, $scope, $injector); + this.$q = $q; + this.uiSegmentSrv = uiSegmentSrv; + this.templateSrv = templateSrv; + this.uiSegmentSrv = uiSegmentSrv; + this.templateSrv = templateSrv; + var ds = this.datasource; + this.crateQueryBuilder = new query_builder_1.CrateQueryBuilder(ds.schema, ds.table, ds.defaultTimeColumn, ds.defaultGroupInterval, templateSrv); + this.operators = ['<', '>', '<=', '>=', '=', '<>', '!=', 'in', 'like', '~', '!~']; + this.timeIntervals = [ + { name: 'Auto', value: 'auto' }, + { name: 'Auto (Grafana)', value: 'auto_gf' }, + { name: 'Second', value: 'second' }, + { name: 'Minute', value: 'minute' }, + { name: 'Hour', value: 'hour' }, + { name: 'Day', value: 'day' }, + { name: 'Week', value: 'week' }, + { name: 'Month', value: 'month' }, + { name: 'Quarter', value: 'quarter' }, + { name: 'Year', value: 'year' } + ]; + this.resultFormats = [ + { text: 'Time series', value: 'time_series' }, + { text: 'Table', value: 'table' }, + ]; + var target_defaults = { + metricAggs: [ + { type: 'avg', column: 'value' } + ], + groupByColumns: [], + groupByAliases: [], + whereClauses: [], + timeInterval: ds.defaultGroupInterval, + resultFormat: 'time_series' + }; + lodash_1["default"].defaults(this.target, target_defaults); + this.updateGroupByAliases(); + this.groupBySegments = lodash_1["default"].map(this.target.groupByColumns, this.uiSegmentSrv.newSegment); + // Build WHERE segments + this.whereSegments = []; + this.buildWhereSegments(this.target.whereClauses); + this.removeWhereSegment = uiSegmentSrv.newSegment({ fake: true, value: '-- remove --' }); + this.fixSegments(this.groupBySegments); + } + CrateDatasourceQueryCtrl.prototype.crateQuery = function (query, args) { + if (args === void 0) { args = []; } + return this.datasource._sql_query(query, args).then(function (response) { + return response.rows; + }); + }; + CrateDatasourceQueryCtrl.prototype.getCollapsedText = function () { + if (this.target.rawQuery) { + return this.target.query; + } + else { + return this.crateQueryBuilder.build(this.target); + } + }; + //////////////////// + // Event handlers // + //////////////////// + CrateDatasourceQueryCtrl.prototype.onChangeInternal = function () { + this.panelCtrl.refresh(); // Asks the panel to refresh data. + }; + CrateDatasourceQueryCtrl.prototype.groupBySegmentChanged = function (segment, index) { + var _this = this; + if (segment.type === 'plus-button') { + segment.type = undefined; + } + this.target.groupByColumns = lodash_1["default"].map(lodash_1["default"].filter(this.groupBySegments, function (segment) { + return (segment.type !== 'plus-button' && + segment.value !== _this.removeWhereSegment.value); + }), 'value'); + this.groupBySegments = lodash_1["default"].map(this.target.groupByColumns, this.uiSegmentSrv.newSegment); + this.groupBySegments.push(this.uiSegmentSrv.newPlusButton()); + if (segment.value === this.removeWhereSegment.value) { + this.target.groupByAliases.splice(index, 1); + } + this.updateGroupByAliases(); + this.onChangeInternal(); + }; + CrateDatasourceQueryCtrl.prototype.onGroupByAliasChange = function (index) { + this.updateGroupByAliases(); + this.onChangeInternal(); + }; + CrateDatasourceQueryCtrl.prototype.onAggTypeChange = function () { + this.onChangeInternal(); + }; + CrateDatasourceQueryCtrl.prototype.addMetricAgg = function () { + this.target.metricAggs.push({ type: 'avg', column: 'value' }); + this.onChangeInternal(); + }; + CrateDatasourceQueryCtrl.prototype.removeMetricAgg = function (index) { + this.target.metricAggs.splice(index, 1); + this.onChangeInternal(); + }; + CrateDatasourceQueryCtrl.prototype.toggleShowMetric = function (agg) { + agg.hide = !agg.hide; + this.onChangeInternal(); + }; + CrateDatasourceQueryCtrl.prototype.toggleEditorMode = function () { + this.target.rawQuery = !this.target.rawQuery; + }; + /////////////////////// + // Query suggestions // + /////////////////////// + CrateDatasourceQueryCtrl.prototype.getColumns = function (allValue, onlyNumeric) { + var query; + if (onlyNumeric) { + query = this.crateQueryBuilder.getNumericColumnsQuery(); + } + else { + query = this.crateQueryBuilder.getColumnsQuery(); + } + var self = this; + return this.crateQuery(query).then(function (rows) { + if (allValue) { + rows.splice(0, 0, '*'); + } + return self.transformToSegments(lodash_1["default"].flatten(rows), true); + }); + }; + CrateDatasourceQueryCtrl.prototype.getGroupByColumns = function () { + var _this = this; + return this.getColumns().then(function (columns) { + columns.splice(0, 0, angular_1["default"].copy(_this.removeWhereSegment)); + return columns; + }); + }; + CrateDatasourceQueryCtrl.prototype.getValues = function (column, limit) { + if (limit === void 0) { limit = 10; } + var self = this; + var time_range = this.panelCtrl.range; + return this.crateQuery(this.crateQueryBuilder.getValuesQuery(column, limit, time_range)) + .then(function (rows) { + return self.transformToSegments(lodash_1["default"].flatten(rows), true); + }); + }; + CrateDatasourceQueryCtrl.prototype.getColumnsOrValues = function (segment, index) { + var _this = this; + var self = this; + if (segment.type === 'condition') { + return this.$q.when([this.uiSegmentSrv.newSegment('AND'), this.uiSegmentSrv.newSegment('OR')]); + } + if (segment.type === 'operator') { + return this.$q.when(this.uiSegmentSrv.newOperators(this.operators)); + } + if (segment.type === 'key' || segment.type === 'plus-button') { + return this.getColumns().then(function (columns) { + columns.splice(0, 0, angular_1["default"].copy(_this.removeWhereSegment)); + return columns; + }); + } + else if (segment.type === 'value') { + return this.getValues(this.whereSegments[index - 2].value); + } + }; + CrateDatasourceQueryCtrl.prototype.getMetricAggTypes = function () { + return query_def_1["default"].getMetricAggTypes(); + }; + CrateDatasourceQueryCtrl.prototype.getMetricAggDef = function (aggType) { + return lodash_1["default"].find(this.getMetricAggTypes(), { value: aggType }); + }; + CrateDatasourceQueryCtrl.prototype.whereSegmentUpdated = function (segment, index) { + this.whereSegments[index] = segment; + if (segment.value === this.removeWhereSegment.value) { + this.whereSegments.splice(index, 3); + if (this.whereSegments.length === 0) { + this.whereSegments.push(this.uiSegmentSrv.newPlusButton()); + } + else if (this.whereSegments.length > 2) { + this.whereSegments.splice(Math.max(index - 1, 0), 1); + if (this.whereSegments[this.whereSegments.length - 1].type !== 'plus-button') { + this.whereSegments.push(this.uiSegmentSrv.newPlusButton()); + } + } + } + else { + if (segment.type === 'plus-button') { + if (index > 2) { + this.whereSegments.splice(index, 0, this.uiSegmentSrv.newCondition('AND')); + } + this.whereSegments.push(this.uiSegmentSrv.newOperator('=')); + this.whereSegments.push(this.uiSegmentSrv.newFake('select tag value', 'value', 'query-segment-value')); + segment.type = 'key'; + segment.cssClass = 'query-segment-key'; + } + if ((index + 1) === this.whereSegments.length) { + this.whereSegments.push(this.uiSegmentSrv.newPlusButton()); + } + } + this.buildWhereClauses(); + // Refresh only if all fields setted + if (lodash_1["default"].every(this.whereSegments, function (segment) { + return ((segment.value || segment.type === 'plus-button') && + !(segment.fake && segment.type !== 'plus-button')); + })) { + this.panelCtrl.refresh(); + } + }; + /////////////////////// + CrateDatasourceQueryCtrl.prototype.buildWhereSegments = function (whereClauses) { + var self = this; + lodash_1["default"].forEach(whereClauses, function (whereClause) { + if (whereClause.condition) { + self.whereSegments.push(self.uiSegmentSrv.newCondition(whereClause.condition)); + } + self.whereSegments.push(self.uiSegmentSrv.newKey(whereClause.column)); + self.whereSegments.push(self.uiSegmentSrv.newOperator(whereClause.operator)); + self.whereSegments.push(self.uiSegmentSrv.newKeyValue(whereClause.value)); + }); + this.fixSegments(this.whereSegments); + }; + CrateDatasourceQueryCtrl.prototype.buildWhereClauses = function () { + var i = 0; + var whereIndex = 0; + var segments = this.whereSegments; + var whereClauses = []; + while (segments.length > i && segments[i].type !== 'plus-button') { + if (whereClauses.length < whereIndex + 1) { + whereClauses.push({ condition: '', column: '', operator: '', value: '' }); + } + if (segments[i].type === 'condition') { + whereClauses[whereIndex].condition = segments[i].value; + } + else if (segments[i].type === 'key') { + whereClauses[whereIndex].column = segments[i].value; + } + else if (segments[i].type === 'operator') { + whereClauses[whereIndex].operator = segments[i].value; + } + else if (segments[i].type === 'value' || segments[i].type === 'template') { + whereClauses[whereIndex].value = segments[i].value; + whereIndex++; + } + i++; + } + this.target.whereClauses = whereClauses; + }; + CrateDatasourceQueryCtrl.prototype.fixSegments = function (segments) { + var count = segments.length; + var lastSegment = segments[Math.max(count - 1, 0)]; + if (!lastSegment || lastSegment.type !== 'plus-button') { + segments.push(this.uiSegmentSrv.newPlusButton()); + } + }; + CrateDatasourceQueryCtrl.prototype.transformToSegments = function (results, addTemplateVars) { + var _this = this; + var segments = lodash_1["default"].map(lodash_1["default"].flatten(results), function (value) { + return _this.uiSegmentSrv.newSegment({ + value: value.toString(), + expandable: false + }); + }); + if (addTemplateVars) { + for (var _i = 0, _a = this.templateSrv.variables; _i < _a.length; _i++) { + var variable = _a[_i]; + segments.unshift(this.uiSegmentSrv.newSegment({ type: 'template', value: '$' + variable.name, expandable: true })); + } + } + return segments; + }; + CrateDatasourceQueryCtrl.prototype.updateGroupByAliases = function () { + var _this = this; + var groupByAliases = new Array(this.target.groupByColumns.length); + this.target.groupByColumns.forEach(function (column, index) { + if (_this.target.groupByAliases[index]) { + groupByAliases[index] = _this.target.groupByAliases[index]; + } + else { + groupByAliases[index] = ""; + } + }); + this.target.groupByAliases = groupByAliases; + }; + CrateDatasourceQueryCtrl.templateUrl = 'partials/query.editor.html'; + return CrateDatasourceQueryCtrl; + })(sdk_1.QueryCtrl); + exports_1("CrateDatasourceQueryCtrl", CrateDatasourceQueryCtrl); + } + } +}); +//# sourceMappingURL=query_ctrl.js.map \ No newline at end of file diff --git a/deploy/crate-datasource/dist/query_ctrl.js.map b/deploy/crate-datasource/dist/query_ctrl.js.map new file mode 100755 index 0000000..d382c01 --- /dev/null +++ b/deploy/crate-datasource/dist/query_ctrl.js.map @@ -0,0 +1 @@ +{"version":3,"file":"query_ctrl.js","sourceRoot":"","sources":["query_ctrl.ts"],"names":["CrateDatasourceQueryCtrl","CrateDatasourceQueryCtrl.constructor","CrateDatasourceQueryCtrl.crateQuery","CrateDatasourceQueryCtrl.getCollapsedText","CrateDatasourceQueryCtrl.onChangeInternal","CrateDatasourceQueryCtrl.groupBySegmentChanged","CrateDatasourceQueryCtrl.onGroupByAliasChange","CrateDatasourceQueryCtrl.onAggTypeChange","CrateDatasourceQueryCtrl.addMetricAgg","CrateDatasourceQueryCtrl.removeMetricAgg","CrateDatasourceQueryCtrl.toggleShowMetric","CrateDatasourceQueryCtrl.toggleEditorMode","CrateDatasourceQueryCtrl.getColumns","CrateDatasourceQueryCtrl.getGroupByColumns","CrateDatasourceQueryCtrl.getValues","CrateDatasourceQueryCtrl.getColumnsOrValues","CrateDatasourceQueryCtrl.getMetricAggTypes","CrateDatasourceQueryCtrl.getMetricAggDef","CrateDatasourceQueryCtrl.whereSegmentUpdated","CrateDatasourceQueryCtrl.buildWhereSegments","CrateDatasourceQueryCtrl.buildWhereClauses","CrateDatasourceQueryCtrl.fixSegments","CrateDatasourceQueryCtrl.transformToSegments","CrateDatasourceQueryCtrl.updateGroupByAliases"],"mappings":"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"} \ No newline at end of file diff --git a/deploy/crate-datasource/dist/query_ctrl.ts b/deploy/crate-datasource/dist/query_ctrl.ts new file mode 100755 index 0000000..afed57c --- /dev/null +++ b/deploy/crate-datasource/dist/query_ctrl.ts @@ -0,0 +1,324 @@ +/// + +import angular from 'angular'; +import _ from 'lodash'; +import {QueryCtrl} from './sdk/sdk'; +import {CrateQueryBuilder} from './query_builder'; +import queryDef from './query_def'; + +export class CrateDatasourceQueryCtrl extends QueryCtrl { + static templateUrl = 'partials/query.editor.html'; + + crateQueryBuilder: CrateQueryBuilder; + groupBySegments: any; + whereSegments: any; + removeWhereSegment: any; + operators: any; + timeIntervals: any[]; + resultFormats: any[]; + + constructor($scope, $injector, private $q, private uiSegmentSrv, private templateSrv) { + super($scope, $injector); + + this.uiSegmentSrv = uiSegmentSrv; + this.templateSrv = templateSrv; + + let ds = this.datasource; + this.crateQueryBuilder = new CrateQueryBuilder(ds.schema, + ds.table, + ds.defaultTimeColumn, + ds.defaultGroupInterval, + templateSrv); + + this.operators = ['<', '>', '<=', '>=', '=', '<>', '!=', 'in', 'like', '~', '!~']; + + this.timeIntervals = [ + {name: 'Auto', value: 'auto'}, + {name: 'Auto (Grafana)', value: 'auto_gf'}, + {name: 'Second', value: 'second'}, + {name: 'Minute', value: 'minute'}, + {name: 'Hour', value: 'hour'}, + {name: 'Day', value: 'day'}, + {name: 'Week', value: 'week'}, + {name: 'Month', value: 'month'}, + {name: 'Quarter', value: 'quarter'}, + {name: 'Year', value: 'year'} + ]; + + this.resultFormats = [ + {text: 'Time series', value: 'time_series'}, + {text: 'Table', value: 'table'}, + ]; + + var target_defaults = { + metricAggs: [ + {type: 'avg', column: 'value'} + ], + groupByColumns: [], + groupByAliases: [], + whereClauses: [], + timeInterval: ds.defaultGroupInterval, + resultFormat: 'time_series' + }; + _.defaults(this.target, target_defaults); + + this.updateGroupByAliases(); + + this.groupBySegments = _.map(this.target.groupByColumns, this.uiSegmentSrv.newSegment); + + // Build WHERE segments + this.whereSegments = []; + this.buildWhereSegments(this.target.whereClauses); + + this.removeWhereSegment = uiSegmentSrv.newSegment({fake: true, value: '-- remove --'}); + this.fixSegments(this.groupBySegments); + } + + crateQuery(query, args = []) { + return this.datasource._sql_query(query, args).then(response => { + return response.rows; + }); + } + + getCollapsedText(): string { + if (this.target.rawQuery) { + return this.target.query; + } else { + return this.crateQueryBuilder.build(this.target); + } + } + + //////////////////// + // Event handlers // + //////////////////// + + onChangeInternal(): void { + this.panelCtrl.refresh(); // Asks the panel to refresh data. + } + + groupBySegmentChanged(segment, index): void { + if (segment.type === 'plus-button') { + segment.type = undefined; + } + this.target.groupByColumns = _.map(_.filter(this.groupBySegments, segment => { + return (segment.type !== 'plus-button' && + segment.value !== this.removeWhereSegment.value); + }), 'value'); + this.groupBySegments = _.map(this.target.groupByColumns, this.uiSegmentSrv.newSegment); + this.groupBySegments.push(this.uiSegmentSrv.newPlusButton()); + + if (segment.value === this.removeWhereSegment.value) { + this.target.groupByAliases.splice(index, 1); + } + this.updateGroupByAliases(); + + this.onChangeInternal(); + } + + onGroupByAliasChange(index) { + this.updateGroupByAliases(); + this.onChangeInternal(); + } + + onAggTypeChange(): void { + this.onChangeInternal(); + } + + addMetricAgg(): void { + this.target.metricAggs.push({ type: 'avg', column: 'value' }); + this.onChangeInternal(); + } + + removeMetricAgg(index): void { + this.target.metricAggs.splice(index, 1); + this.onChangeInternal(); + } + + toggleShowMetric(agg): void { + agg.hide = !agg.hide; + this.onChangeInternal(); + } + + toggleEditorMode(): void { + this.target.rawQuery = !this.target.rawQuery; + } + + /////////////////////// + // Query suggestions // + /////////////////////// + + getColumns(allValue?: boolean, onlyNumeric?: boolean) { + let query; + if (onlyNumeric) { + query = this.crateQueryBuilder.getNumericColumnsQuery(); + } else { + query = this.crateQueryBuilder.getColumnsQuery(); + } + let self = this; + return this.crateQuery(query).then(rows => { + if (allValue) { + rows.splice(0, 0, '*'); + } + return self.transformToSegments(_.flatten(rows), true); + }); + } + + getGroupByColumns() { + return this.getColumns().then(columns => { + columns.splice(0, 0, angular.copy(this.removeWhereSegment)); + return columns; + }); + } + + getValues(column, limit = 10) { + let self = this; + let time_range = this.panelCtrl.range; + return this.crateQuery(this.crateQueryBuilder.getValuesQuery(column, limit, time_range)) + .then(rows => { + return self.transformToSegments(_.flatten(rows), true); + }); + } + + getColumnsOrValues(segment, index) { + var self = this; + if (segment.type === 'condition') { + return this.$q.when([this.uiSegmentSrv.newSegment('AND'), this.uiSegmentSrv.newSegment('OR')]); + } + if (segment.type === 'operator') { + return this.$q.when(this.uiSegmentSrv.newOperators(this.operators)); + } + + if (segment.type === 'key' || segment.type === 'plus-button') { + return this.getColumns().then(columns => { + columns.splice(0, 0, angular.copy(this.removeWhereSegment)); + return columns; + }); + } else if (segment.type === 'value') { + return this.getValues(this.whereSegments[index - 2].value); + } + } + + getMetricAggTypes() { + return queryDef.getMetricAggTypes(); + } + + getMetricAggDef(aggType) { + return _.find(this.getMetricAggTypes(), { value: aggType }); + } + + whereSegmentUpdated(segment, index) { + this.whereSegments[index] = segment; + + if (segment.value === this.removeWhereSegment.value) { + this.whereSegments.splice(index, 3); + if (this.whereSegments.length === 0) { + this.whereSegments.push(this.uiSegmentSrv.newPlusButton()); + } else if (this.whereSegments.length > 2) { + this.whereSegments.splice(Math.max(index - 1, 0), 1); + if (this.whereSegments[this.whereSegments.length - 1].type !== 'plus-button') { + this.whereSegments.push(this.uiSegmentSrv.newPlusButton()); + } + } + } else { + if (segment.type === 'plus-button') { + if (index > 2) { + this.whereSegments.splice(index, 0, this.uiSegmentSrv.newCondition('AND')); + } + this.whereSegments.push(this.uiSegmentSrv.newOperator('=')); + this.whereSegments.push(this.uiSegmentSrv.newFake('select tag value', 'value', 'query-segment-value')); + segment.type = 'key'; + segment.cssClass = 'query-segment-key'; + } + if ((index + 1) === this.whereSegments.length) { + this.whereSegments.push(this.uiSegmentSrv.newPlusButton()); + } + } + + this.buildWhereClauses(); + + // Refresh only if all fields setted + if (_.every(this.whereSegments, segment => { + return ((segment.value || segment.type === 'plus-button') && + !(segment.fake && segment.type !== 'plus-button')); + })) { + this.panelCtrl.refresh(); + } + } + + /////////////////////// + + buildWhereSegments(whereClauses: any): void { + var self = this; + _.forEach(whereClauses, whereClause => { + if (whereClause.condition) { + self.whereSegments.push(self.uiSegmentSrv.newCondition(whereClause.condition)); + } + self.whereSegments.push(self.uiSegmentSrv.newKey(whereClause.column)); + self.whereSegments.push(self.uiSegmentSrv.newOperator(whereClause.operator)); + self.whereSegments.push(self.uiSegmentSrv.newKeyValue(whereClause.value)); + }); + this.fixSegments(this.whereSegments); + } + + buildWhereClauses() { + var i = 0; + var whereIndex = 0; + var segments = this.whereSegments; + var whereClauses = []; + while (segments.length > i && segments[i].type !== 'plus-button') { + if (whereClauses.length < whereIndex + 1) { + whereClauses.push({condition: '', column: '', operator: '', value: ''}); + } + if (segments[i].type === 'condition') { + whereClauses[whereIndex].condition = segments[i].value; + } else if (segments[i].type === 'key') { + whereClauses[whereIndex].column = segments[i].value; + } else if (segments[i].type === 'operator') { + whereClauses[whereIndex].operator = segments[i].value; + } else if (segments[i].type === 'value' || segments[i].type === 'template') { + whereClauses[whereIndex].value = segments[i].value; + whereIndex++; + } + i++; + } + this.target.whereClauses = whereClauses; + } + + fixSegments(segments) { + var count = segments.length; + var lastSegment = segments[Math.max(count-1, 0)]; + + if (!lastSegment || lastSegment.type !== 'plus-button') { + segments.push(this.uiSegmentSrv.newPlusButton()); + } + } + + transformToSegments(results, addTemplateVars?: boolean) { + var segments = _.map(_.flatten(results), value => { + return this.uiSegmentSrv.newSegment({ + value: value.toString(), + expandable: false + }); + }); + + if (addTemplateVars) { + for (let variable of this.templateSrv.variables) { + segments.unshift(this.uiSegmentSrv.newSegment({ type: 'template', value: '$' + variable.name, expandable: true })); + } + } + return segments; + } + + updateGroupByAliases() { + let groupByAliases = new Array(this.target.groupByColumns.length); + this.target.groupByColumns.forEach((column, index) => { + if (this.target.groupByAliases[index]) { + groupByAliases[index] = this.target.groupByAliases[index]; + } else { + groupByAliases[index] = ""; + } + }); + this.target.groupByAliases = groupByAliases; + } + +} diff --git a/deploy/crate-datasource/dist/query_def.d.ts b/deploy/crate-datasource/dist/query_def.d.ts new file mode 100755 index 0000000..d2563cd --- /dev/null +++ b/deploy/crate-datasource/dist/query_def.d.ts @@ -0,0 +1,13 @@ +/// +export default class QueryDef { + static getMetricAggTypes(): ({ + text: string; + value: string; + allValue: boolean; + } | { + text: string; + value: string; + allValue: boolean; + anyDataType: boolean; + })[]; +} diff --git a/deploy/crate-datasource/dist/query_def.js b/deploy/crate-datasource/dist/query_def.js new file mode 100755 index 0000000..ea24a07 --- /dev/null +++ b/deploy/crate-datasource/dist/query_def.js @@ -0,0 +1,32 @@ +/// +System.register([], function(exports_1) { + var _metricAggTypes, QueryDef; + return { + setters:[], + execute: function() { + _metricAggTypes = [ + { text: "Raw", value: "raw", allValue: false }, + { text: "Count", value: 'count', allValue: true, anyDataType: true }, + { text: "Distinct Count", value: 'count_distinct', allValue: false, anyDataType: true }, + { text: "Avg / Mean", value: 'avg', allValue: false }, + { text: "Min", value: 'min', allValue: false }, + { text: "Max", value: 'max', allValue: false }, + { text: "Sum", value: 'sum', allValue: false }, + { text: "Geometric Mean", value: 'geometric_mean', allValue: false }, + { text: "Variance", value: 'variance', allValue: false }, + { text: "Std Deviation", value: 'stddev', allValue: false }, + { text: "Arbitrary", value: "arbitrary", allValue: false } + ]; + QueryDef = (function () { + function QueryDef() { + } + QueryDef.getMetricAggTypes = function () { + return _metricAggTypes; + }; + return QueryDef; + })(); + exports_1("default", QueryDef); + } + } +}); +//# sourceMappingURL=query_def.js.map \ No newline at end of file diff --git a/deploy/crate-datasource/dist/query_def.js.map b/deploy/crate-datasource/dist/query_def.js.map new file mode 100755 index 0000000..b06e553 --- /dev/null +++ b/deploy/crate-datasource/dist/query_def.js.map @@ -0,0 +1 @@ +{"version":3,"file":"query_def.js","sourceRoot":"","sources":["query_def.ts"],"names":["QueryDef","QueryDef.constructor","QueryDef.getMetricAggTypes"],"mappings":"AAAA,8CAA8C;;QAI1C,eAAe;;;;YAAf,eAAe,GAAG;gBACpB,EAAC,IAAI,EAAE,KAAK,EAAa,KAAK,EAAE,KAAK,EAAa,QAAQ,EAAE,KAAK,EAAC;gBAClE,EAAC,IAAI,EAAE,OAAO,EAAW,KAAK,EAAE,OAAO,EAAW,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAC;gBACpF,EAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAC;gBACrF,EAAC,IAAI,EAAE,YAAY,EAAM,KAAK,EAAE,KAAK,EAAa,QAAQ,EAAE,KAAK,EAAC;gBAClE,EAAC,IAAI,EAAE,KAAK,EAAa,KAAK,EAAE,KAAK,EAAa,QAAQ,EAAE,KAAK,EAAC;gBAClE,EAAC,IAAI,EAAE,KAAK,EAAa,KAAK,EAAE,KAAK,EAAa,QAAQ,EAAE,KAAK,EAAC;gBAClE,EAAC,IAAI,EAAE,KAAK,EAAa,KAAK,EAAE,KAAK,EAAa,QAAQ,EAAE,KAAK,EAAC;gBAClE,EAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,KAAK,EAAC;gBAClE,EAAC,IAAI,EAAE,UAAU,EAAQ,KAAK,EAAE,UAAU,EAAQ,QAAQ,EAAE,KAAK,EAAC;gBAClE,EAAC,IAAI,EAAE,eAAe,EAAG,KAAK,EAAE,QAAQ,EAAU,QAAQ,EAAE,KAAK,EAAC;gBAClE,EAAC,IAAI,EAAE,WAAW,EAAO,KAAK,EAAE,WAAW,EAAO,QAAQ,EAAE,KAAK,EAAC;aACnE,CAAC;YAEF;gBAAAA;gBAKAC,CAACA;gBAHQD,0BAAiBA,GAAxBA;oBACEE,MAAMA,CAACA,eAAeA,CAACA;gBACzBA,CAACA;gBACHF,eAACA;YAADA,CAACA,AALD,IAKC;YALD,8BAKC,CAAA"} \ No newline at end of file diff --git a/deploy/crate-datasource/dist/query_def.ts b/deploy/crate-datasource/dist/query_def.ts new file mode 100755 index 0000000..9396ff2 --- /dev/null +++ b/deploy/crate-datasource/dist/query_def.ts @@ -0,0 +1,24 @@ +/// + +import _ from 'lodash'; + +let _metricAggTypes = [ + {text: "Raw", value: "raw", allValue: false}, + {text: "Count", value: 'count', allValue: true, anyDataType: true}, + {text: "Distinct Count", value: 'count_distinct', allValue: false, anyDataType: true}, + {text: "Avg / Mean", value: 'avg', allValue: false}, + {text: "Min", value: 'min', allValue: false}, + {text: "Max", value: 'max', allValue: false}, + {text: "Sum", value: 'sum', allValue: false}, + {text: "Geometric Mean", value: 'geometric_mean', allValue: false}, + {text: "Variance", value: 'variance', allValue: false}, + {text: "Std Deviation", value: 'stddev', allValue: false}, + {text: "Arbitrary", value: "arbitrary", allValue: false} +]; + +export default class QueryDef { + + static getMetricAggTypes() { + return _metricAggTypes; + } +} diff --git a/deploy/crate-datasource/dist/response_handler.d.ts b/deploy/crate-datasource/dist/response_handler.d.ts new file mode 100755 index 0000000..9ff9e54 --- /dev/null +++ b/deploy/crate-datasource/dist/response_handler.d.ts @@ -0,0 +1,2 @@ +/// +export default function handleResponse(target: any, result: any): any; diff --git a/deploy/crate-datasource/dist/response_handler.js b/deploy/crate-datasource/dist/response_handler.js new file mode 100755 index 0000000..27c7c8b --- /dev/null +++ b/deploy/crate-datasource/dist/response_handler.js @@ -0,0 +1,148 @@ +/// +System.register(['lodash'], function(exports_1) { + var lodash_1; + function handleResponse(target, result) { + if (target.resultFormat === 'table') { + return handleTableResponse(target, result); + } + if (target.rawQuery) { + return handleRawResponse(target, result); + } + else { + return handleBuildedResponse(target, result); + } + } + exports_1("default", handleResponse); + function handleTableResponse(target, result) { + return { + columns: lodash_1["default"].map(result.cols, function (col) { + return { text: col }; + }), + rows: result.rows, + type: 'table' + }; + } + function handleRawResponse(target, result) { + var columns = result.cols; + var timeColumnIndex = 0; + var valueColumnIndex = 1; + if (columns.length > 2) { + var groupedResponse = lodash_1["default"].groupBy(result.rows, function (row) { + // Assume row structure is + // [ts, value, ...group by columns] + return row.slice(2).join(' '); + }); + return lodash_1["default"].map(groupedResponse, function (rows, key) { + return { + target: key + ': ' + columns[valueColumnIndex], + datapoints: convertToGrafanaPoints(rows, timeColumnIndex, valueColumnIndex) + }; + }); + } + else { + return [{ + target: columns[valueColumnIndex], + datapoints: convertToGrafanaPoints(result.rows, timeColumnIndex, valueColumnIndex) + }]; + } + } + function handleBuildedResponse(target, result) { + var columns = result.cols; + var timeColumnIndex = 0; + var groupByColumnIndexes, selectColumnIndexes; + if (target.groupByColumns.length) { + groupByColumnIndexes = lodash_1["default"].map(target.groupByColumns, function (groupByCol) { + return lodash_1["default"].indexOf(columns, groupByCol); + }); + } + var enabledAggs = lodash_1["default"].filter(target.metricAggs, function (agg) { + return !agg.hide; + }); + if (enabledAggs.length) { + selectColumnIndexes = lodash_1["default"].map(enabledAggs, function (metricAgg, index) { + return index + 1; + }); + } + else { + return []; + } + if (groupByColumnIndexes && groupByColumnIndexes.length && !lodash_1["default"].some(groupByColumnIndexes, -1)) { + var groupedResponse = lodash_1["default"].groupBy(result.rows, function (row) { + // Construct groupBy key from Group By columns, for example: + // [metric, host] => 'metric host' + return lodash_1["default"].map(groupByColumnIndexes, function (columnIndex) { + return row[columnIndex]; + }).join(' '); + }); + return lodash_1["default"].flatten(lodash_1["default"].map(groupedResponse, function (rows, key) { + return lodash_1["default"].map(selectColumnIndexes, function (valueIndex) { + var datapoints = convertToGrafanaPoints(rows, timeColumnIndex, valueIndex); + // Build alias for Group By column values + var group_by_alias; + if (rows.length) { + group_by_alias = lodash_1["default"].map(groupByColumnIndexes, function (columnIndex, i) { + var first_row = rows[0]; + if (target.groupByAliases && target.groupByAliases[i]) { + var pattern = new RegExp(target.groupByAliases[i]); + var match = pattern.exec(first_row[columnIndex]); + if (match && match.length > 1) { + return match[1]; + } + else if (match) { + return match[0]; + } + else { + return first_row[columnIndex]; + } + } + else { + return first_row[columnIndex]; + } + }).join(' '); + } + else { + group_by_alias = key; + } + return { + target: group_by_alias + ': ' + columns[valueIndex], + datapoints: datapoints + }; + }); + })); + } + else { + return lodash_1["default"].map(selectColumnIndexes, function (valueIndex) { + var datapoints = convertToGrafanaPoints(result.rows, timeColumnIndex, valueIndex); + return { + target: columns[valueIndex], + datapoints: datapoints + }; + }); + } + } + function convertToGrafanaPoints(rows, timeColumnIndex, valueColumnIndex) { + return lodash_1["default"].map(rows, function (row) { + var ts = Number(row[timeColumnIndex]); + var val = row[valueColumnIndex]; + val = val !== null ? Number(val) : null; + return [val, ts]; + }); + } + function makeColName(aggType, column) { + if (aggType === 'count_distinct') { + return 'count(DISTINCT ' + column + ')'; + } + else { + return aggType + '(' + column + ')'; + } + } + return { + setters:[ + function (lodash_1_1) { + lodash_1 = lodash_1_1; + }], + execute: function() { + } + } +}); +//# sourceMappingURL=response_handler.js.map \ No newline at end of file diff --git a/deploy/crate-datasource/dist/response_handler.js.map b/deploy/crate-datasource/dist/response_handler.js.map new file mode 100755 index 0000000..a82311f --- /dev/null +++ b/deploy/crate-datasource/dist/response_handler.js.map @@ -0,0 +1 @@ +{"version":3,"file":"response_handler.js","sourceRoot":"","sources":["response_handler.ts"],"names":["handleResponse","handleTableResponse","handleRawResponse","handleBuildedResponse","convertToGrafanaPoints","makeColName"],"mappings":"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CAACA,cAAcA,CAACA,CAACA,CAACA,CAACA,CAACA,CAACA;gCACtDA,IAAIA,OAAOA,GAAGA,IAAIA,MAAMA,CAACA,MAAMA,CAACA,cAAcA,CAACA,CAACA,CAACA,CAACA,CAACA;gCACnDA,IAAIA,KAAKA,GAAGA,OAAOA,CAACA,IAAIA,CAACA,SAASA,CAACA,WAAWA,CAACA,CAACA,CAACA;gCACjDA,EAAEA,CAACA,CAACA,KAAKA,IAAIA,KAAKA,CAACA,MAAMA,GAAGA,CAACA,CAACA,CAACA,CAACA;oCAC9BA,MAAMA,CAACA,KAAKA,CAACA,CAACA,CAACA,CAACA;gCAClBA,CAACA;gCAACA,IAAIA,CAACA,EAAEA,CAACA,CAACA,KAAKA,CAACA,CAAAA,CAACA;oCAChBA,MAAMA,CAACA,KAAKA,CAACA,CAACA,CAACA,CAACA;gCAClBA,CAACA;gCAACA,IAAIA,CAACA,CAACA;oCACNA,MAAMA,CAACA,SAASA,CAACA,WAAWA,CAACA,CAACA;gCAChCA,CAACA;4BACHA,CAACA;4BAACA,IAAIA,CAACA,CAACA;gCACNA,MAAMA,CAACA,SAASA,CAACA,WAAWA,CAACA,CAACA;4BAChCA,CAACA;wBACHA,CAACA,CAACA,CAACA,IAAIA,CAACA,GAAGA,CAACA,CAACA;oBACfA,CAACA;oBAACA,IAAIA,CAACA,CAACA;wBACNA,cAAcA,GAAGA,GAAGA,CAACA;oBACvBA,CAACA;oBAEDA,MAAMA,CAACA;wBACLA,MAAMA,EAAEA,cAAcA,GAAGA,IAAIA,GAAGA,OAAOA,CAACA,UAAUA,CAACA;wBACnDA,UAAUA,EAAEA,UAAUA;qBACvBA,CAACA;gBACJA,CAACA,CAACA,CAACA;YACLA,CAACA,CAACA,CAACA,CAACA;QACNA,CAACA;QAACA,IAAIA,CAACA,CAACA;YACNA,MAAMA,CAACA,mBAACA,CAACA,GAAGA,CAACA,mBAAmBA,EAAEA,UAACA,UAAUA;gBAC3CA,IAAIA,UAAUA,GAAGA,sBAAsBA,CAACA,MAAMA,CAACA,IAAIA,EAAEA,eAAeA,EAAEA,UAAUA,CAACA,CAACA;gBAElFA,MAAMA,CAACA;oBACLA,MAAMA,EAAEA,OAAOA,CAACA,UAAUA,CAACA;oBAC3BA,UAAUA,EAAEA,UAAUA;iBACvBA,CAACA;YACJA,CAACA,CAACA,CAACA;QACLA,CAACA;IACHA,CAACA;IAED,gCAAgC,IAAI,EAAE,eAAe,EAAE,gBAAgB;QACrEC,MAAMA,CAACA,mBAACA,CAACA,GAAGA,CAACA,IAAIA,EAAEA,UAAAA,GAAGA;YACpBA,IAAIA,EAAEA,GAAGA,MAAMA,CAACA,GAAGA,CAACA,eAAeA,CAACA,CAACA,CAACA;YACtCA,IAAIA,GAAGA,GAAGA,GAAGA,CAACA,gBAAgBA,CAACA,CAACA;YAChCA,GAAGA,GAAGA,GAAGA,KAAKA,IAAIA,GAAGA,MAAMA,CAACA,GAAGA,CAACA,GAAGA,IAAIA,CAACA;YAExCA,MAAMA,CAACA,CAACA,GAAGA,EAAEA,EAAEA,CAACA,CAACA;QACnBA,CAACA,CAACA,CAACA;IACLA,CAACA;IAED,qBAAqB,OAAO,EAAE,MAAM;QAClCC,EAAEA,CAACA,CAACA,OAAOA,KAAKA,gBAAgBA,CAACA,CAACA,CAACA;YACjCA,MAAMA,CAACA,iBAAiBA,GAAGA,MAAMA,GAAGA,GAAGA,CAACA;QAC1CA,CAACA;QAACA,IAAIA,CAACA,CAACA;YACNA,MAAMA,CAACA,OAAOA,GAAGA,GAAGA,GAAGA,MAAMA,GAAGA,GAAGA,CAACA;QACtCA,CAACA;IACHA,CAACA"} \ No newline at end of file diff --git a/deploy/crate-datasource/dist/response_handler.ts b/deploy/crate-datasource/dist/response_handler.ts new file mode 100755 index 0000000..1a7fdaf --- /dev/null +++ b/deploy/crate-datasource/dist/response_handler.ts @@ -0,0 +1,146 @@ +/// + +import _ from 'lodash'; + +export default function handleResponse(target, result) { + if (target.resultFormat === 'table') { + return handleTableResponse(target, result); + } + + if (target.rawQuery) { + return handleRawResponse(target, result); + } else { + return handleBuildedResponse(target, result); + } +} + +function handleTableResponse(target, result) { + return { + columns: _.map(result.cols, col => { + return {text: col}; + }), + rows: result.rows, + type: 'table' + }; +} + +function handleRawResponse(target, result) { + let columns = result.cols; + let timeColumnIndex = 0; + let valueColumnIndex = 1; + + if (columns.length > 2) { + let groupedResponse = _.groupBy(result.rows, row => { + // Assume row structure is + // [ts, value, ...group by columns] + return row.slice(2).join(' '); + }); + + return _.map(groupedResponse, (rows, key) => { + return { + target: key + ': ' + columns[valueColumnIndex], + datapoints: convertToGrafanaPoints(rows, timeColumnIndex, valueColumnIndex) + }; + }); + } else { + return [{ + target: columns[valueColumnIndex], + datapoints: convertToGrafanaPoints(result.rows, timeColumnIndex, valueColumnIndex) + }]; + } +} + +function handleBuildedResponse(target, result) { + let columns = result.cols; + let timeColumnIndex = 0; + let groupByColumnIndexes: number[], selectColumnIndexes: number[]; + + if (target.groupByColumns.length) { + groupByColumnIndexes = _.map(target.groupByColumns, groupByCol => { + return _.indexOf(columns, groupByCol); + }); + } + + let enabledAggs = _.filter(target.metricAggs, (agg) => { + return !agg.hide; + }); + + if (enabledAggs.length) { + selectColumnIndexes = _.map(enabledAggs, (metricAgg, index) => { + return index + 1; + }); + } else { + return []; + } + + if (groupByColumnIndexes && groupByColumnIndexes.length && !_.some(groupByColumnIndexes, -1)) { + let groupedResponse = _.groupBy(result.rows, row => { + // Construct groupBy key from Group By columns, for example: + // [metric, host] => 'metric host' + return _.map(groupByColumnIndexes, columnIndex => { + return row[columnIndex]; + }).join(' '); + }); + + return _.flatten(_.map(groupedResponse, (rows, key) => { + return _.map(selectColumnIndexes, (valueIndex) => { + let datapoints = convertToGrafanaPoints(rows, timeColumnIndex, valueIndex); + + // Build alias for Group By column values + let group_by_alias: string; + if (rows.length) { + group_by_alias = _.map(groupByColumnIndexes, (columnIndex, i) => { + let first_row = rows[0]; + if (target.groupByAliases && target.groupByAliases[i]) { + let pattern = new RegExp(target.groupByAliases[i]); + let match = pattern.exec(first_row[columnIndex]); + if (match && match.length > 1) { + return match[1]; + } else if (match){ + return match[0]; + } else { + return first_row[columnIndex]; + } + } else { + return first_row[columnIndex]; + } + }).join(' '); + } else { + group_by_alias = key; + } + + return { + target: group_by_alias + ': ' + columns[valueIndex], + datapoints: datapoints + }; + }); + })); + } else { + return _.map(selectColumnIndexes, (valueIndex) => { + let datapoints = convertToGrafanaPoints(result.rows, timeColumnIndex, valueIndex); + + return { + target: columns[valueIndex], + datapoints: datapoints + }; + }); + } +} + +function convertToGrafanaPoints(rows, timeColumnIndex, valueColumnIndex) { + return _.map(rows, row => { + let ts = Number(row[timeColumnIndex]); + let val = row[valueColumnIndex]; + val = val !== null ? Number(val) : null; + + return [val, ts]; + }); +} + +function makeColName(aggType, column) { + if (aggType === 'count_distinct') { + return 'count(DISTINCT ' + column + ')'; + } else { + return aggType + '(' + column + ')'; + } +} diff --git a/deploy/crate-datasource/dist/sdk/query_ctrl.d.ts b/deploy/crate-datasource/dist/sdk/query_ctrl.d.ts new file mode 100755 index 0000000..fd36cf1 --- /dev/null +++ b/deploy/crate-datasource/dist/sdk/query_ctrl.d.ts @@ -0,0 +1,13 @@ +/// +export declare class QueryCtrl { + $scope: any; + private $injector; + target: any; + datasource: any; + panelCtrl: any; + panel: any; + hasRawMode: boolean; + error: string; + constructor($scope: any, $injector: any); + refresh(): void; +} diff --git a/deploy/crate-datasource/dist/sdk/query_ctrl.js b/deploy/crate-datasource/dist/sdk/query_ctrl.js new file mode 100755 index 0000000..a203fc2 --- /dev/null +++ b/deploy/crate-datasource/dist/sdk/query_ctrl.js @@ -0,0 +1,22 @@ +/// +System.register([], function(exports_1) { + var QueryCtrl; + return { + setters:[], + execute: function() { + QueryCtrl = (function () { + function QueryCtrl($scope, $injector) { + this.$scope = $scope; + this.$injector = $injector; + this.panel = this.panelCtrl.panel; + } + QueryCtrl.prototype.refresh = function () { + this.panelCtrl.refresh(); + }; + return QueryCtrl; + })(); + exports_1("QueryCtrl", QueryCtrl); + } + } +}); +//# sourceMappingURL=query_ctrl.js.map \ No newline at end of file diff --git a/deploy/crate-datasource/dist/sdk/query_ctrl.js.map b/deploy/crate-datasource/dist/sdk/query_ctrl.js.map new file mode 100755 index 0000000..8f5d09f --- /dev/null +++ b/deploy/crate-datasource/dist/sdk/query_ctrl.js.map @@ -0,0 +1 @@ +{"version":3,"file":"query_ctrl.js","sourceRoot":"","sources":["query_ctrl.ts"],"names":["QueryCtrl","QueryCtrl.constructor","QueryCtrl.refresh"],"mappings":"AAAA,iDAAiD;;;;;;YAKjD;gBAQEA,mBAAmBA,MAAMA,EAAUA,SAASA;oBAAzBC,WAAMA,GAANA,MAAMA,CAAAA;oBAAUA,cAASA,GAATA,SAASA,CAAAA;oBAC1CA,IAAIA,CAACA,KAAKA,GAAGA,IAAIA,CAACA,SAASA,CAACA,KAAKA,CAACA;gBACpCA,CAACA;gBAEDD,2BAAOA,GAAPA;oBACEE,IAAIA,CAACA,SAASA,CAACA,OAAOA,EAAEA,CAACA;gBAC3BA,CAACA;gBAEHF,gBAACA;YAADA,CAACA,AAhBD,IAgBC;YAhBD,iCAgBC,CAAA"} \ No newline at end of file diff --git a/deploy/crate-datasource/dist/sdk/query_ctrl.ts b/deploy/crate-datasource/dist/sdk/query_ctrl.ts new file mode 100755 index 0000000..67f4f93 --- /dev/null +++ b/deploy/crate-datasource/dist/sdk/query_ctrl.ts @@ -0,0 +1,23 @@ +/// + +import angular from 'angular'; +import _ from 'lodash'; + +export class QueryCtrl { + target: any; + datasource: any; + panelCtrl: any; + panel: any; + hasRawMode: boolean; + error: string; + + constructor(public $scope, private $injector) { + this.panel = this.panelCtrl.panel; + } + + refresh() { + this.panelCtrl.refresh(); + } + +} + diff --git a/deploy/crate-datasource/dist/sdk/sdk.d.ts b/deploy/crate-datasource/dist/sdk/sdk.d.ts new file mode 100755 index 0000000..33023c3 --- /dev/null +++ b/deploy/crate-datasource/dist/sdk/sdk.d.ts @@ -0,0 +1,3 @@ +import { QueryCtrl } from './query_ctrl'; +export declare function loadPluginCss(options: any): void; +export { QueryCtrl }; diff --git a/deploy/crate-datasource/dist/sdk/sdk.js b/deploy/crate-datasource/dist/sdk/sdk.js new file mode 100755 index 0000000..555a2a2 --- /dev/null +++ b/deploy/crate-datasource/dist/sdk/sdk.js @@ -0,0 +1,25 @@ +System.register(['./query_ctrl', 'app/core/config'], function(exports_1) { + var query_ctrl_1, config_1; + function loadPluginCss(options) { + if (config_1["default"].bootData.user.lightTheme) { + System.import(options.light + '!css'); + } + else { + System.import(options.dark + '!css'); + } + } + exports_1("loadPluginCss", loadPluginCss); + return { + setters:[ + function (query_ctrl_1_1) { + query_ctrl_1 = query_ctrl_1_1; + }, + function (config_1_1) { + config_1 = config_1_1; + }], + execute: function() { + exports_1("QueryCtrl", query_ctrl_1.QueryCtrl); + } + } +}); +//# sourceMappingURL=sdk.js.map \ No newline at end of file diff --git a/deploy/crate-datasource/dist/sdk/sdk.js.map b/deploy/crate-datasource/dist/sdk/sdk.js.map new file mode 100755 index 0000000..a608af4 --- /dev/null +++ b/deploy/crate-datasource/dist/sdk/sdk.js.map @@ -0,0 +1 @@ +{"version":3,"file":"sdk.js","sourceRoot":"","sources":["sdk.ts"],"names":["loadPluginCss"],"mappings":";;IAIA,uBAA8B,OAAO;QACnCA,EAAEA,CAACA,CAACA,mBAAMA,CAACA,QAAQA,CAACA,IAAIA,CAACA,UAAUA,CAACA,CAACA,CAACA;YACpCA,MAAMA,CAACA,MAAMA,CAACA,OAAOA,CAACA,KAAKA,GAAGA,MAAMA,CAACA,CAACA;QACxCA,CAACA;QAACA,IAAIA,CAACA,CAACA;YACNA,MAAMA,CAACA,MAAMA,CAACA,OAAOA,CAACA,IAAIA,GAAGA,MAAMA,CAACA,CAACA;QACvCA,CAACA;IACHA,CAACA;IAND,yCAMC,CAAA;;;;;;;;;;YAGC,8CAAS"} \ No newline at end of file diff --git a/deploy/crate-datasource/dist/sdk/sdk.ts b/deploy/crate-datasource/dist/sdk/sdk.ts new file mode 100755 index 0000000..37ed221 --- /dev/null +++ b/deploy/crate-datasource/dist/sdk/sdk.ts @@ -0,0 +1,15 @@ +import {QueryCtrl} from './query_ctrl'; + +import config from 'app/core/config'; + +export function loadPluginCss(options) { + if (config.bootData.user.lightTheme) { + System.import(options.light + '!css'); + } else { + System.import(options.dark + '!css'); + } +} + +export { + QueryCtrl +} diff --git a/deploy/crate-datasource/headers/common.d.ts b/deploy/crate-datasource/headers/common.d.ts new file mode 100755 index 0000000..2ef4ae5 --- /dev/null +++ b/deploy/crate-datasource/headers/common.d.ts @@ -0,0 +1,61 @@ +/// + +declare var System: any; + +// dummy modules +declare module 'app/core/config' { + var config: any; + export default config; +} + +declare module 'lodash' { + var lodash: any; + export default lodash; +} + +declare module 'moment' { + var moment: any; + export default moment; +} + +declare module 'angular' { + var angular: any; + export default angular; +} + +declare module 'jquery' { + var jquery: any; + export default jquery; +} + +declare module 'app/core/utils/kbn' { + var kbn: any; + export default kbn; +} + +// Hack for datemath module +declare module 'app/core/utils/datemath' { + export var parse: any; + export var isValid: any; + export var parseDateMath: any; +} + +declare module 'app/core/store' { + var store: any; + export default store; +} + +declare module 'tether' { + var config: any; + export default config; +} + +declare module 'tether-drop' { + var config: any; + export default config; +} + +declare module 'eventemitter3' { + var config: any; + export default config; +} diff --git a/deploy/crate-datasource/headers/es6-shim/es6-shim.d.ts b/deploy/crate-datasource/headers/es6-shim/es6-shim.d.ts new file mode 100755 index 0000000..265c19e --- /dev/null +++ b/deploy/crate-datasource/headers/es6-shim/es6-shim.d.ts @@ -0,0 +1,670 @@ +// Generated by typings +// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/7de6c3dd94feaeb21f20054b9f30d5dabc5efabd/es6-shim/es6-shim.d.ts +// Type definitions for es6-shim v0.31.2 +// Project: https://github.com/paulmillr/es6-shim +// Definitions by: Ron Buckton +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +declare type PropertyKey = string | number | symbol; + +interface IteratorResult { + done: boolean; + value?: T; +} + +interface IterableShim { + /** + * Shim for an ES6 iterable. Not intended for direct use by user code. + */ + "_es6-shim iterator_"(): Iterator; +} + +interface Iterator { + next(value?: any): IteratorResult; + return?(value?: any): IteratorResult; + throw?(e?: any): IteratorResult; +} + +interface IterableIteratorShim extends IterableShim, Iterator { + /** + * Shim for an ES6 iterable iterator. Not intended for direct use by user code. + */ + "_es6-shim iterator_"(): IterableIteratorShim; +} + +interface StringConstructor { + /** + * Return the String value whose elements are, in order, the elements in the List elements. + * If length is 0, the empty string is returned. + */ + fromCodePoint(...codePoints: number[]): string; + + /** + * String.raw is intended for use as a tag function of a Tagged Template String. When called + * as such the first argument will be a well formed template call site object and the rest + * parameter will contain the substitution values. + * @param template A well-formed template string call site representation. + * @param substitutions A set of substitution values. + */ + raw(template: TemplateStringsArray, ...substitutions: any[]): string; +} + +interface String { + /** + * Returns a nonnegative integer Number less than 1114112 (0x110000) that is the code point + * value of the UTF-16 encoded code point starting at the string element at position pos in + * the String resulting from converting this object to a String. + * If there is no element at that position, the result is undefined. + * If a valid UTF-16 surrogate pair does not begin at pos, the result is the code unit at pos. + */ + codePointAt(pos: number): number; + + /** + * Returns true if searchString appears as a substring of the result of converting this + * object to a String, at one or more positions that are + * greater than or equal to position; otherwise, returns false. + * @param searchString search string + * @param position If position is undefined, 0 is assumed, so as to search all of the String. + */ + includes(searchString: string, position?: number): boolean; + + /** + * Returns true if the sequence of elements of searchString converted to a String is the + * same as the corresponding elements of this object (converted to a String) starting at + * endPosition – length(this). Otherwise returns false. + */ + endsWith(searchString: string, endPosition?: number): boolean; + + /** + * Returns a String value that is made from count copies appended together. If count is 0, + * T is the empty String is returned. + * @param count number of copies to append + */ + repeat(count: number): string; + + /** + * Returns true if the sequence of elements of searchString converted to a String is the + * same as the corresponding elements of this object (converted to a String) starting at + * position. Otherwise returns false. + */ + startsWith(searchString: string, position?: number): boolean; + + /** + * Returns an HTML anchor element and sets the name attribute to the text value + * @param name + */ + anchor(name: string): string; + + /** Returns a HTML element */ + big(): string; + + /** Returns a HTML element */ + blink(): string; + + /** Returns a HTML element */ + bold(): string; + + /** Returns a HTML element */ + fixed(): string + + /** Returns a HTML element and sets the color attribute value */ + fontcolor(color: string): string + + /** Returns a HTML element and sets the size attribute value */ + fontsize(size: number): string; + + /** Returns a HTML element and sets the size attribute value */ + fontsize(size: string): string; + + /** Returns an HTML element */ + italics(): string; + + /** Returns an HTML element and sets the href attribute value */ + link(url: string): string; + + /** Returns a HTML element */ + small(): string; + + /** Returns a HTML element */ + strike(): string; + + /** Returns a HTML element */ + sub(): string; + + /** Returns a HTML element */ + sup(): string; + + /** + * Shim for an ES6 iterable. Not intended for direct use by user code. + */ + "_es6-shim iterator_"(): IterableIteratorShim; +} + +interface ArrayConstructor { + /** + * Creates an array from an array-like object. + * @param arrayLike An array-like object to convert to an array. + * @param mapfn A mapping function to call on every element of the array. + * @param thisArg Value of 'this' used to invoke the mapfn. + */ + from(arrayLike: ArrayLike, mapfn: (v: T, k: number) => U, thisArg?: any): Array; + + /** + * Creates an array from an iterable object. + * @param iterable An iterable object to convert to an array. + * @param mapfn A mapping function to call on every element of the array. + * @param thisArg Value of 'this' used to invoke the mapfn. + */ + from(iterable: IterableShim, mapfn: (v: T, k: number) => U, thisArg?: any): Array; + + /** + * Creates an array from an array-like object. + * @param arrayLike An array-like object to convert to an array. + */ + from(arrayLike: ArrayLike): Array; + + /** + * Creates an array from an iterable object. + * @param iterable An iterable object to convert to an array. + */ + from(iterable: IterableShim): Array; + + /** + * Returns a new array from a set of elements. + * @param items A set of elements to include in the new array object. + */ + of(...items: T[]): Array; +} + +interface Array { + /** + * Returns the value of the first element in the array where predicate is true, and undefined + * otherwise. + * @param predicate find calls predicate once for each element of the array, in ascending + * order, until it finds one where predicate returns true. If such an element is found, find + * immediately returns that element value. Otherwise, find returns undefined. + * @param thisArg If provided, it will be used as the this value for each invocation of + * predicate. If it is not provided, undefined is used instead. + */ + find(predicate: (value: T, index: number, obj: Array) => boolean, thisArg?: any): T; + + /** + * Returns the index of the first element in the array where predicate is true, and undefined + * otherwise. + * @param predicate find calls predicate once for each element of the array, in ascending + * order, until it finds one where predicate returns true. If such an element is found, find + * immediately returns that element value. Otherwise, find returns undefined. + * @param thisArg If provided, it will be used as the this value for each invocation of + * predicate. If it is not provided, undefined is used instead. + */ + findIndex(predicate: (value: T) => boolean, thisArg?: any): number; + + /** + * Returns the this object after filling the section identified by start and end with value + * @param value value to fill array section with + * @param start index to start filling the array at. If start is negative, it is treated as + * length+start where length is the length of the array. + * @param end index to stop filling the array at. If end is negative, it is treated as + * length+end. + */ + fill(value: T, start?: number, end?: number): T[]; + + /** + * Returns the this object after copying a section of the array identified by start and end + * to the same array starting at position target + * @param target If target is negative, it is treated as length+target where length is the + * length of the array. + * @param start If start is negative, it is treated as length+start. If end is negative, it + * is treated as length+end. + * @param end If not specified, length of the this object is used as its default value. + */ + copyWithin(target: number, start: number, end?: number): T[]; + + /** + * Returns an array of key, value pairs for every entry in the array + */ + entries(): IterableIteratorShim<[number, T]>; + + /** + * Returns an list of keys in the array + */ + keys(): IterableIteratorShim; + + /** + * Returns an list of values in the array + */ + values(): IterableIteratorShim; + + /** + * Shim for an ES6 iterable. Not intended for direct use by user code. + */ + "_es6-shim iterator_"(): IterableIteratorShim; +} + +interface NumberConstructor { + /** + * The value of Number.EPSILON is the difference between 1 and the smallest value greater than 1 + * that is representable as a Number value, which is approximately: + * 2.2204460492503130808472633361816 x 10‍−‍16. + */ + EPSILON: number; + + /** + * Returns true if passed value is finite. + * Unlike the global isFininte, Number.isFinite doesn't forcibly convert the parameter to a + * number. Only finite values of the type number, result in true. + * @param number A numeric value. + */ + isFinite(number: number): boolean; + + /** + * Returns true if the value passed is an integer, false otherwise. + * @param number A numeric value. + */ + isInteger(number: number): boolean; + + /** + * Returns a Boolean value that indicates whether a value is the reserved value NaN (not a + * number). Unlike the global isNaN(), Number.isNaN() doesn't forcefully convert the parameter + * to a number. Only values of the type number, that are also NaN, result in true. + * @param number A numeric value. + */ + isNaN(number: number): boolean; + + /** + * Returns true if the value passed is a safe integer. + * @param number A numeric value. + */ + isSafeInteger(number: number): boolean; + + /** + * The value of the largest integer n such that n and n + 1 are both exactly representable as + * a Number value. + * The value of Number.MIN_SAFE_INTEGER is 9007199254740991 2^53 − 1. + */ + MAX_SAFE_INTEGER: number; + + /** + * The value of the smallest integer n such that n and n − 1 are both exactly representable as + * a Number value. + * The value of Number.MIN_SAFE_INTEGER is −9007199254740991 (−(2^53 − 1)). + */ + MIN_SAFE_INTEGER: number; + + /** + * Converts a string to a floating-point number. + * @param string A string that contains a floating-point number. + */ + parseFloat(string: string): number; + + /** + * Converts A string to an integer. + * @param s A string to convert into a number. + * @param radix A value between 2 and 36 that specifies the base of the number in numString. + * If this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal. + * All other strings are considered decimal. + */ + parseInt(string: string, radix?: number): number; +} + +interface ObjectConstructor { + /** + * Copy the values of all of the enumerable own properties from one or more source objects to a + * target object. Returns the target object. + * @param target The target object to copy to. + * @param sources One or more source objects to copy properties from. + */ + assign(target: any, ...sources: any[]): any; + + /** + * Returns true if the values are the same value, false otherwise. + * @param value1 The first value. + * @param value2 The second value. + */ + is(value1: any, value2: any): boolean; + + /** + * Sets the prototype of a specified object o to object proto or null. Returns the object o. + * @param o The object to change its prototype. + * @param proto The value of the new prototype or null. + * @remarks Requires `__proto__` support. + */ + setPrototypeOf(o: any, proto: any): any; +} + +interface RegExp { + /** + * Returns a string indicating the flags of the regular expression in question. This field is read-only. + * The characters in this string are sequenced and concatenated in the following order: + * + * - "g" for global + * - "i" for ignoreCase + * - "m" for multiline + * - "u" for unicode + * - "y" for sticky + * + * If no flags are set, the value is the empty string. + */ + flags: string; +} + +interface Math { + /** + * Returns the number of leading zero bits in the 32-bit binary representation of a number. + * @param x A numeric expression. + */ + clz32(x: number): number; + + /** + * Returns the result of 32-bit multiplication of two numbers. + * @param x First number + * @param y Second number + */ + imul(x: number, y: number): number; + + /** + * Returns the sign of the x, indicating whether x is positive, negative or zero. + * @param x The numeric expression to test + */ + sign(x: number): number; + + /** + * Returns the base 10 logarithm of a number. + * @param x A numeric expression. + */ + log10(x: number): number; + + /** + * Returns the base 2 logarithm of a number. + * @param x A numeric expression. + */ + log2(x: number): number; + + /** + * Returns the natural logarithm of 1 + x. + * @param x A numeric expression. + */ + log1p(x: number): number; + + /** + * Returns the result of (e^x - 1) of x (e raised to the power of x, where e is the base of + * the natural logarithms). + * @param x A numeric expression. + */ + expm1(x: number): number; + + /** + * Returns the hyperbolic cosine of a number. + * @param x A numeric expression that contains an angle measured in radians. + */ + cosh(x: number): number; + + /** + * Returns the hyperbolic sine of a number. + * @param x A numeric expression that contains an angle measured in radians. + */ + sinh(x: number): number; + + /** + * Returns the hyperbolic tangent of a number. + * @param x A numeric expression that contains an angle measured in radians. + */ + tanh(x: number): number; + + /** + * Returns the inverse hyperbolic cosine of a number. + * @param x A numeric expression that contains an angle measured in radians. + */ + acosh(x: number): number; + + /** + * Returns the inverse hyperbolic sine of a number. + * @param x A numeric expression that contains an angle measured in radians. + */ + asinh(x: number): number; + + /** + * Returns the inverse hyperbolic tangent of a number. + * @param x A numeric expression that contains an angle measured in radians. + */ + atanh(x: number): number; + + /** + * Returns the square root of the sum of squares of its arguments. + * @param values Values to compute the square root for. + * If no arguments are passed, the result is +0. + * If there is only one argument, the result is the absolute value. + * If any argument is +Infinity or -Infinity, the result is +Infinity. + * If any argument is NaN, the result is NaN. + * If all arguments are either +0 or −0, the result is +0. + */ + hypot(...values: number[]): number; + + /** + * Returns the integral part of the a numeric expression, x, removing any fractional digits. + * If x is already an integer, the result is x. + * @param x A numeric expression. + */ + trunc(x: number): number; + + /** + * Returns the nearest single precision float representation of a number. + * @param x A numeric expression. + */ + fround(x: number): number; + + /** + * Returns an implementation-dependent approximation to the cube root of number. + * @param x A numeric expression. + */ + cbrt(x: number): number; +} + +interface PromiseLike { + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then(onfulfilled?: (value: T) => TResult | PromiseLike, onrejected?: (reason: any) => TResult | PromiseLike): PromiseLike; + then(onfulfilled?: (value: T) => TResult | PromiseLike, onrejected?: (reason: any) => void): PromiseLike; +} + +/** + * Represents the completion of an asynchronous operation + */ +interface Promise { + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then(onfulfilled?: (value: T) => TResult | PromiseLike, onrejected?: (reason: any) => TResult | PromiseLike): Promise; + then(onfulfilled?: (value: T) => TResult | PromiseLike, onrejected?: (reason: any) => void): Promise; + + /** + * Attaches a callback for only the rejection of the Promise. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of the callback. + */ + catch(onrejected?: (reason: any) => T | PromiseLike): Promise; + catch(onrejected?: (reason: any) => void): Promise; +} + +interface PromiseConstructor { + /** + * A reference to the prototype. + */ + prototype: Promise; + + /** + * Creates a new Promise. + * @param executor A callback used to initialize the promise. This callback is passed two arguments: + * a resolve callback used resolve the promise with a value or the result of another promise, + * and a reject callback used to reject the promise with a provided reason or error. + */ + new (executor: (resolve: (value?: T | PromiseLike) => void, reject: (reason?: any) => void) => void): Promise; + + /** + * Creates a Promise that is resolved with an array of results when all of the provided Promises + * resolve, or rejected when any Promise is rejected. + * @param values An array of Promises. + * @returns A new Promise. + */ + all(values: IterableShim>): Promise; + + /** + * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved + * or rejected. + * @param values An array of Promises. + * @returns A new Promise. + */ + race(values: IterableShim>): Promise; + + /** + * Creates a new rejected promise for the provided reason. + * @param reason The reason the promise was rejected. + * @returns A new rejected Promise. + */ + reject(reason: any): Promise; + + /** + * Creates a new rejected promise for the provided reason. + * @param reason The reason the promise was rejected. + * @returns A new rejected Promise. + */ + reject(reason: any): Promise; + + /** + * Creates a new resolved promise for the provided value. + * @param value A promise. + * @returns A promise whose internal state matches the provided promise. + */ + resolve(value: T | PromiseLike): Promise; + + /** + * Creates a new resolved promise . + * @returns A resolved promise. + */ + resolve(): Promise; +} + +declare var Promise: PromiseConstructor; + +interface Map { + clear(): void; + delete(key: K): boolean; + forEach(callbackfn: (value: V, index: K, map: Map) => void, thisArg?: any): void; + get(key: K): V; + has(key: K): boolean; + set(key: K, value?: V): Map; + size: number; + entries(): IterableIteratorShim<[K, V]>; + keys(): IterableIteratorShim; + values(): IterableIteratorShim; +} + +interface MapConstructor { + new (): Map; + new (iterable: IterableShim<[K, V]>): Map; + prototype: Map; +} + +declare var Map: MapConstructor; + +interface Set { + add(value: T): Set; + clear(): void; + delete(value: T): boolean; + forEach(callbackfn: (value: T, index: T, set: Set) => void, thisArg?: any): void; + has(value: T): boolean; + size: number; + entries(): IterableIteratorShim<[T, T]>; + keys(): IterableIteratorShim; + values(): IterableIteratorShim; +} + +interface SetConstructor { + new (): Set; + new (iterable: IterableShim): Set; + prototype: Set; +} + +declare var Set: SetConstructor; + +interface WeakMap { + delete(key: K): boolean; + get(key: K): V; + has(key: K): boolean; + set(key: K, value?: V): WeakMap; +} + +interface WeakMapConstructor { + new (): WeakMap; + new (iterable: IterableShim<[K, V]>): WeakMap; + prototype: WeakMap; +} + +declare var WeakMap: WeakMapConstructor; + +interface WeakSet { + add(value: T): WeakSet; + delete(value: T): boolean; + has(value: T): boolean; +} + +interface WeakSetConstructor { + new (): WeakSet; + new (iterable: IterableShim): WeakSet; + prototype: WeakSet; +} + +declare var WeakSet: WeakSetConstructor; + +declare namespace Reflect { + function apply(target: Function, thisArgument: any, argumentsList: ArrayLike): any; + function construct(target: Function, argumentsList: ArrayLike): any; + function defineProperty(target: any, propertyKey: PropertyKey, attributes: PropertyDescriptor): boolean; + function deleteProperty(target: any, propertyKey: PropertyKey): boolean; + function enumerate(target: any): IterableIteratorShim; + function get(target: any, propertyKey: PropertyKey, receiver?: any): any; + function getOwnPropertyDescriptor(target: any, propertyKey: PropertyKey): PropertyDescriptor; + function getPrototypeOf(target: any): any; + function has(target: any, propertyKey: PropertyKey): boolean; + function isExtensible(target: any): boolean; + function ownKeys(target: any): Array; + function preventExtensions(target: any): boolean; + function set(target: any, propertyKey: PropertyKey, value: any, receiver?: any): boolean; + function setPrototypeOf(target: any, proto: any): boolean; +} + +declare module "es6-shim" { + var String: StringConstructor; + var Array: ArrayConstructor; + var Number: NumberConstructor; + var Math: Math; + var Object: ObjectConstructor; + var Map: MapConstructor; + var Set: SetConstructor; + var WeakMap: WeakMapConstructor; + var WeakSet: WeakSetConstructor; + var Promise: PromiseConstructor; + namespace Reflect { + function apply(target: Function, thisArgument: any, argumentsList: ArrayLike): any; + function construct(target: Function, argumentsList: ArrayLike): any; + function defineProperty(target: any, propertyKey: PropertyKey, attributes: PropertyDescriptor): boolean; + function deleteProperty(target: any, propertyKey: PropertyKey): boolean; + function enumerate(target: any): Iterator; + function get(target: any, propertyKey: PropertyKey, receiver?: any): any; + function getOwnPropertyDescriptor(target: any, propertyKey: PropertyKey): PropertyDescriptor; + function getPrototypeOf(target: any): any; + function has(target: any, propertyKey: PropertyKey): boolean; + function isExtensible(target: any): boolean; + function ownKeys(target: any): Array; + function preventExtensions(target: any): boolean; + function set(target: any, propertyKey: PropertyKey, value: any, receiver?: any): boolean; + function setPrototypeOf(target: any, proto: any): boolean; + } +} diff --git a/deploy/crate-datasource/headers/mocha/mocha.d.ts b/deploy/crate-datasource/headers/mocha/mocha.d.ts new file mode 100755 index 0000000..3f5d3e5 --- /dev/null +++ b/deploy/crate-datasource/headers/mocha/mocha.d.ts @@ -0,0 +1,147 @@ +// Type definitions for mocha 2.0.1 +// Project: http://mochajs.org/ +// Definitions by: Kazi Manzur Rashid , otiai10 , jt000 +// Definitions: https://github.com/borisyankov/DefinitelyTyped + +interface Mocha { + // Setup mocha with the given setting options. + setup(options: MochaSetupOptions): Mocha; + + //Run tests and invoke `fn()` when complete. + run(callback?: () => void): void; + + // Set reporter as function + reporter(reporter: () => void): Mocha; + + // Set reporter, defaults to "dot" + reporter(reporter: string): Mocha; + + // Enable growl support. + growl(): Mocha +} + +interface MochaSetupOptions { + //milliseconds to wait before considering a test slow + slow?: number; + + // timeout in milliseconds + timeout?: number; + + // ui name "bdd", "tdd", "exports" etc + ui?: string; + + //array of accepted globals + globals?: any[]; + + // reporter instance (function or string), defaults to `mocha.reporters.Dot` + reporter?: any; + + // bail on the first test failure + bail?: boolean; + + // ignore global leaks + ignoreLeaks?: boolean; + + // grep string or regexp to filter tests with + grep?: any; +} + +interface MochaDone { + (error?: Error): void; +} + +declare var mocha: Mocha; + +declare var describe : { + (description: string, spec: () => void): void; + only(description: string, spec: () => void): void; + skip(description: string, spec: () => void): void; + timeout(ms: number): void; +} + +// alias for `describe` +declare var context : { + (contextTitle: string, spec: () => void): void; + only(contextTitle: string, spec: () => void): void; + skip(contextTitle: string, spec: () => void): void; + timeout(ms: number): void; +} + +declare var it: { + (expectation: string, assertion?: () => void): void; + (expectation: string, assertion?: (done: MochaDone) => void): void; + only(expectation: string, assertion?: () => void): void; + only(expectation: string, assertion?: (done: MochaDone) => void): void; + skip(expectation: string, assertion?: () => void): void; + skip(expectation: string, assertion?: (done: MochaDone) => void): void; + timeout(ms: number): void; +}; + +declare function before(action: () => void): void; + +declare function before(action: (done: MochaDone) => void): void; + +declare function setup(action: () => void): void; + +declare function setup(action: (done: MochaDone) => void): void; + +declare function after(action: () => void): void; + +declare function after(action: (done: MochaDone) => void): void; + +declare function teardown(action: () => void): void; + +declare function teardown(action: (done: MochaDone) => void): void; + +declare function beforeEach(action: () => void): void; + +declare function beforeEach(action: (done: MochaDone) => void): void; + +declare function suiteSetup(action: () => void): void; + +declare function suiteSetup(action: (done: MochaDone) => void): void; + +declare function afterEach(action: () => void): void; + +declare function afterEach(action: (done: MochaDone) => void): void; + +declare function suiteTeardown(action: () => void): void; + +declare function suiteTeardown(action: (done: MochaDone) => void): void; + +declare module "mocha" { + + class Mocha { + constructor(options?: { + grep?: RegExp; + ui?: string; + reporter?: string; + timeout?: number; + bail?: boolean; + }); + + bail(value?: boolean): Mocha; + addFile(file: string): Mocha; + reporter(value: string): Mocha; + ui(value: string): Mocha; + grep(value: string): Mocha; + grep(value: RegExp): Mocha; + invert(): Mocha; + ignoreLeaks(value: boolean): Mocha; + checkLeaks(): Mocha; + growl(): Mocha; + globals(value: string): Mocha; + globals(values: string[]): Mocha; + useColors(value: boolean): Mocha; + useInlineDiffs(value: boolean): Mocha; + timeout(value: number): Mocha; + slow(value: number): Mocha; + enableTimeouts(value: boolean): Mocha; + asyncOnly(value: boolean): Mocha; + noHighlighting(value: boolean): Mocha; + + run(onComplete?: (failures: number) => void): void; + } + + export = Mocha; +} diff --git a/deploy/crate-datasource/headers/zone/zone.d.ts b/deploy/crate-datasource/headers/zone/zone.d.ts new file mode 100755 index 0000000..7549079 --- /dev/null +++ b/deploy/crate-datasource/headers/zone/zone.d.ts @@ -0,0 +1,66 @@ +declare module Zone { + export class Stacktrace { + constructor(e: Error); + get(): string; + } +} + + +declare class Zone { + constructor(parentZone: Zone, data: any); + fork(locals: any): Zone; + bind(fn, skipEnqueue): void; + bindOnce(fn): any; + run(fn, applyTo?, applyWith?): void; + beforeTask(): void; + onZoneCreated(): void; + afterTask(): void; + enqueueTask(): void; + dequeueTask(): void; + + static patchSetClearFn(obj, fnNames): string; + static patchPrototype(obj, fnNames): any; + static bindArguments(args: any[]): any; + static bindArgumentsOnce(args: any[]): any; + static patchableFn(obj, fnNames): any + static patchProperty(obj, prop): void; + static patchProperties(obj, properties): void; + static patchEventTargetMethods(obj): void; + static patch(): void; + static canPatchViaPropertyDescriptor(): boolean; + static patchViaPropertyDescriptor(): void; + static patchViaCapturingAllTheEvents(): void; + static patchWebSocket(): void; + static patchClass(className: string): void; + static patchMutationObserverClass(className: string): void; + static patchDefineProperty(): void; + static patchRegisterElement(): void; + static eventNames: string; + static onEventNames: string; + static init(): void; + static exceptZone: { + boringZone: Zone; + interestingZone: Zone, + beforeTask: () => void; + afterTask: () => void; + fork: (ops: any) => Zone; + }; + static longStackTraceZone: { + getLongStacktrace(exception: any): string; + stackFramesFilter(line: string): boolean; + onError(exception): void; + fork(locals): Zone; + }; + static getStacktrace(): Zone.Stacktrace; + static countingZone: { + '+enqueueTask': () => void; + '-dequeueTask': () => void; + '+afterTask': () => void; + counter: () => void; + data: { + count: number; + flushed: boolean; + }; + onFlush: () => void; + }; +} diff --git a/deploy/crate-datasource/package.json b/deploy/crate-datasource/package.json new file mode 100755 index 0000000..3dc410b --- /dev/null +++ b/deploy/crate-datasource/package.json @@ -0,0 +1,48 @@ +{ + "name": "crate-datasource", + "private": true, + "version": "0.0.1", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/raintank/crate-datasource.git" + }, + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/raintank/crate-datasource/issues" + }, + "devDependencies": { + "babel": "~6.5.1", + "chai": "~3.5.0", + "grunt": "~0.4.5", + "grunt-babel": "~6.0.0", + "grunt-contrib-clean": "~0.6.0", + "grunt-contrib-copy": "~0.8.2", + "grunt-contrib-uglify": "~0.11.0", + "grunt-contrib-watch": "^0.6.1", + "grunt-execute": "~0.2.2", + "grunt-mocha-test": "~0.12.7", + "grunt-systemjs-builder": "^0.2.5", + "grunt-tslint": "^3.0.2", + "grunt-typescript": "^0.8.0", + "jsdom": "~3.1.2", + "load-grunt-tasks": "~3.2.0", + "prunk": "~1.2.1", + "q": "~1.4.1" + }, + "dependencies": { + "babel-plugin-transform-es2015-for-of": "^6.6.0", + "babel-plugin-transform-es2015-modules-systemjs": "^6.5.0", + "babel-preset-es2015": "^6.5.0", + "lodash": "~4.0.0", + "mocha": "^2.4.5", + "tslint": "^3.4.0", + "typescript": "^1.7.5" + }, + "homepage": "https://github.com/raintank/crate-datasource#readme" +} diff --git a/deploy/crate-datasource/src/config_ctrl.ts b/deploy/crate-datasource/src/config_ctrl.ts new file mode 100755 index 0000000..21b5221 --- /dev/null +++ b/deploy/crate-datasource/src/config_ctrl.ts @@ -0,0 +1,26 @@ +/// + +import angular from 'angular'; +import _ from 'lodash'; + +export class CrateConfigCtrl { + static templateUrl = 'partials/config.html'; + current: any; + + timeIntervals: any[] = [ + {name: 'Auto', value: 'auto'}, + {name: 'Auto (Grafana)', value: 'auto_gf'}, + {name: 'Second', value: 'second'}, + {name: 'Minute', value: 'minute'}, + {name: 'Hour', value: 'hour'}, + {name: 'Day', value: 'day'}, + {name: 'Week', value: 'week'}, + {name: 'Month', value: 'month'}, + {name: 'Quarter', value: 'quarter'}, + {name: 'Year', value: 'year'} + ]; + + constructor($scope) { + this.current.jsonData.timeInterval = this.current.jsonData.timeInterval || this.timeIntervals[1].value; + } +} diff --git a/deploy/crate-datasource/src/datasource.ts b/deploy/crate-datasource/src/datasource.ts new file mode 100755 index 0000000..ef777e4 --- /dev/null +++ b/deploy/crate-datasource/src/datasource.ts @@ -0,0 +1,425 @@ +/// + +import _ from 'lodash'; +import * as dateMath from 'app/core/utils/datemath'; +import moment from 'moment'; +import {CrateQueryBuilder, getEnabledAggs, getRawAggs, getNotRawAggs} from './query_builder'; +import handleResponse from './response_handler'; + +export class CrateDatasource { + type: string; + url: string; + name: string; + basicAuth: string; + withCredentials: boolean; + schema: string; + table: string; + defaultTimeColumn: string; + defaultGroupInterval: string; + checkQuerySource: boolean; + queryBuilder: CrateQueryBuilder; + CRATE_ROWS_LIMIT: number; + + + constructor(instanceSettings, + private $q, + private backendSrv, + private templateSrv, + private timeSrv) { + + this.type = instanceSettings.type; + this.url = instanceSettings.url; + this.name = instanceSettings.name; + this.basicAuth = instanceSettings.basicAuth; + this.withCredentials = instanceSettings.withCredentials; + this.schema = instanceSettings.jsonData.schema; + this.table = instanceSettings.jsonData.table; + this.defaultTimeColumn = instanceSettings.jsonData.timeColumn; + this.defaultGroupInterval = instanceSettings.jsonData.timeInterval; + this.checkQuerySource = instanceSettings.jsonData.checkQuerySource; + + this.$q = $q; + this.backendSrv = backendSrv; + this.templateSrv = templateSrv; + this.timeSrv = timeSrv; + + this.queryBuilder = new CrateQueryBuilder(this.schema, + this.table, + this.defaultTimeColumn, + this.defaultGroupInterval, + this.templateSrv); + + this.CRATE_ROWS_LIMIT = 10000; + } + + // Called once per panel (graph) + query(options) { + let timeFrom = Math.ceil(dateMath.parse(options.range.from)); + let timeTo = Math.ceil(dateMath.parse(options.range.to)); + let timeFilter = this.getTimeFilter(timeFrom, timeTo); + let scopedVars = this.setScopedVars(options.scopedVars); + + let queries = _.map(options.targets, target => { + if (target.hide || (target.rawQuery && !target.query)) { return []; } + + let query: string; + let rawAggQuery: string; + let queryTarget, rawAggTarget; + let getQuery: any; + let getRawAggQuery: any; + let getRawAggInterval: any; + let adhocFilters = this.templateSrv.getAdhocFilters(this.name); + + if (target.rawQuery) { + query = target.query; + } else { + let minInterval = Math.ceil((timeTo - timeFrom) / this.CRATE_ROWS_LIMIT); + let maxLimit = timeTo - timeFrom; + let interval; + + if (target.timeInterval === 'auto') { + interval = getMinCrateInterval(options.intervalMs); + } else if (target.timeInterval === 'auto_gf') { + // Use intervalMs for panel, provided by Grafana + interval = options.intervalMs; + } else { + interval = target.timeInterval; + } + + // Split target into two queries (with aggs and raw data) + query = this.queryBuilder.buildAggQuery(target, interval, adhocFilters); + queryTarget = _.cloneDeep(target); + queryTarget.metricAggs = getNotRawAggs(queryTarget.metricAggs); + + rawAggQuery = this.queryBuilder.buildRawAggQuery(target, 0, adhocFilters, maxLimit); + rawAggQuery = this.templateSrv.replace(rawAggQuery, scopedVars, formatCrateValue); + rawAggTarget = _.cloneDeep(target); + rawAggTarget.metricAggs = getRawAggs(rawAggTarget.metricAggs); + } + + query = this.templateSrv.replace(query, scopedVars, formatCrateValue); + + let queries = [ + {query: query, target: queryTarget}, + {query: rawAggQuery, target: rawAggTarget} + ]; + queries = _.filter(queries, q => { + return q.query; + }); + + return _.map(queries, q => { + return this._sql_query(q.query, [timeFrom, timeTo]) + .then(result => { + if (q.target) { + return handleResponse(q.target, result); + } else { + return handleResponse(target, result); + } + }); + }) + }); + return this.$q.all(_.flattenDepth(queries, 2)).then(result => { + return { + data: _.flatten(result) + }; + }); + } + + /** + * Required. + * Checks datasource and returns Crate cluster name and version or + * error details. + */ + testDatasource() { + return this._get() + .then(response => { + if (response.$$status === 200) { + return { + status: "success", + message: "Cluster: " + response.cluster_name + + ", version: " + response.version.number, + title: "Success" + }; + } + }) + .catch(error => { + let message = error.statusText ? error.statusText + ': ' : ''; + if (error.data && error.data.error) { + message += error.data.error; + } else if (error.data) { + message += error.data; + } else { + message = "Can't connect to Crate instance"; + } + return { + status: "error", + message: message, + title: "Error" + }; + }); + } + + metricFindQuery(query: string) { + if (!query) { + return this.$q.when([]); + } + + query = this.templateSrv.replace(query, null, formatCrateValue); + return this._sql_query(query).then(result => { + return _.map(_.flatten(result.rows), row => { + return { + text: row.toString(), + value: row + }; + }); + }); + } + + annotationQuery(options) { + if (!options.annotation.query) { + return this.$q.reject({ + message: 'Query missing in annotation definition', + }); + } + let timeFrom = Math.ceil(dateMath.parse(options.range.from)); + let timeTo = Math.ceil(dateMath.parse(options.range.to)); + var timeFilter = this.getTimeFilter(timeFrom, timeTo); + var query = options.annotation.query.replace('$timeFilter', timeFilter); + query = this.templateSrv.replace(query, null, 'regex'); + + let data = { + "stmt": query, + "args": [] + }; + + return this._post('_sql', data).then(data => { + if (!data || !data.rows || !data.rows[0]) { + throw { message: 'No results' }; + } + return this.transformAnnotationResponse(options, data); + }); + } + + transformAnnotationResponse(options, data){ + var list = []; + var titleCol = null; + var timeCol = null; + var tagsCol = []; + var textCol = null; + + _.each(data.cols, (column, index) => { + if (column === 'time') { + timeCol = index; + return; + } + if (column === 'sequence_number') { + return; + } + if (!titleCol) { + titleCol = index; + } + if (column === options.annotation.titleColumn) { + titleCol = index; + return; + } + if (_.includes((options.annotation.tagsColumn || '').replace(' ', '').split(','), column)) { + tagsCol.push(index); + return; + } + if (column === options.annotation.textColumn) { + textCol = index; + return; + } + }); + + + + _.each(data.rows, value => { + var data = { + annotation: options.annotation, + time: +new Date(value[timeCol]), + title: value[titleCol], + // Remove empty values, then split in different tags for comma separated values + tags: _.flatten( + tagsCol + .filter(function(t) { + return value[t]; + }) + .map(function(t) { + return value[t].split(','); + }) + ), + text: value[textCol], + }; + + list.push(data); + }); + + return list; + + } + + getTimeFilter(timeFrom, timeTo) { + return this.defaultTimeColumn + " >= '" + timeFrom + "' and " + this.defaultTimeColumn + " <= '" + timeTo + "'"; + } + + getTagKeys(options) { + let query = this.queryBuilder.getColumnsQuery(); + return this.metricFindQuery(query); + } + + getTagValues(options) { + let range = this.timeSrv.timeRange(); + let query = this.queryBuilder.getValuesQuery(options.key, this.CRATE_ROWS_LIMIT, range); + return this.metricFindQuery(query); + } + + setScopedVars(scopedVars) { + scopedVars.crate_schema = {text: this.schema, value: `"${this.schema}"`}; + scopedVars.crate_table = {text: this.table, value: `"${this.table}"`}; + + let crate_source = `"${this.schema}"."${this.table}"`; + scopedVars.crate_source = {text: crate_source, value: crate_source}; + + return scopedVars; + } + + /** + * Sends SQL query to Crate and returns result. + * @param {string} query SQL query string + * @param {any[]} args Optional query arguments + * @return + */ + _sql_query(query: string, args: any[] = []) { + let data = { + "stmt": query, + "args": args + }; + + if (this.checkQuerySource) { + // Checks schema and table and throw error if it different from configured in data source + this.checkSQLSource(query); + } + + return this._post('_sql', data); + } + + checkSQLSource(query) { + let source_pattern = /.*[Ff][Rr][Oo][Mm]\s"?([^\.\s\"]*)"?\.?"?([^\.\s\"]*)"?/; + let match = query.match(source_pattern); + let schema = match[1]; + let table = match[2]; + if (schema !== this.schema || table !== this.table) { + throw { message: `Schema and table should be ${this.schema}.${this.table}` }; + } + } + + _request(method: string, url: string, data?: any) { + let options = { + url: this.url + "/" + url, + method: method, + data: data, + headers: { + "Content-Type": "application/json" + } + }; + + if (this.basicAuth || this.withCredentials) { + options["withCredentials"] = true; + } + if (this.basicAuth) { + options.headers["Authorization"] = this.basicAuth; + } + + return this.backendSrv.datasourceRequest(options) + .then(response => { + response.data.$$status = response.status; + response.data.$$config = response.config; + return response.data; + }); + } + + _get(url = "") { + return this._request('GET', url); + } + + _post(url: string, data?: any) { + return this._request('POST', url, data); + } +} + +// Special value formatter for Crate. +function formatCrateValue(value) { + if (typeof value === 'string') { + return wrapWithQuotes(value); + } else { + return value.map(v => wrapWithQuotes(v)).join(', '); + } +} + +function wrapWithQuotes(value) { + if (!isNaN(value) || + value.indexOf("'") != -1 || + value.indexOf('"') != -1) { + return value; + } else { + return "'" + value + "'"; + } +} + +export function convertToCrateInterval(grafanaInterval) { + let crateIntervals = [ + {shorthand: 's', value: 'second'}, + {shorthand: 'm', value: 'minute'}, + {shorthand: 'h', value: 'hour'}, + {shorthand: 'd', value: 'day'}, + {shorthand: 'w', value: 'week'}, + {shorthand: 'M', value: 'month'}, + {shorthand: 'y', value: 'year'} + ]; + let intervalRegex = /([\d]*)([smhdwMy])/; + let parsedInterval = intervalRegex.exec(grafanaInterval); + let value = Number(parsedInterval[1]); + let unit = parsedInterval[2]; + let crateInterval = _.find(crateIntervals, {'shorthand': unit}); + return crateInterval ? crateInterval.value : undefined; +} + +function crateToMsInterval(crateInterval: string) { + let intervals_s = { + 'year': 60 * 60 * 24 * 30 * 12, + 'quarter': 60 * 60 * 24 * 30 * 3, + 'month': 60 * 60 * 24 * 30, + 'week': 60 * 60 * 24 * 7, + 'day': 60 * 60 * 24, + 'hour': 60 * 60, + 'minute': 60, + 'second': 1 + }; + + if (intervals_s[crateInterval]) { + return intervals_s[crateInterval] * 1000; // Return ms + } else { + return undefined; + } +} + +function getMinCrateInterval(ms) { + let seconds = ms / 1000; + if (seconds > 60 * 60 * 24 * 30 * 3) + return 'year'; + else if (seconds > 60 * 60 * 24 * 30) // TODO: check defenition of month interval + return 'quarter'; + else if (seconds > 60 * 60 * 24 * 7) + return 'month'; + else if (seconds > 60 * 60 * 24) + return 'week'; + else if (seconds > 60 * 60) + return 'day'; + else if (seconds > 60) + return 'hour'; + else if (seconds > 1) + return 'second'; + else + return 'second'; +} diff --git a/deploy/crate-datasource/src/img/crate-datasource-add-src.png b/deploy/crate-datasource/src/img/crate-datasource-add-src.png new file mode 100755 index 0000000..0d2c4e4 Binary files /dev/null and b/deploy/crate-datasource/src/img/crate-datasource-add-src.png differ diff --git a/deploy/crate-datasource/src/img/crate-datasource-error.png b/deploy/crate-datasource/src/img/crate-datasource-error.png new file mode 100755 index 0000000..40f9a8b Binary files /dev/null and b/deploy/crate-datasource/src/img/crate-datasource-error.png differ diff --git a/deploy/crate-datasource/src/img/crate-datasource-graph.png b/deploy/crate-datasource/src/img/crate-datasource-graph.png new file mode 100755 index 0000000..6d7b735 Binary files /dev/null and b/deploy/crate-datasource/src/img/crate-datasource-graph.png differ diff --git a/deploy/crate-datasource/src/img/crate-datasource-nonvalidation.png b/deploy/crate-datasource/src/img/crate-datasource-nonvalidation.png new file mode 100755 index 0000000..3fade94 Binary files /dev/null and b/deploy/crate-datasource/src/img/crate-datasource-nonvalidation.png differ diff --git a/deploy/crate-datasource/src/img/crate_logo.png b/deploy/crate-datasource/src/img/crate_logo.png new file mode 100755 index 0000000..0a34a15 Binary files /dev/null and b/deploy/crate-datasource/src/img/crate_logo.png differ diff --git a/deploy/crate-datasource/src/module.ts b/deploy/crate-datasource/src/module.ts new file mode 100755 index 0000000..b1b9b40 --- /dev/null +++ b/deploy/crate-datasource/src/module.ts @@ -0,0 +1,19 @@ +import {CrateDatasource} from './datasource'; +import {CrateDatasourceQueryCtrl} from './query_ctrl'; +import {CrateConfigCtrl} from './config_ctrl'; + +class CrateQueryOptionsCtrl { + static templateUrl = 'partials/query.options.html'; +} + +class CrateAnnotationsQueryCtrl { + static templateUrl = 'partials/annotations.editor.html'; +} + +export { + CrateDatasource as Datasource, + CrateDatasourceQueryCtrl as QueryCtrl, + CrateConfigCtrl as ConfigCtrl, + CrateQueryOptionsCtrl as QueryOptionsCtrl, + CrateAnnotationsQueryCtrl as AnnotationsQueryCtrl, +}; diff --git a/deploy/crate-datasource/src/partials/annotations.editor.html b/deploy/crate-datasource/src/partials/annotations.editor.html new file mode 100755 index 0000000..81f3baf --- /dev/null +++ b/deploy/crate-datasource/src/partials/annotations.editor.html @@ -0,0 +1,24 @@ + +
+
+ +
+
+ +
Field mappings If your query returns more than one field you need to specify the column names below. An annotation event is composed of a title, tags, and an additional text field.
+
+
+
+ Title + +
+
+ Text + +
+
+ Tags + +
+
+
diff --git a/deploy/crate-datasource/src/partials/config.html b/deploy/crate-datasource/src/partials/config.html new file mode 100755 index 0000000..60a7192 --- /dev/null +++ b/deploy/crate-datasource/src/partials/config.html @@ -0,0 +1,50 @@ + + + +

Crate details

+ +
+
+
+ Schema + + +
+ +
+ Table + + +
+
+ + + + +
+ Time column + + +
+ +
+ Default grouping interval + +
+ +
diff --git a/deploy/crate-datasource/src/partials/query.editor.html b/deploy/crate-datasource/src/partials/query.editor.html new file mode 100755 index 0000000..f5d3c87 --- /dev/null +++ b/deploy/crate-datasource/src/partials/query.editor.html @@ -0,0 +1,149 @@ + + + +
+ + +
+ + +
+ diff --git a/deploy/crate-datasource/src/partials/query.options.html b/deploy/crate-datasource/src/partials/query.options.html new file mode 100755 index 0000000..e69de29 diff --git a/deploy/crate-datasource/src/plugin.json b/deploy/crate-datasource/src/plugin.json new file mode 100755 index 0000000..7396d85 --- /dev/null +++ b/deploy/crate-datasource/src/plugin.json @@ -0,0 +1,36 @@ +{ + "name": "Crate", + "id": "crate-datasource", + "type": "datasource", + + "partials": { + "config": "public/app/plugins/datasource/crate/partials/config.html" + }, + + "metrics": true, + "annotations": true, + "alerting": true, + + "info": { + "description": "Crate SQL Database datasource", + "author": { + "name": "Crate.IO", + "url": "https://crate.io" + }, + "logos": { + "small": "img/crate_logo.png", + "large": "img/crate_logo.png" + }, + "links": [ + {"name": "GitHub", "url": "https://github.com/raintank/crate-datasource"}, + {"name": "MIT License", "url": "https://github.com/raintank/crate-datasource/blob/master/LICENSE"} + ], + "version": "0.5.2", + "updated": "2018-03-12" + }, + + "dependencies": { + "grafanaVersion": "3.x.x", + "plugins": [] + } +} diff --git a/deploy/crate-datasource/src/query_builder.ts b/deploy/crate-datasource/src/query_builder.ts new file mode 100755 index 0000000..2aeda51 --- /dev/null +++ b/deploy/crate-datasource/src/query_builder.ts @@ -0,0 +1,425 @@ +/// + +import _ from 'lodash'; + +// Maximum LIMIT value +let MAX_LIMIT = 100000; +let DEFAULT_LIMIT = 10000; + +export class CrateQueryBuilder { + schema: string; + table: string; + defaultTimeColumn: string; + defaultGroupInterval: string; + + constructor(schema: string, + table: string, + defaultTimeColumn: string, + defaultGroupInterval: string, + private templateSrv) { + this.schema = schema; + this.table = table; + this.defaultTimeColumn = defaultTimeColumn; + this.defaultGroupInterval = defaultGroupInterval; + this.templateSrv = templateSrv; + } + + /** + * Builds Crate SQL query from given target object. + * @param {any} target Target object. + * @param {number} groupInterval Interval for grouping values. + * @param {string} defaultAgg Default aggregation for values. + * @return {string} SQL query. + */ + build(target: any, groupInterval = 0, adhocFilters = [], limit = DEFAULT_LIMIT, defaultAgg='avg') { + let query: string; + let timeExp: string; + + let timeColumn = quoteColumn(this.defaultTimeColumn); + let aggs = getEnabledAggs(target.metricAggs); + let rawAggs = getRawAggs(aggs); + + if (!aggs.length) { return null; } + + if (groupInterval) { + // Manually aggregate by time interval, ie "SELECT floor(ts/10)*10 as time ..." + timeExp = `floor(${timeColumn}/${groupInterval})*${groupInterval}`; + aggs = aggregateMetrics(aggs, 'avg'); + } else { + timeExp = timeColumn; + } + + // SELECT + let renderedAggs = this.renderMetricAggs(aggs); + query = "SELECT " + timeExp + " as time, " + renderedAggs; + + // Add GROUP BY columns to SELECT statement. + if (target.groupByColumns && target.groupByColumns.length) { + query += ", " + target.groupByColumns.join(', '); + } + query += ` FROM "${this.schema}"."${this.table}"` + + ` WHERE ${timeColumn} >= ? AND ${timeColumn} <= ?`; + + // WHERE + if (target.whereClauses && target.whereClauses.length) { + query += " AND " + this.renderWhereClauses(target.whereClauses); + } + + // Add ad-hoc filters + if (adhocFilters.length > 0) { + query += " AND " + this.renderAdhocFilters(adhocFilters); + } + + // GROUP BY + query += " GROUP BY time"; + if (!groupInterval && rawAggs.length) { + query += ", " + this.renderMetricAggs(rawAggs, false); + } + + if (target.groupByColumns && target.groupByColumns.length) { + query += ", " + target.groupByColumns.join(', '); + } + + // If GROUP BY specified, sort also by selected columns + query += " ORDER BY time"; + if (target.groupByColumns && target.groupByColumns.length) { + query += ", " + target.groupByColumns.join(', '); + } + query += " ASC"; + + return query; + } + + buildAggQuery(target: any, groupInterval = 0, adhocFilters = [], limit?: number) { + let query: string; + let timeExp: string; + + let timeColumn = quoteColumn(this.defaultTimeColumn); + let aggs = getEnabledAggs(target.metricAggs); + aggs = getNotRawAggs(aggs); + + if (!aggs.length) { return null; } + + if (!groupInterval) { + groupInterval = 1; + } + + if (typeof groupInterval === 'number') { + // Manually aggregate by time interval, ie "SELECT floor(ts/10)*10 as time ..." + timeExp = `floor(${timeColumn}/${groupInterval})*${groupInterval}`; + } else { + // Use built-in date_trunc() function + timeExp = `date_trunc('${groupInterval}', ${timeColumn})`; + } + + // SELECT + let renderedAggs = this.renderMetricAggs(aggs); + query = `SELECT ${timeExp} as time, ${renderedAggs}`; + + // Add GROUP BY columns to SELECT statement. + if (target.groupByColumns && target.groupByColumns.length) { + query += ", " + target.groupByColumns.join(', '); + } + + // FROM + query += ` FROM "${this.schema}"."${this.table}"`; + + // WHERE + query += ` WHERE ${timeColumn} >= ? AND ${timeColumn} <= ?`; + if (target.whereClauses && target.whereClauses.length) { + query += " AND " + this.renderWhereClauses(target.whereClauses); + } + + // Add ad-hoc filters + if (adhocFilters.length > 0) { + query += " AND " + this.renderAdhocFilters(adhocFilters); + } + + // GROUP BY + query += " GROUP BY time"; + + if (target.groupByColumns && target.groupByColumns.length) { + query += ", " + target.groupByColumns.join(', '); + } + + // If GROUP BY specified, sort also by selected columns + query += " ORDER BY time"; + if (target.groupByColumns && target.groupByColumns.length) { + query += ", " + target.groupByColumns.join(', '); + } + query += " ASC"; + + if (limit && limit > DEFAULT_LIMIT) { + limit = Math.min(limit, MAX_LIMIT); + query += ` LIMIT ${limit}`; + } + + return query; + } + + buildRawAggQuery(target: any, groupInterval = 0, adhocFilters = [], limit?: number) { + let query: string; + let timeExp: string; + + let timeColumn = quoteColumn(this.defaultTimeColumn); + let aggs = getEnabledAggs(target.metricAggs); + let rawAggs = getRawAggs(aggs); + + if (!rawAggs.length) { return null; } + + // SELECT + let renderedAggs = this.renderMetricAggs(rawAggs); + query = "SELECT " + timeColumn + " as time, " + renderedAggs; + + // Add GROUP BY columns to SELECT statement. + if (target.groupByColumns && target.groupByColumns.length) { + query += ", " + target.groupByColumns.join(', '); + } + query += ` FROM "${this.schema}"."${this.table}"` + + ` WHERE ${timeColumn} >= ? AND ${timeColumn} <= ?`; + + // WHERE + if (target.whereClauses && target.whereClauses.length) { + query += " AND " + this.renderWhereClauses(target.whereClauses); + } + + // Add ad-hoc filters + if (adhocFilters.length > 0) { + query += " AND " + this.renderAdhocFilters(adhocFilters); + } + + // GROUP BY + query += " GROUP BY time"; + query += ", " + this.renderMetricAggs(rawAggs, false); + + if (target.groupByColumns && target.groupByColumns.length) { + query += ", " + target.groupByColumns.join(', '); + } + + // If GROUP BY specified, sort also by selected columns + query += " ORDER BY time"; + if (target.groupByColumns && target.groupByColumns.length) { + query += ", " + target.groupByColumns.join(', '); + } + query += " ASC"; + + if (limit) { + limit = Math.min(limit, MAX_LIMIT); + query += ` LIMIT ${limit}`; + } + + return query; + } + + renderAdhocFilters(filters) { + let conditions = _.map(filters, (tag, index) => { + let filter_str = ""; + let condition = tag.condition || 'AND'; + let key = quoteColumn(tag.key); + let operator = tag.operator; + let value = quoteValue(tag.value); + + if (index > 0) { + filter_str = `${condition} `; + } + + if (operator === '=~') { + operator = '~'; + } + + filter_str += `${key} ${operator} ${value}` + return filter_str; + }); + return conditions.join(' '); + } + + /** + * Builds SQL query for getting available columns from table. + * @return {string} SQL query. + */ + getColumnsQuery() { + let query = "SELECT column_name " + + "FROM information_schema.columns " + + "WHERE table_schema = '" + this.schema + "' " + + "AND table_name = '" + this.table + "' " + + "ORDER BY 1"; + return query; + } + + getNumericColumnsQuery() { + return "SELECT column_name " + + "FROM information_schema.columns " + + "WHERE table_schema = '" + this.schema + "' " + + "AND table_name = '" + this.table + "' " + + "AND data_type in ('integer', 'long', 'short', 'double', 'float', 'byte') " + + "ORDER BY 1"; + } + + /** + * Builds SQL query for getting unique values for given column. + * @param {string} column Column name + * @param {number} limit Optional. Limit number returned values. + */ + getValuesQuery(column: string, limit?: number, timeRange?) { + let timeColumn = quoteColumn(this.defaultTimeColumn); + let query = `SELECT DISTINCT ${column} ` + + `FROM "${this.schema}"."${this.table}"`; + + if (timeRange) { + let timeFrom = timeRange.from.valueOf(); + let timeTo = timeRange.to.valueOf(); + query += ` WHERE ${timeColumn} >= ${timeFrom} AND ${timeColumn} <= ${timeTo}`; + } + + if (limit) { + query += ` LIMIT ${limit}`; + } + return query; + } + + private renderMetricAggs(metricAggs: any, withAlias=true): string { + let enabledAggs = _.filter(metricAggs, (agg) => { + return !agg.hide; + }); + + let renderedAggs = _.map(enabledAggs, (agg) => { + let alias = ''; + if (agg.alias && withAlias) { + alias = ' AS \"' + agg.alias + '\"'; + } + + let column = quoteColumn(agg.column); + if (agg.type === 'count_distinct') { + return "count(distinct " + column + ")" + alias; + } else if (agg.type === 'raw') { + return column + alias; + } else { + return agg.type + "(" + column + ")" + alias; + } + }); + + if (renderedAggs.length) { + return renderedAggs.join(', '); + } else { + return ""; + } + } + + private renderWhereClauses(whereClauses): string { + let renderedClauses = _.map(whereClauses, (clauseObj, index) => { + let rendered = ""; + if (index !== 0) { + rendered += clauseObj.condition + " "; + } + + // Quote arguments as required by the operator and value type + let rendered_value: string; + let value = clauseObj.value; + if (clauseObj.operator.toLowerCase() === 'in') { + // Handle IN operator. Split comma-separated values. + // "42, 10, a" => 42, 10, 'a' + rendered_value = '(' + _.map(value.split(','), v => { + v = v.trim(); + if (!isNaN(v) || this.containsVariable(v)) { + return v; + } else { + return "'" + v + "'"; + } + }).join(', ') + ')'; + } else { + rendered_value = _.map(value.split(','), v => { + v = v.trim(); + if (!isNaN(v) || this.containsVariable(v)) { + return v; + } else { + return "'" + v + "'"; + } + }).join(', '); + } + rendered += clauseObj.column + ' ' + clauseObj.operator + ' ' + rendered_value; + return rendered; + }); + return renderedClauses.join(' '); + } + + // Check for template variables + private containsVariable(str: string): boolean { + let variables = _.map(this.templateSrv.variables, 'name'); + return _.some(variables, variable => { + let pattern = new RegExp('\\$' + variable); + return pattern.test(str); + }); + } +} + +export function getSchemas() { + var query = "SELECT schema_name " + + "FROM information_schema.schemata " + + "WHERE schema_name NOT IN ('information_schema', 'blob', 'sys', 'pg_catalog') " + + "ORDER BY 1"; + return query; +} + +export function getTables(schema) { + var query = "SELECT table_name " + + "FROM information_schema.tables " + + "WHERE table_schema='" + schema + "' " + + "ORDER BY 1"; + return query; +} + +function quoteColumn(column: string): string { + if (isWithUpperCase(column)) { + return '\"' + column + '\"'; + } else { + return column; + } +} + +function quoteValue(value: string): string { + value = value.trim(); + let match = value.match(/^'?([^']*)'?$/); + if (match[1]) { + value = match[1]; + } else { + return value; + } + + if (!isNaN(Number(value))) { + return value; + } else { + return "'" + value + "'"; + } +} + +function isWithUpperCase(str: string): boolean { + return str.toLowerCase() !== str; +} + +function aggregateMetrics(metricAggs: any, aggType: string) { + let aggs = _.cloneDeep(metricAggs); + return _.map(aggs, agg => { + if (agg.type === 'raw') { + agg.type = aggType; + return agg; + } else { + return agg; + } + }); +} + +export function getEnabledAggs(metricAggs) { + return _.filter(metricAggs, (agg) => { + return !agg.hide; + }); +} + +export function getRawAggs(metricAggs) { + return _.filter(metricAggs, {type: 'raw'}); +} + +export function getNotRawAggs(metricAggs) { + return _.filter(metricAggs, agg => { + return agg.type !== 'raw'; + }); +} diff --git a/deploy/crate-datasource/src/query_ctrl.ts b/deploy/crate-datasource/src/query_ctrl.ts new file mode 100755 index 0000000..afed57c --- /dev/null +++ b/deploy/crate-datasource/src/query_ctrl.ts @@ -0,0 +1,324 @@ +/// + +import angular from 'angular'; +import _ from 'lodash'; +import {QueryCtrl} from './sdk/sdk'; +import {CrateQueryBuilder} from './query_builder'; +import queryDef from './query_def'; + +export class CrateDatasourceQueryCtrl extends QueryCtrl { + static templateUrl = 'partials/query.editor.html'; + + crateQueryBuilder: CrateQueryBuilder; + groupBySegments: any; + whereSegments: any; + removeWhereSegment: any; + operators: any; + timeIntervals: any[]; + resultFormats: any[]; + + constructor($scope, $injector, private $q, private uiSegmentSrv, private templateSrv) { + super($scope, $injector); + + this.uiSegmentSrv = uiSegmentSrv; + this.templateSrv = templateSrv; + + let ds = this.datasource; + this.crateQueryBuilder = new CrateQueryBuilder(ds.schema, + ds.table, + ds.defaultTimeColumn, + ds.defaultGroupInterval, + templateSrv); + + this.operators = ['<', '>', '<=', '>=', '=', '<>', '!=', 'in', 'like', '~', '!~']; + + this.timeIntervals = [ + {name: 'Auto', value: 'auto'}, + {name: 'Auto (Grafana)', value: 'auto_gf'}, + {name: 'Second', value: 'second'}, + {name: 'Minute', value: 'minute'}, + {name: 'Hour', value: 'hour'}, + {name: 'Day', value: 'day'}, + {name: 'Week', value: 'week'}, + {name: 'Month', value: 'month'}, + {name: 'Quarter', value: 'quarter'}, + {name: 'Year', value: 'year'} + ]; + + this.resultFormats = [ + {text: 'Time series', value: 'time_series'}, + {text: 'Table', value: 'table'}, + ]; + + var target_defaults = { + metricAggs: [ + {type: 'avg', column: 'value'} + ], + groupByColumns: [], + groupByAliases: [], + whereClauses: [], + timeInterval: ds.defaultGroupInterval, + resultFormat: 'time_series' + }; + _.defaults(this.target, target_defaults); + + this.updateGroupByAliases(); + + this.groupBySegments = _.map(this.target.groupByColumns, this.uiSegmentSrv.newSegment); + + // Build WHERE segments + this.whereSegments = []; + this.buildWhereSegments(this.target.whereClauses); + + this.removeWhereSegment = uiSegmentSrv.newSegment({fake: true, value: '-- remove --'}); + this.fixSegments(this.groupBySegments); + } + + crateQuery(query, args = []) { + return this.datasource._sql_query(query, args).then(response => { + return response.rows; + }); + } + + getCollapsedText(): string { + if (this.target.rawQuery) { + return this.target.query; + } else { + return this.crateQueryBuilder.build(this.target); + } + } + + //////////////////// + // Event handlers // + //////////////////// + + onChangeInternal(): void { + this.panelCtrl.refresh(); // Asks the panel to refresh data. + } + + groupBySegmentChanged(segment, index): void { + if (segment.type === 'plus-button') { + segment.type = undefined; + } + this.target.groupByColumns = _.map(_.filter(this.groupBySegments, segment => { + return (segment.type !== 'plus-button' && + segment.value !== this.removeWhereSegment.value); + }), 'value'); + this.groupBySegments = _.map(this.target.groupByColumns, this.uiSegmentSrv.newSegment); + this.groupBySegments.push(this.uiSegmentSrv.newPlusButton()); + + if (segment.value === this.removeWhereSegment.value) { + this.target.groupByAliases.splice(index, 1); + } + this.updateGroupByAliases(); + + this.onChangeInternal(); + } + + onGroupByAliasChange(index) { + this.updateGroupByAliases(); + this.onChangeInternal(); + } + + onAggTypeChange(): void { + this.onChangeInternal(); + } + + addMetricAgg(): void { + this.target.metricAggs.push({ type: 'avg', column: 'value' }); + this.onChangeInternal(); + } + + removeMetricAgg(index): void { + this.target.metricAggs.splice(index, 1); + this.onChangeInternal(); + } + + toggleShowMetric(agg): void { + agg.hide = !agg.hide; + this.onChangeInternal(); + } + + toggleEditorMode(): void { + this.target.rawQuery = !this.target.rawQuery; + } + + /////////////////////// + // Query suggestions // + /////////////////////// + + getColumns(allValue?: boolean, onlyNumeric?: boolean) { + let query; + if (onlyNumeric) { + query = this.crateQueryBuilder.getNumericColumnsQuery(); + } else { + query = this.crateQueryBuilder.getColumnsQuery(); + } + let self = this; + return this.crateQuery(query).then(rows => { + if (allValue) { + rows.splice(0, 0, '*'); + } + return self.transformToSegments(_.flatten(rows), true); + }); + } + + getGroupByColumns() { + return this.getColumns().then(columns => { + columns.splice(0, 0, angular.copy(this.removeWhereSegment)); + return columns; + }); + } + + getValues(column, limit = 10) { + let self = this; + let time_range = this.panelCtrl.range; + return this.crateQuery(this.crateQueryBuilder.getValuesQuery(column, limit, time_range)) + .then(rows => { + return self.transformToSegments(_.flatten(rows), true); + }); + } + + getColumnsOrValues(segment, index) { + var self = this; + if (segment.type === 'condition') { + return this.$q.when([this.uiSegmentSrv.newSegment('AND'), this.uiSegmentSrv.newSegment('OR')]); + } + if (segment.type === 'operator') { + return this.$q.when(this.uiSegmentSrv.newOperators(this.operators)); + } + + if (segment.type === 'key' || segment.type === 'plus-button') { + return this.getColumns().then(columns => { + columns.splice(0, 0, angular.copy(this.removeWhereSegment)); + return columns; + }); + } else if (segment.type === 'value') { + return this.getValues(this.whereSegments[index - 2].value); + } + } + + getMetricAggTypes() { + return queryDef.getMetricAggTypes(); + } + + getMetricAggDef(aggType) { + return _.find(this.getMetricAggTypes(), { value: aggType }); + } + + whereSegmentUpdated(segment, index) { + this.whereSegments[index] = segment; + + if (segment.value === this.removeWhereSegment.value) { + this.whereSegments.splice(index, 3); + if (this.whereSegments.length === 0) { + this.whereSegments.push(this.uiSegmentSrv.newPlusButton()); + } else if (this.whereSegments.length > 2) { + this.whereSegments.splice(Math.max(index - 1, 0), 1); + if (this.whereSegments[this.whereSegments.length - 1].type !== 'plus-button') { + this.whereSegments.push(this.uiSegmentSrv.newPlusButton()); + } + } + } else { + if (segment.type === 'plus-button') { + if (index > 2) { + this.whereSegments.splice(index, 0, this.uiSegmentSrv.newCondition('AND')); + } + this.whereSegments.push(this.uiSegmentSrv.newOperator('=')); + this.whereSegments.push(this.uiSegmentSrv.newFake('select tag value', 'value', 'query-segment-value')); + segment.type = 'key'; + segment.cssClass = 'query-segment-key'; + } + if ((index + 1) === this.whereSegments.length) { + this.whereSegments.push(this.uiSegmentSrv.newPlusButton()); + } + } + + this.buildWhereClauses(); + + // Refresh only if all fields setted + if (_.every(this.whereSegments, segment => { + return ((segment.value || segment.type === 'plus-button') && + !(segment.fake && segment.type !== 'plus-button')); + })) { + this.panelCtrl.refresh(); + } + } + + /////////////////////// + + buildWhereSegments(whereClauses: any): void { + var self = this; + _.forEach(whereClauses, whereClause => { + if (whereClause.condition) { + self.whereSegments.push(self.uiSegmentSrv.newCondition(whereClause.condition)); + } + self.whereSegments.push(self.uiSegmentSrv.newKey(whereClause.column)); + self.whereSegments.push(self.uiSegmentSrv.newOperator(whereClause.operator)); + self.whereSegments.push(self.uiSegmentSrv.newKeyValue(whereClause.value)); + }); + this.fixSegments(this.whereSegments); + } + + buildWhereClauses() { + var i = 0; + var whereIndex = 0; + var segments = this.whereSegments; + var whereClauses = []; + while (segments.length > i && segments[i].type !== 'plus-button') { + if (whereClauses.length < whereIndex + 1) { + whereClauses.push({condition: '', column: '', operator: '', value: ''}); + } + if (segments[i].type === 'condition') { + whereClauses[whereIndex].condition = segments[i].value; + } else if (segments[i].type === 'key') { + whereClauses[whereIndex].column = segments[i].value; + } else if (segments[i].type === 'operator') { + whereClauses[whereIndex].operator = segments[i].value; + } else if (segments[i].type === 'value' || segments[i].type === 'template') { + whereClauses[whereIndex].value = segments[i].value; + whereIndex++; + } + i++; + } + this.target.whereClauses = whereClauses; + } + + fixSegments(segments) { + var count = segments.length; + var lastSegment = segments[Math.max(count-1, 0)]; + + if (!lastSegment || lastSegment.type !== 'plus-button') { + segments.push(this.uiSegmentSrv.newPlusButton()); + } + } + + transformToSegments(results, addTemplateVars?: boolean) { + var segments = _.map(_.flatten(results), value => { + return this.uiSegmentSrv.newSegment({ + value: value.toString(), + expandable: false + }); + }); + + if (addTemplateVars) { + for (let variable of this.templateSrv.variables) { + segments.unshift(this.uiSegmentSrv.newSegment({ type: 'template', value: '$' + variable.name, expandable: true })); + } + } + return segments; + } + + updateGroupByAliases() { + let groupByAliases = new Array(this.target.groupByColumns.length); + this.target.groupByColumns.forEach((column, index) => { + if (this.target.groupByAliases[index]) { + groupByAliases[index] = this.target.groupByAliases[index]; + } else { + groupByAliases[index] = ""; + } + }); + this.target.groupByAliases = groupByAliases; + } + +} diff --git a/deploy/crate-datasource/src/query_def.ts b/deploy/crate-datasource/src/query_def.ts new file mode 100755 index 0000000..9396ff2 --- /dev/null +++ b/deploy/crate-datasource/src/query_def.ts @@ -0,0 +1,24 @@ +/// + +import _ from 'lodash'; + +let _metricAggTypes = [ + {text: "Raw", value: "raw", allValue: false}, + {text: "Count", value: 'count', allValue: true, anyDataType: true}, + {text: "Distinct Count", value: 'count_distinct', allValue: false, anyDataType: true}, + {text: "Avg / Mean", value: 'avg', allValue: false}, + {text: "Min", value: 'min', allValue: false}, + {text: "Max", value: 'max', allValue: false}, + {text: "Sum", value: 'sum', allValue: false}, + {text: "Geometric Mean", value: 'geometric_mean', allValue: false}, + {text: "Variance", value: 'variance', allValue: false}, + {text: "Std Deviation", value: 'stddev', allValue: false}, + {text: "Arbitrary", value: "arbitrary", allValue: false} +]; + +export default class QueryDef { + + static getMetricAggTypes() { + return _metricAggTypes; + } +} diff --git a/deploy/crate-datasource/src/response_handler.ts b/deploy/crate-datasource/src/response_handler.ts new file mode 100755 index 0000000..1a7fdaf --- /dev/null +++ b/deploy/crate-datasource/src/response_handler.ts @@ -0,0 +1,146 @@ +/// + +import _ from 'lodash'; + +export default function handleResponse(target, result) { + if (target.resultFormat === 'table') { + return handleTableResponse(target, result); + } + + if (target.rawQuery) { + return handleRawResponse(target, result); + } else { + return handleBuildedResponse(target, result); + } +} + +function handleTableResponse(target, result) { + return { + columns: _.map(result.cols, col => { + return {text: col}; + }), + rows: result.rows, + type: 'table' + }; +} + +function handleRawResponse(target, result) { + let columns = result.cols; + let timeColumnIndex = 0; + let valueColumnIndex = 1; + + if (columns.length > 2) { + let groupedResponse = _.groupBy(result.rows, row => { + // Assume row structure is + // [ts, value, ...group by columns] + return row.slice(2).join(' '); + }); + + return _.map(groupedResponse, (rows, key) => { + return { + target: key + ': ' + columns[valueColumnIndex], + datapoints: convertToGrafanaPoints(rows, timeColumnIndex, valueColumnIndex) + }; + }); + } else { + return [{ + target: columns[valueColumnIndex], + datapoints: convertToGrafanaPoints(result.rows, timeColumnIndex, valueColumnIndex) + }]; + } +} + +function handleBuildedResponse(target, result) { + let columns = result.cols; + let timeColumnIndex = 0; + let groupByColumnIndexes: number[], selectColumnIndexes: number[]; + + if (target.groupByColumns.length) { + groupByColumnIndexes = _.map(target.groupByColumns, groupByCol => { + return _.indexOf(columns, groupByCol); + }); + } + + let enabledAggs = _.filter(target.metricAggs, (agg) => { + return !agg.hide; + }); + + if (enabledAggs.length) { + selectColumnIndexes = _.map(enabledAggs, (metricAgg, index) => { + return index + 1; + }); + } else { + return []; + } + + if (groupByColumnIndexes && groupByColumnIndexes.length && !_.some(groupByColumnIndexes, -1)) { + let groupedResponse = _.groupBy(result.rows, row => { + // Construct groupBy key from Group By columns, for example: + // [metric, host] => 'metric host' + return _.map(groupByColumnIndexes, columnIndex => { + return row[columnIndex]; + }).join(' '); + }); + + return _.flatten(_.map(groupedResponse, (rows, key) => { + return _.map(selectColumnIndexes, (valueIndex) => { + let datapoints = convertToGrafanaPoints(rows, timeColumnIndex, valueIndex); + + // Build alias for Group By column values + let group_by_alias: string; + if (rows.length) { + group_by_alias = _.map(groupByColumnIndexes, (columnIndex, i) => { + let first_row = rows[0]; + if (target.groupByAliases && target.groupByAliases[i]) { + let pattern = new RegExp(target.groupByAliases[i]); + let match = pattern.exec(first_row[columnIndex]); + if (match && match.length > 1) { + return match[1]; + } else if (match){ + return match[0]; + } else { + return first_row[columnIndex]; + } + } else { + return first_row[columnIndex]; + } + }).join(' '); + } else { + group_by_alias = key; + } + + return { + target: group_by_alias + ': ' + columns[valueIndex], + datapoints: datapoints + }; + }); + })); + } else { + return _.map(selectColumnIndexes, (valueIndex) => { + let datapoints = convertToGrafanaPoints(result.rows, timeColumnIndex, valueIndex); + + return { + target: columns[valueIndex], + datapoints: datapoints + }; + }); + } +} + +function convertToGrafanaPoints(rows, timeColumnIndex, valueColumnIndex) { + return _.map(rows, row => { + let ts = Number(row[timeColumnIndex]); + let val = row[valueColumnIndex]; + val = val !== null ? Number(val) : null; + + return [val, ts]; + }); +} + +function makeColName(aggType, column) { + if (aggType === 'count_distinct') { + return 'count(DISTINCT ' + column + ')'; + } else { + return aggType + '(' + column + ')'; + } +} diff --git a/deploy/crate-datasource/src/sdk/query_ctrl.ts b/deploy/crate-datasource/src/sdk/query_ctrl.ts new file mode 100755 index 0000000..67f4f93 --- /dev/null +++ b/deploy/crate-datasource/src/sdk/query_ctrl.ts @@ -0,0 +1,23 @@ +/// + +import angular from 'angular'; +import _ from 'lodash'; + +export class QueryCtrl { + target: any; + datasource: any; + panelCtrl: any; + panel: any; + hasRawMode: boolean; + error: string; + + constructor(public $scope, private $injector) { + this.panel = this.panelCtrl.panel; + } + + refresh() { + this.panelCtrl.refresh(); + } + +} + diff --git a/deploy/crate-datasource/src/sdk/sdk.ts b/deploy/crate-datasource/src/sdk/sdk.ts new file mode 100755 index 0000000..37ed221 --- /dev/null +++ b/deploy/crate-datasource/src/sdk/sdk.ts @@ -0,0 +1,15 @@ +import {QueryCtrl} from './query_ctrl'; + +import config from 'app/core/config'; + +export function loadPluginCss(options) { + if (config.bootData.user.lightTheme) { + System.import(options.light + '!css'); + } else { + System.import(options.dark + '!css'); + } +} + +export { + QueryCtrl +} diff --git a/deploy/crate-datasource/src/spec/datasource_specs.js b/deploy/crate-datasource/src/spec/datasource_specs.js new file mode 100755 index 0000000..f1c3d3c --- /dev/null +++ b/deploy/crate-datasource/src/spec/datasource_specs.js @@ -0,0 +1,142 @@ +//import {describe, beforeEach, it, sinon, expect} from '../utils/test_common'; +import {Datasource} from '../module'; +import {convertToCrateInterval} from '../datasource'; +import Q from "q"; + +describe('CrateDatasource', function() { + var ctx = {}; + + describe('When testing datasource', function() { + + beforeEach(function() { + ctx.$q = Q; + ctx.backendSrv = {}; + ctx.templateSrv = {}; + ctx.instanceSettings = { + url: "http://crate.io:4200", + jsonData: { + schema: 'stats', + table: 'nodes', + defaultTimeColumn: 'ts', + defaultGroupInterval: 'minute' + } + }; + ctx.ds = new Datasource(ctx.instanceSettings, ctx.$q, ctx.backendSrv, ctx.templateSrv); + }); + + it('should return Crate cluster name and version if test ok', function(done) { + ctx.backendSrv.datasourceRequest = function(options) { + return ctx.$q.when({ + status: 200, + data: { + "ok" : true, + "status" : 200, + "name" : "Negasonic Teenage Warhead", + "cluster_name" : "Crate Test Cluster", + "version" : { + "number" : "0.54.8", + "build_hash" : "c3a7dc4caecfe4fef2992148c8b78347d8c30b2e", + "build_timestamp" : "2016-04-08T12:26:00Z", + "build_snapshot" : false, + "es_version" : "1.7.5", + "lucene_version" : "4.10.4" + } + } + }); + }; + + ctx.ds.testDatasource().then(function(result) { + expect(result).to.have.property('status'); + expect(result).to.have.property('title'); + expect(result).to.have.property('message'); + expect(result.status).to.equal('success'); + expect(result.title).to.equal('Success'); + expect(result.message).to.equal('Cluster: Crate Test Cluster, version: 0.54.8'); + done(); + }); + }); + + it('should return Crate error if host and port was set properly but url is wrong', function(done) { + ctx.backendSrv.datasourceRequest = function(options) { + var deferred = ctx.$q.defer(); + deferred.reject({ + status: 400, + statusText: "Bad Request", + data: "No handler found for uri [/wrong] and method [GET]" + }); + return deferred.promise; + }; + + ctx.ds.testDatasource().then(function(result) { + expect(result).to.have.property('status'); + expect(result).to.have.property('title'); + expect(result).to.have.property('message'); + expect(result.status).to.equal('error'); + expect(result.title).to.equal('Error'); + expect(result.message).to.equal('Bad Request: No handler found for uri [/wrong] and method [GET]'); + done(); + }); + }); + + it('should return http error if url is unreachable', function(done) { + ctx.backendSrv.datasourceRequest = function(options) { + var deferred = ctx.$q.defer(); + deferred.reject({ + status: 500, + statusText: "Internal Server Error", + data: { + error: "Internal Server Error", + message: "Internal Server Error" + } + }); + return deferred.promise; + }; + + ctx.ds.testDatasource().then(function(result) { + expect(result).to.have.property('status'); + expect(result).to.have.property('title'); + expect(result).to.have.property('message'); + expect(result.status).to.equal('error'); + expect(result.title).to.equal('Error'); + expect(result.message).to.equal('Internal Server Error: Internal Server Error'); + done(); + }); + }); + }); + + describe('When converting to Crate interval', function() { + + beforeEach(function() { + }); + + it('should return proper interval for date_trunc() function', function(done) { + var test_map = [ + ['10s', 'second'], + ['20s', 'second'], + ['30s', 'second'], + ['40s', 'second'], + ['50s', 'second'], + ['59s', 'second'], + + ['1m', 'minute'], + ['1h', 'hour'], + ['1d', 'day'], + ['1w', 'week'], + ['1M', 'month'], + ['1y', 'year'] + ]; + + var test_intervals = test_map.map(function(value) { + return value[0]; + }); + var expected_result = test_map.map(function(value) { + return value[1]; + }); + var result = test_intervals.map(convertToCrateInterval); + + expect(result).to.deep.equal(expected_result); + done(); + }); + }); + +}); diff --git a/deploy/crate-datasource/src/spec/query_builder_specs.js b/deploy/crate-datasource/src/spec/query_builder_specs.js new file mode 100755 index 0000000..842f017 --- /dev/null +++ b/deploy/crate-datasource/src/spec/query_builder_specs.js @@ -0,0 +1,374 @@ +//import {describe, beforeEach, it, sinon, expect} from '../utils/test_common'; +import {CrateQueryBuilder} from '../query_builder'; + +describe('CrateQueryBuilder', function() { + var ctx = {}; + + beforeEach(function() { + ctx.templateSrv = { + containsVariable: (str, variable) => {return true;}, + variables: [] + }; + ctx.limit = 100; + ctx.adhocFilters = []; + ctx.queryBuilder = new CrateQueryBuilder('stats', 'nodes', 'ts', 'minute', ctx.templateSrv); + }); + + describe('When building query', function() { + + beforeEach(function() { + ctx.target = { + metricAggs: [ + {type: 'avg', column: 'load'} + ], + whereClauses: [ + {condition: 'AND', column: 'hostname', operator: '=', value: 'backend01'} + ], + groupByColumns: [], + timeInterval: 'auto' + }; + + ctx.interval = 'second'; + }); + + it('should build proper Crate SQL query', function(done) { + var expected_query = "SELECT date_trunc('second', ts) as time, " + + "avg(load) " + + "FROM \"stats\".\"nodes\" " + + "WHERE ts >= ? AND ts <= ? " + + "AND hostname = 'backend01' " + + "GROUP BY time " + + "ORDER BY time ASC"; + + var query = ctx.queryBuilder.buildAggQuery(ctx.target, ctx.interval); + expect(query).to.equal(expected_query); + done(); + }); + + it('should build proper WHERE clause', function(done) { + ctx.target.whereClauses = [ + {condition: 'AND', column: 'hostname', operator: '=', value: 'backend01'}, + {condition: 'OR', column: 'hostname', operator: '=', value: 'frontend01'} + ]; + + var expected_query = "SELECT date_trunc('second', ts) as time, " + + "avg(load) " + + "FROM \"stats\".\"nodes\" " + + "WHERE ts >= ? AND ts <= ? " + + "AND hostname = 'backend01' " + + "OR hostname = 'frontend01' " + + "GROUP BY time " + + "ORDER BY time ASC"; + + var query = ctx.queryBuilder.buildAggQuery(ctx.target, ctx.interval); + expect(query).to.equal(expected_query); + + // Raw agg query + ctx.target.metricAggs = [ + {type: 'raw', column: 'load'} + ]; + + expected_query = "SELECT ts as time, " + + "load " + + "FROM \"stats\".\"nodes\" " + + "WHERE ts >= ? AND ts <= ? " + + "AND hostname = 'backend01' " + + "OR hostname = 'frontend01' " + + "GROUP BY time, load " + + "ORDER BY time ASC"; + + query = ctx.queryBuilder.buildRawAggQuery(ctx.target, ctx.interval); + expect(query).to.equal(expected_query); + done(); + }); + + it('should handle WHERE ... IN ... properly', function(done) { + ctx.target.whereClauses = [ + {condition: 'AND', column: 'id', operator: 'IN', value: 'a, 42'} + ]; + var expected_query = "SELECT date_trunc('second', ts) as time, " + + "avg(load) " + + "FROM \"stats\".\"nodes\" " + + "WHERE ts >= ? AND ts <= ? " + + "AND id IN ('a', 42) " + + "GROUP BY time " + + "ORDER BY time ASC"; + + var query = ctx.queryBuilder.buildAggQuery(ctx.target, ctx.interval); + expect(query).to.equal(expected_query); + done(); + }); + + it('should handle WHERE IN properly if template variables has been used', function(done) { + ctx.templateSrv.variables = [{name: 'id'}]; + + ctx.target.whereClauses = [ + {condition: 'AND', column: 'id', operator: 'IN', value: '$id'} + ]; + + var expected_query = "SELECT date_trunc('second', ts) as time, " + + "avg(load) " + + "FROM \"stats\".\"nodes\" " + + "WHERE ts >= ? AND ts <= ? " + + "AND id IN ($id) " + + "GROUP BY time " + + "ORDER BY time ASC"; + + var query = ctx.queryBuilder.buildAggQuery(ctx.target, ctx.interval); + expect(query).to.equal(expected_query); + done(); + }); + + it('should add GROUP BY columns to SELECT and ORDER BY expressions', function(done) { + ctx.target = { + metricAggs: [ + {type: 'avg', column: 'load'} + ], + whereClauses: [], + groupByColumns: ['hostname'], + }; + + var expected_query = "SELECT date_trunc('second', ts) as time, " + + "avg(load), hostname " + + "FROM \"stats\".\"nodes\" " + + "WHERE ts >= ? AND ts <= ? " + + "GROUP BY time, hostname " + + "ORDER BY time, hostname ASC"; + + var query = ctx.queryBuilder.buildAggQuery(ctx.target, ctx.interval); + expect(query).to.equal(expected_query); + + // Raw agg query + ctx.target.metricAggs = [ + {type: 'raw', column: 'load'} + ]; + + expected_query = "SELECT ts as time, " + + "load, hostname " + + "FROM \"stats\".\"nodes\" " + + "WHERE ts >= ? AND ts <= ? " + + "GROUP BY time, load, hostname " + + "ORDER BY time, hostname ASC"; + + query = ctx.queryBuilder.buildRawAggQuery(ctx.target, ctx.interval); + expect(query).to.equal(expected_query); + done(); + }); + + it('should add AS clause to SELECT if alias has been specified', function(done) { + ctx.target = { + metricAggs: [ + {type: 'avg', column: 'load[\'1\']', alias: 'load'} + ], + whereClauses: [], + groupByColumns: [], + }; + + var expected_query = "SELECT date_trunc('second', ts) as time, " + + "avg(load[\'1\']) AS \"load\" " + + "FROM \"stats\".\"nodes\" " + + "WHERE ts >= ? AND ts <= ? " + + "GROUP BY time " + + "ORDER BY time ASC"; + + var query = ctx.queryBuilder.buildAggQuery(ctx.target, ctx.interval); + expect(query).to.equal(expected_query); + done(); + }); + + it('should add limit to query if it passed', function(done) { + var expected_query = "SELECT date_trunc('second', ts) as time, " + + "avg(load) " + + "FROM \"stats\".\"nodes\" " + + "WHERE ts >= ? AND ts <= ? " + + "AND hostname = 'backend01' " + + "GROUP BY time " + + "ORDER BY time ASC"; + + var query = ctx.queryBuilder.buildAggQuery(ctx.target, ctx.interval, ctx.adhocFilters, ctx.limit); + expect(query).to.equal(expected_query); + done(); + }); + + it('should quote column names with capital letters', function(done) { + var queryBuilder = new CrateQueryBuilder('stats', 'nodes', 'tsCamelCase', 'minute', ctx.templateSrv); + ctx.target = { + metricAggs: [ + {type: 'sum', column: 'intValue'} + ], + whereClauses: [], + groupByColumns: [], + }; + + var expected_query = "SELECT date_trunc('second', \"tsCamelCase\") as time, " + + "sum(\"intValue\") " + + "FROM \"stats\".\"nodes\" " + + "WHERE \"tsCamelCase\" >= ? AND \"tsCamelCase\" <= ? " + + "GROUP BY time " + + "ORDER BY time ASC"; + + var query = queryBuilder.buildAggQuery(ctx.target, ctx.interval); + expect(query).to.equal(expected_query); + done(); + }); + + it('should add ad-hoc filters if it set', function(done) { + ctx.target.whereClauses = []; + ctx.adhocFilters = [ + {key: 'region', operator: '=', value: 'west'}, + {key: 'load', operator: '>', value: '2'} + ]; + + var expected_query = "SELECT date_trunc('second', ts) as time, " + + "avg(load) " + + "FROM \"stats\".\"nodes\" " + + "WHERE ts >= ? AND ts <= ? " + + "AND region = 'west' " + + "AND load > 2 " + + "GROUP BY time " + + "ORDER BY time ASC"; + + var query = ctx.queryBuilder.buildAggQuery(ctx.target, ctx.interval, ctx.adhocFilters); + expect(query).to.equal(expected_query); + done(); + }); + }); + + describe('When building raw query', function() { + beforeEach(function() { + ctx.target = { + metricAggs: [ + {type: 'raw', column: 'load'} + ], + whereClauses: [ + {condition: 'AND', column: 'hostname', operator: '=', value: 'backend01'} + ], + groupByColumns: [], + timeInterval: 'auto' + }; + }); + + it('should build proper SQL query', function(done) { + ctx.target = { + metricAggs: [ + {type: 'raw', column: 'load'} + ], + whereClauses: [], + groupByColumns: [], + }; + + var expected_query = "SELECT ts as time, " + + "load " + + "FROM \"stats\".\"nodes\" " + + "WHERE ts >= ? AND ts <= ? " + + "GROUP BY time, load " + + "ORDER BY time ASC LIMIT 100"; + + var query = ctx.queryBuilder.buildRawAggQuery(ctx.target, ctx.interval, ctx.adhocFilters, ctx.limit); + expect(query).to.equal(expected_query); + done(); + }); + }); + + describe('When Group By time Interval set', function () { + beforeEach(function () { + ctx.target = { + metricAggs: [ + { type: 'avg', column: 'load' } + ], + groupByColumns: [], + timeInterval: 'auto' + }; + }); + + it('should use date_trunc if set to "second"', function (done) { + ctx.interval = 'second'; + + var expected_query = "SELECT date_trunc('second', ts) as time, " + + "avg(load) " + + "FROM \"stats\".\"nodes\" " + + "WHERE ts >= ? AND ts <= ? " + + "GROUP BY time " + + "ORDER BY time ASC"; + + var query = ctx.queryBuilder.buildAggQuery(ctx.target, ctx.interval, ctx.adhocFilters, ctx.limit); + expect(query).to.equal(expected_query); + done(); + }); + + it('should use date_trunc if set to "minute"', function (done) { + ctx.interval = 'minute'; + + var expected_query = "SELECT date_trunc('minute', ts) as time, " + + "avg(load) " + + "FROM \"stats\".\"nodes\" " + + "WHERE ts >= ? AND ts <= ? " + + "GROUP BY time " + + "ORDER BY time ASC"; + + var query = ctx.queryBuilder.buildAggQuery(ctx.target, ctx.interval, ctx.adhocFilters, ctx.limit); + expect(query).to.equal(expected_query); + done(); + }); + + it('should use floor() if set to "auto_gf"', function (done) { + ctx.interval = 60; + + var expected_query = "SELECT floor(ts/60)*60 as time, " + + "avg(load) " + + "FROM \"stats\".\"nodes\" " + + "WHERE ts >= ? AND ts <= ? " + + "GROUP BY time " + + "ORDER BY time ASC"; + + var query = ctx.queryBuilder.buildAggQuery(ctx.target, ctx.interval, ctx.adhocFilters, ctx.limit); + expect(query).to.equal(expected_query); + done(); + }); + }); + + describe('When building columns query', function() { + + it('should build proper Crate SQL query', function(done) { + var expected_query = "SELECT column_name " + + "FROM information_schema.columns " + + "WHERE table_schema = 'stats' " + + "AND table_name = 'nodes' " + + "ORDER BY 1"; + var query = ctx.queryBuilder.getColumnsQuery(); + expect(query).to.equal(expected_query); + done(); + }); + }); + + describe('When building values query', function() { + + it('should build proper Crate SQL query', function(done) { + var expected_query = "SELECT DISTINCT load " + + "FROM \"stats\".\"nodes\""; + var query = ctx.queryBuilder.getValuesQuery('load'); + expect(query).to.equal(expected_query); + done(); + }); + + it('should add time range to query if it passed', function(done) { + var expected_query = "SELECT DISTINCT load " + + "FROM \"stats\".\"nodes\" " + + "WHERE ts >= 123 AND ts <= 456 " + + "LIMIT 10"; + + var timeRange = {from: 123, to: 456}; + var query = ctx.queryBuilder.getValuesQuery('load', 10, timeRange); + expect(query).to.equal(expected_query); + done(); + }); + + it('should add limit to query if it passed', function(done) { + var expected_query = "SELECT DISTINCT load " + + "FROM \"stats\".\"nodes\" LIMIT 10"; + var query = ctx.queryBuilder.getValuesQuery('load', 10); + expect(query).to.equal(expected_query); + done(); + }); + }); +}); diff --git a/deploy/crate-datasource/src/spec/response_handler_specs.js b/deploy/crate-datasource/src/spec/response_handler_specs.js new file mode 100755 index 0000000..e27be5c --- /dev/null +++ b/deploy/crate-datasource/src/spec/response_handler_specs.js @@ -0,0 +1,270 @@ +//import {describe, beforeEach, it, sinon, expect} from '../utils/test_common'; +import handleResponse from '../response_handler'; + +describe('Response Handler', function() { + var ctx = {}; + + describe('When handling Crate response', function() { + + beforeEach(function() { + ctx.target = {}; + ctx.crateResponse = {}; + }); + + it('should convert timeseries data to grafana format', function(done) { + ctx.target = { + "groupByColumns": [], + "metricAggs": [ + {"column": "value", "type": "avg"} + ], + "whereClauses": [] + }; + + ctx.crateResponse = { + "cols": ["time","avg(value)"], + "duration": 16, + "rowcount":5, + "rows":[ + [1466640780000,1.2562332153320312], + [1466640840000,1.1889413595199585], + [1466640900000,1.3127131064732869], + [1466640960000,1.3972599903742473], + [1466641020000,1.27950386206309] + ] + }; + + var result = handleResponse(ctx.target, ctx.crateResponse); + expect(result[0].datapoints).to.deep.equal([ + [1.2562332153320312,1466640780000], + [1.1889413595199585,1466640840000], + [1.3127131064732869,1466640900000], + [1.3972599903742473,1466640960000], + [1.27950386206309,1466641020000] + ]); + done(); + }); + + // TODO: find better default metric name + it('should set metric name if no group by columns selected', function(done) { + ctx.target = { + "groupByColumns": [], + "metricAggs": [ + {"column": "value", "type": "avg"} + ], + "whereClauses": [] + }; + + ctx.crateResponse = { + "cols": ["time","avg(value)"], + "duration": 16, + "rowcount":5, + "rows":[ + [1466640780000,1.2562332153320312], + [1466640840000,1.1889413595199585], + [1466640900000,1.3127131064732869], + [1466640960000,1.3972599903742473], + [1466641020000,1.27950386206309] + ] + }; + + var result = handleResponse(ctx.target, ctx.crateResponse); + var series = result[0]; + expect(series).to.have.property('target'); + expect(series).to.have.property('datapoints'); + //expect(series.target).to.equal(""); + done(); + }); + + it('should group response by selected columns', function(done) { + ctx.target = { + "groupByColumns": ["host"], + "groupByAliases": [], + "metricAggs": [ + {"column": "value", "type": "avg"} + ], + "whereClauses": [] + }; + + ctx.crateResponse = { + "cols": ["time","avg(value)","host"], + "duration": 16, + "rowcount":10, + "rows":[ + [1466640780000,1.2562332153320312,"backend01"], + [1466640840000,1.1889413595199585,"backend01"], + [1466640900000,1.3127131064732869,"backend01"], + [1466640960000,1.3972599903742473,"backend01"], + [1466641020000,1.27950386206309,"backend01"], + [1466641080000,1.3942841291427612,"backend02"], + [1466641140000,1.245995541413625,"backend02"], + [1466641200000,1.3355928659439087,"backend02"], + [1466641260000,1.2358959714571636,"backend02"], + [1466641320000,1.4172419905662537,"backend02"] + ] + }; + + var result = handleResponse(ctx.target, ctx.crateResponse); + expect(result.length).to.equal(2); + expect(result[0]).to.have.property('target'); + expect(result[0]).to.have.property('datapoints'); + expect(result[0].target).to.equal('backend01: avg(value)'); + expect(result[1]).to.have.property('target'); + expect(result[1]).to.have.property('datapoints'); + expect(result[1].target).to.equal('backend02: avg(value)'); + done(); + }); + + it('should transform to set of series for all group by columns', function(done) { + ctx.target = { + "groupByColumns": ["host", "metric"], + "groupByAliases": [], + "metricAggs": [ + {"column": "value", "type": "avg"} + ], + "whereClauses": [] + }; + + ctx.crateResponse = { + "cols": ["time","avg(value)","host", "metric"], + "duration": 16, + "rowcount":10, + "rows":[ + [1466640780000,1.2562332153320312,"backend01", "load1"], + [1466640840000,1.1889413595199585,"backend01", "load1"], + + [1466640900000,1.3127131064732869,"backend01", "load5"], + [1466640960000,1.3972599903742473,"backend01", "load5"], + [1466641020000,1.27950386206309, "backend01", "load5"], + + [1466641080000,1.3942841291427612,"backend02", "load1"], + [1466641140000,1.245995541413625, "backend02", "load1"], + + [1466641200000,1.3355928659439087,"backend02", "load5"], + [1466641260000,1.2358959714571636,"backend02", "load5"], + [1466641320000,1.4172419905662537,"backend02", "load5"] + ] + }; + + var result = handleResponse(ctx.target, ctx.crateResponse); + expect(result.length).to.equal(4); + expect(result[0].datapoints).to.deep.equal([ + [1.2562332153320312,1466640780000], + [1.1889413595199585,1466640840000] + ]); + expect(result[0].target).to.equal('backend01 load1: avg(value)'); + done(); + }); + + it('should handle multiple select values', function(done) { + ctx.target = { + "groupByColumns": [], + "metricAggs": [ + {"column": "load1", "type": "avg"}, + {"column": "load15", "type": "avg"} + ], + "whereClauses": [] + }; + + ctx.crateResponse = { + "cols": ["time","avg(load1)","avg(load15)"], + "duration": 16, + "rowcount":5, + "rows":[ + [1466640780000,1.2562332153320312,1.12], + [1466640840000,1.1889413595199585,1.01], + [1466640900000,1.3127131064732869,1.21], + [1466640960000,1.3972599903742473,1.28], + [1466641020000,1.27950386206309,1.16] + ] + }; + + var result = handleResponse(ctx.target, ctx.crateResponse); + expect(result).to.deep.equal([ + { + target: 'avg(load1)', + datapoints: [ + [1.2562332153320312,1466640780000], + [1.1889413595199585,1466640840000], + [1.3127131064732869,1466640900000], + [1.3972599903742473,1466640960000], + [1.27950386206309,1466641020000] + ] + }, + { + target: 'avg(load15)', + datapoints: [ + [1.12,1466640780000], + [1.01,1466640840000], + [1.21,1466640900000], + [1.28,1466640960000], + [1.16,1466641020000] + ] + } + ]); + done(); + }); + + }); + + describe('When handling raw response', function() { + + beforeEach(function() { + ctx.target = {}; + ctx.crateResponse = {}; + }); + + it('should handle GROUP BY columns', function(done) { + ctx.target = { + "rawQuery": true, + "query": "SELECT ts as time, load, hostname " + + "FROM stats.nodes WHERE ts >= ? AND ts <= ? " + + "GROUP BY time, load, hostname " + + "ORDER BY time ASC" + }; + + ctx.crateResponse = { + "cols": ["time", "load", "hostname"], + "duration": 16, + "rowcount":5, + "rows":[ + [1466640780000,1.2562332153320312, "host01"], + [1466640780000,1.2562332153320312, "host02"], + [1466640840000,1.1889413595199585, "host01"], + [1466640840000,1.1889413595199585, "host02"], + [1466640900000,1.3127131064732869, "host01"], + [1466640900000,1.3127131064732869, "host02"], + [1466640960000,1.3972599903742473, "host01"], + [1466640960000,1.3972599903742473, "host02"], + [1466641020000,1.27950386206309, "host01"], + [1466641020000,1.27950386206309, "host02"] + ] + }; + + var result = handleResponse(ctx.target, ctx.crateResponse); + expect(result).to.deep.equal([ + { + target: 'host01: load', + datapoints: [ + [1.2562332153320312,1466640780000], + [1.1889413595199585,1466640840000], + [1.3127131064732869,1466640900000], + [1.3972599903742473,1466640960000], + [1.27950386206309,1466641020000] + ] + }, + { + target: 'host02: load', + datapoints: [ + [1.2562332153320312,1466640780000], + [1.1889413595199585,1466640840000], + [1.3127131064732869,1466640900000], + [1.3972599903742473,1466640960000], + [1.27950386206309,1466641020000] + ] + } + ]); + done(); + }); + }); + +}); diff --git a/deploy/crate-datasource/src/spec/test-main.js b/deploy/crate-datasource/src/spec/test-main.js new file mode 100755 index 0000000..70fcee1 --- /dev/null +++ b/deploy/crate-datasource/src/spec/test-main.js @@ -0,0 +1,56 @@ +import prunk from 'prunk'; +import {jsdom} from 'jsdom'; +import chai from 'chai'; +import _ from 'lodash'; + +// Mock angular module +var angularMocks = { + module: function() { + return { + directive: function() { } + }; + } +}; + +var datemathMock = { + parse: function() { } +}; + +var configMock = { + bootData: { + user: { + lightTheme: false + } + } +}; + +// Mock lodash for using with CommonJS in tests. +// Because typescript compiler generates code like this: +// lodash["default"].map() - it uses default export. +var lodashMock = { + default: _ +}; + +// Mock Grafana modules that are not available outside of the core project +// Required for loading module.js +prunk.mock('./css/query-editor.css!', 'no css, dude.'); +prunk.mock('app/plugins/sdk', { + QueryCtrl: null +}); +prunk.mock('app/core/utils/datemath', datemathMock); +prunk.mock('app/core/config', configMock); +prunk.mock('angular', angularMocks); +prunk.mock('jquery', 'module not found'); +prunk.mock('lodash', lodashMock); + +// Setup jsdom +// Required for loading angularjs +global.document = jsdom(''); +global.window = global.document.parentWindow; +global.navigator = window.navigator = {}; +global.Node = window.Node; + +// Setup Chai +chai.should(); +global.assert = chai.assert; +global.expect = chai.expect; diff --git a/deploy/crate-datasource/tsconfig.json b/deploy/crate-datasource/tsconfig.json new file mode 100755 index 0000000..f74d811 --- /dev/null +++ b/deploy/crate-datasource/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "sourceMap": true, + "declaration": true, + "outDir": "dist", + "noImplicitAny": false, + "target": "es3", + "rootDir": "src/", + "sourceRoot": "src/", + "module": "system", + "noEmitOnError": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true + }, + "files": [ + "src/**/*.ts" + ] +} diff --git a/deploy/crate-datasource/tsd.json b/deploy/crate-datasource/tsd.json new file mode 100755 index 0000000..d384b2f --- /dev/null +++ b/deploy/crate-datasource/tsd.json @@ -0,0 +1,33 @@ +{ + "version": "v4", + "repo": "angular/DefinitelyTyped", + "ref": "master", + "path": "headers", + "bundle": "headers/common.d.ts", + "installed": { + "es6-promise/es6-promise.d.ts": { + "commit": "31e7317c9a0793857109236ef7c7f223305a8aa9" + }, + "mocha/mocha.d.ts": { + "commit": "055b3172e8eb374a75826710c4d08677872620d3" + }, + "zone/zone.d.ts": { + "commit": "055b3172e8eb374a75826710c4d08677872620d3" + }, + "rx/rx.d.ts": { + "commit": "31e7317c9a0793857109236ef7c7f223305a8aa9" + }, + "rx/rx-lite.d.ts": { + "commit": "31e7317c9a0793857109236ef7c7f223305a8aa9" + }, + "angular2/angular2.d.ts": { + "commit": "31e7317c9a0793857109236ef7c7f223305a8aa9" + }, + "es6-shim/es6-shim.d.ts": { + "commit": "31e7317c9a0793857109236ef7c7f223305a8aa9" + }, + "jquery/jquery.d.ts": { + "commit": "31e7317c9a0793857109236ef7c7f223305a8aa9" + } + } +} diff --git a/deploy/crate-datasource/tslint.json b/deploy/crate-datasource/tslint.json new file mode 100755 index 0000000..15e36cf --- /dev/null +++ b/deploy/crate-datasource/tslint.json @@ -0,0 +1,61 @@ +{ + "rules": { + "class-name": true, + "comment-format": [false, "check-space"], + "curly": true, + "eofline": true, + "forin": false, + "indent": [true, "spaces"], + "label-position": true, + "label-undefined": true, + "max-line-length": [true, 140], + "member-access": false, + "no-arg": true, + "no-bitwise": true, + "no-console": [true, + "debug", + "info", + "time", + "timeEnd", + "trace" + ], + "no-construct": true, + "no-debugger": true, + "no-duplicate-key": true, + "no-duplicate-variable": true, + "no-empty": false, + "no-eval": true, + "no-inferrable-types": true, + "no-shadowed-variable": false, + "no-string-literal": false, + "no-switch-case-fall-through": false, + "no-trailing-whitespace": true, + "no-unused-expression": false, + "no-unused-variable": false, + "no-unreachable": true, + "no-use-before-declare": true, + "no-var-keyword": false, + "object-literal-sort-keys": false, + "one-line": [true, + "check-open-brace", + "check-catch", + "check-else" + ], + "radix": false, + "semicolon": true, + "triple-equals": [true, "allow-null-check"], + "typedef-whitespace": [true, { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + }], + "variable-name": [true, "ban-keywords"], + "whitespace": [true, + "check-branch", + "check-decl", + "check-type" + ] + } +} diff --git a/deploy/cratedata/data/nodes/0/_state/global-4.st b/deploy/cratedata/data/nodes/0/_state/global-4.st new file mode 100644 index 0000000..b930059 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/_state/global-4.st differ diff --git a/deploy/cratedata/data/nodes/0/_state/manifest-17.st b/deploy/cratedata/data/nodes/0/_state/manifest-17.st new file mode 100644 index 0000000..5ae1dcd Binary files /dev/null and b/deploy/cratedata/data/nodes/0/_state/manifest-17.st differ diff --git a/deploy/cratedata/data/nodes/0/_state/node-0.st b/deploy/cratedata/data/nodes/0/_state/node-0.st new file mode 100644 index 0000000..dd1402f Binary files /dev/null and b/deploy/cratedata/data/nodes/0/_state/node-0.st differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/_state/state-0.st b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/_state/state-0.st new file mode 100644 index 0000000..da6ac3f Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/_state/state-0.st differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/index/_0.cfe b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/index/_0.cfe new file mode 100644 index 0000000..3cc33c1 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/index/_0.cfe differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/index/_0.cfs b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/index/_0.cfs new file mode 100644 index 0000000..b7abec9 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/index/_0.cfs differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/index/_0.si b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/index/_0.si new file mode 100644 index 0000000..4259269 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/index/_0.si differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/index/segments_2 b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/index/segments_2 new file mode 100644 index 0000000..8bb5d88 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/index/segments_2 differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/index/write.lock b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/index/write.lock new file mode 100644 index 0000000..e69de29 diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/translog/translog-1.ckp b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/translog/translog-1.ckp new file mode 100644 index 0000000..2cc8916 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/translog/translog-1.ckp differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/translog/translog-1.tlog b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/translog/translog-1.tlog new file mode 100644 index 0000000..c8004d2 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/translog/translog-1.tlog differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/translog/translog-2.tlog b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/translog/translog-2.tlog new file mode 100644 index 0000000..5f00a10 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/translog/translog-2.tlog differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/translog/translog.ckp b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/translog/translog.ckp new file mode 100644 index 0000000..33a58fd Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/0/translog/translog.ckp differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/1/_state/state-0.st b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/1/_state/state-0.st new file mode 100644 index 0000000..8fa850e Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/1/_state/state-0.st differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/1/index/segments_2 b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/1/index/segments_2 new file mode 100644 index 0000000..5d0a4b2 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/1/index/segments_2 differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/1/index/write.lock b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/1/index/write.lock new file mode 100644 index 0000000..e69de29 diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/1/translog/translog-1.ckp b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/1/translog/translog-1.ckp new file mode 100644 index 0000000..2cc8916 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/1/translog/translog-1.ckp differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/1/translog/translog-1.tlog b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/1/translog/translog-1.tlog new file mode 100644 index 0000000..518c3b3 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/1/translog/translog-1.tlog differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/1/translog/translog-2.tlog b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/1/translog/translog-2.tlog new file mode 100644 index 0000000..518c3b3 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/1/translog/translog-2.tlog differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/1/translog/translog.ckp b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/1/translog/translog.ckp new file mode 100644 index 0000000..a2582fe Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/1/translog/translog.ckp differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/2/_state/state-0.st b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/2/_state/state-0.st new file mode 100644 index 0000000..3b02b9f Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/2/_state/state-0.st differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/2/index/segments_2 b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/2/index/segments_2 new file mode 100644 index 0000000..eb25498 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/2/index/segments_2 differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/2/index/write.lock b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/2/index/write.lock new file mode 100644 index 0000000..e69de29 diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/2/translog/translog-1.ckp b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/2/translog/translog-1.ckp new file mode 100644 index 0000000..2cc8916 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/2/translog/translog-1.ckp differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/2/translog/translog-1.tlog b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/2/translog/translog-1.tlog new file mode 100644 index 0000000..5c4fa49 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/2/translog/translog-1.tlog differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/2/translog/translog-2.tlog b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/2/translog/translog-2.tlog new file mode 100644 index 0000000..5c4fa49 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/2/translog/translog-2.tlog differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/2/translog/translog.ckp b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/2/translog/translog.ckp new file mode 100644 index 0000000..a2582fe Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/2/translog/translog.ckp differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/3/_state/state-0.st b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/3/_state/state-0.st new file mode 100644 index 0000000..27cd34b Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/3/_state/state-0.st differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/3/index/segments_2 b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/3/index/segments_2 new file mode 100644 index 0000000..17a0e78 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/3/index/segments_2 differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/3/index/write.lock b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/3/index/write.lock new file mode 100644 index 0000000..e69de29 diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/3/translog/translog-1.ckp b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/3/translog/translog-1.ckp new file mode 100644 index 0000000..2cc8916 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/3/translog/translog-1.ckp differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/3/translog/translog-1.tlog b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/3/translog/translog-1.tlog new file mode 100644 index 0000000..f6b9e26 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/3/translog/translog-1.tlog differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/3/translog/translog-2.tlog b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/3/translog/translog-2.tlog new file mode 100644 index 0000000..f6b9e26 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/3/translog/translog-2.tlog differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/3/translog/translog.ckp b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/3/translog/translog.ckp new file mode 100644 index 0000000..a2582fe Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/3/translog/translog.ckp differ diff --git a/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/_state/state-3.st b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/_state/state-3.st new file mode 100644 index 0000000..f56ae28 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/Gl6Y_hmQSpiBntIMB59mBQ/_state/state-3.st differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/_state/state-0.st b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/_state/state-0.st new file mode 100644 index 0000000..96b49bd Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/_state/state-0.st differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/index/_0.cfe b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/index/_0.cfe new file mode 100644 index 0000000..9451efe Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/index/_0.cfe differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/index/_0.cfs b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/index/_0.cfs new file mode 100644 index 0000000..c519673 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/index/_0.cfs differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/index/_0.si b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/index/_0.si new file mode 100644 index 0000000..6fe789d Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/index/_0.si differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/index/segments_2 b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/index/segments_2 new file mode 100644 index 0000000..5a4da4d Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/index/segments_2 differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/index/write.lock b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/index/write.lock new file mode 100644 index 0000000..e69de29 diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/translog/translog-1.ckp b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/translog/translog-1.ckp new file mode 100644 index 0000000..2cc8916 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/translog/translog-1.ckp differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/translog/translog-1.tlog b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/translog/translog-1.tlog new file mode 100644 index 0000000..6a0421e Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/translog/translog-1.tlog differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/translog/translog-2.tlog b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/translog/translog-2.tlog new file mode 100644 index 0000000..ce392be Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/translog/translog-2.tlog differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/translog/translog.ckp b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/translog/translog.ckp new file mode 100644 index 0000000..3a508d1 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/0/translog/translog.ckp differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/_state/state-0.st b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/_state/state-0.st new file mode 100644 index 0000000..a3c6ab9 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/_state/state-0.st differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/index/_0.cfe b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/index/_0.cfe new file mode 100644 index 0000000..e24045e Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/index/_0.cfe differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/index/_0.cfs b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/index/_0.cfs new file mode 100644 index 0000000..9cf8c78 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/index/_0.cfs differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/index/_0.si b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/index/_0.si new file mode 100644 index 0000000..a2b8859 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/index/_0.si differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/index/segments_2 b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/index/segments_2 new file mode 100644 index 0000000..369930d Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/index/segments_2 differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/index/write.lock b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/index/write.lock new file mode 100644 index 0000000..e69de29 diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/translog/translog-1.ckp b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/translog/translog-1.ckp new file mode 100644 index 0000000..2cc8916 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/translog/translog-1.ckp differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/translog/translog-1.tlog b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/translog/translog-1.tlog new file mode 100644 index 0000000..086b57c Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/translog/translog-1.tlog differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/translog/translog-2.tlog b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/translog/translog-2.tlog new file mode 100644 index 0000000..a2076bc Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/translog/translog-2.tlog differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/translog/translog.ckp b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/translog/translog.ckp new file mode 100644 index 0000000..3a508d1 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/1/translog/translog.ckp differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/_state/state-0.st b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/_state/state-0.st new file mode 100644 index 0000000..0004aec Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/_state/state-0.st differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/index/_0.cfe b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/index/_0.cfe new file mode 100644 index 0000000..28cef62 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/index/_0.cfe differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/index/_0.cfs b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/index/_0.cfs new file mode 100644 index 0000000..b5aae9a Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/index/_0.cfs differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/index/_0.si b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/index/_0.si new file mode 100644 index 0000000..1b86884 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/index/_0.si differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/index/segments_2 b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/index/segments_2 new file mode 100644 index 0000000..14b52d4 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/index/segments_2 differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/index/write.lock b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/index/write.lock new file mode 100644 index 0000000..e69de29 diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/translog/translog-1.ckp b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/translog/translog-1.ckp new file mode 100644 index 0000000..2cc8916 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/translog/translog-1.ckp differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/translog/translog-1.tlog b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/translog/translog-1.tlog new file mode 100644 index 0000000..f90cae2 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/translog/translog-1.tlog differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/translog/translog-2.tlog b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/translog/translog-2.tlog new file mode 100644 index 0000000..d1c5e43 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/translog/translog-2.tlog differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/translog/translog.ckp b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/translog/translog.ckp new file mode 100644 index 0000000..3a508d1 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/2/translog/translog.ckp differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/3/_state/state-0.st b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/3/_state/state-0.st new file mode 100644 index 0000000..30eaa72 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/3/_state/state-0.st differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/3/index/segments_2 b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/3/index/segments_2 new file mode 100644 index 0000000..bfaae61 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/3/index/segments_2 differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/3/index/write.lock b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/3/index/write.lock new file mode 100644 index 0000000..e69de29 diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/3/translog/translog-1.ckp b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/3/translog/translog-1.ckp new file mode 100644 index 0000000..2cc8916 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/3/translog/translog-1.ckp differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/3/translog/translog-1.tlog b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/3/translog/translog-1.tlog new file mode 100644 index 0000000..5098cc7 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/3/translog/translog-1.tlog differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/3/translog/translog-2.tlog b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/3/translog/translog-2.tlog new file mode 100644 index 0000000..5098cc7 Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/3/translog/translog-2.tlog differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/3/translog/translog.ckp b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/3/translog/translog.ckp new file mode 100644 index 0000000..a2582fe Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/3/translog/translog.ckp differ diff --git a/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/_state/state-4.st b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/_state/state-4.st new file mode 100644 index 0000000..5cad79f Binary files /dev/null and b/deploy/cratedata/data/nodes/0/indices/ragres8eSNKF9Tkb2N4X3A/_state/state-4.st differ diff --git a/deploy/cratedata/data/nodes/0/node.lock b/deploy/cratedata/data/nodes/0/node.lock new file mode 100644 index 0000000..e69de29 diff --git a/deploy/cratedata/log/gc.log b/deploy/cratedata/log/gc.log new file mode 100644 index 0000000..41df3d0 --- /dev/null +++ b/deploy/cratedata/log/gc.log @@ -0,0 +1,1302 @@ +[2021-01-28T10:41:06.405+0000][1][gc,heap] Heap region size: 1M +[2021-01-28T10:41:06.419+0000][1][gc ] Using G1 +[2021-01-28T10:41:06.419+0000][1][gc,heap,coops] Heap address: 0x00000000e0000000, size: 512 MB, Compressed Oops mode: 32-bit +[2021-01-28T10:41:06.419+0000][1][gc,cds ] Mark closed archive regions in map: [0x00000000fff00000, 0x00000000fff79ff8] +[2021-01-28T10:41:06.419+0000][1][gc,cds ] Mark open archive regions in map: [0x00000000ffe00000, 0x00000000ffe47ff8] +[2021-01-28T10:41:06.447+0000][1][gc ] Periodic GC disabled +[2021-01-28T10:41:06.522+0000][1][safepoint ] Safepoint "EnableBiasedLocking", Time since last: 82712526 ns, Reaching safepoint: 2094135 ns, At safepoint: 97845 ns, Total: 2191980 ns +[2021-01-28T10:41:06.535+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 12469823 ns, Reaching safepoint: 690045 ns, At safepoint: 64773 ns, Total: 754818 ns +[2021-01-28T10:41:06.632+0000][1][safepoint ] Safepoint "Deoptimize", Time since last: 96897100 ns, Reaching safepoint: 53789 ns, At safepoint: 26415 ns, Total: 80204 ns +[2021-01-28T10:41:06.949+0000][1][safepoint ] Safepoint "Deoptimize", Time since last: 317379598 ns, Reaching safepoint: 90417 ns, At safepoint: 42638 ns, Total: 133055 ns +[2021-01-28T10:41:07.362+0000][1][safepoint ] Safepoint "Deoptimize", Time since last: 412493565 ns, Reaching safepoint: 298153 ns, At safepoint: 62729 ns, Total: 360882 ns +[2021-01-28T10:41:07.701+0000][1][safepoint ] Safepoint "Deoptimize", Time since last: 334323990 ns, Reaching safepoint: 3683986 ns, At safepoint: 215786 ns, Total: 3899772 ns +[2021-01-28T10:41:08.707+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1005904419 ns, Reaching safepoint: 691410 ns, At safepoint: 2457 ns, Total: 693867 ns +[2021-01-28T10:41:09.713+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000203515 ns, Reaching safepoint: 5218715 ns, At safepoint: 31837 ns, Total: 5250552 ns +[2021-01-28T10:41:10.530+0000][1][gc,start ] GC(0) Pause Young (Normal) (G1 Evacuation Pause) +[2021-01-28T10:41:10.541+0000][1][gc,task ] GC(0) Using 4 workers of 4 for evacuation +[2021-01-28T10:41:10.541+0000][1][gc,age ] GC(0) Desired survivor size 2097152 bytes, new threshold 15 (max threshold 15) +[2021-01-28T10:41:10.639+0000][1][gc,age ] GC(0) Age table with threshold 15 (max threshold 15) +[2021-01-28T10:41:10.639+0000][1][gc,age ] GC(0) - age 1: 4096736 bytes, 4096736 total +[2021-01-28T10:41:10.640+0000][1][gc,phases ] GC(0) Pre Evacuate Collection Set: 0.0ms +[2021-01-28T10:41:10.640+0000][1][gc,phases ] GC(0) Evacuate Collection Set: 88.8ms +[2021-01-28T10:41:10.640+0000][1][gc,phases ] GC(0) Post Evacuate Collection Set: 8.9ms +[2021-01-28T10:41:10.640+0000][1][gc,phases ] GC(0) Other: 11.7ms +[2021-01-28T10:41:10.640+0000][1][gc,heap ] GC(0) Eden regions: 25->0(21) +[2021-01-28T10:41:10.640+0000][1][gc,heap ] GC(0) Survivor regions: 0->4(4) +[2021-01-28T10:41:10.640+0000][1][gc,heap ] GC(0) Old regions: 0->1 +[2021-01-28T10:41:10.640+0000][1][gc,heap ] GC(0) Archive regions: 2->2 +[2021-01-28T10:41:10.640+0000][1][gc,heap ] GC(0) Humongous regions: 1->1 +[2021-01-28T10:41:10.640+0000][1][gc,metaspace ] GC(0) Metaspace: 7349K->7349K(1056768K) +[2021-01-28T10:41:10.640+0000][1][gc ] GC(0) Pause Young (Normal) (G1 Evacuation Pause) 26M->6M(512M) 109.601ms +[2021-01-28T10:41:10.640+0000][1][gc,cpu ] GC(0) User=0.02s Sys=0.01s Real=0.11s +[2021-01-28T10:41:10.640+0000][1][safepoint ] Safepoint "G1CollectForAllocation", Time since last: 817622132 ns, Reaching safepoint: 126982 ns, At safepoint: 109782202 ns, Total: 109909184 ns +[2021-01-28T10:41:10.682+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 11764147 ns, Reaching safepoint: 30394971 ns, At safepoint: 166077 ns, Total: 30561048 ns +[2021-01-28T10:41:10.687+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 190416 ns, Reaching safepoint: 3322812 ns, At safepoint: 664992 ns, Total: 3987804 ns +[2021-01-28T10:41:10.688+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 242389 ns, Reaching safepoint: 592765 ns, At safepoint: 263860 ns, Total: 856625 ns +[2021-01-28T10:41:10.689+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 341748 ns, Reaching safepoint: 659981 ns, At safepoint: 149500 ns, Total: 809481 ns +[2021-01-28T10:41:10.690+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 300541 ns, Reaching safepoint: 299571 ns, At safepoint: 107830 ns, Total: 407401 ns +[2021-01-28T10:41:10.692+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 344580 ns, Reaching safepoint: 1598456 ns, At safepoint: 159414 ns, Total: 1757870 ns +[2021-01-28T10:41:10.695+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 530924 ns, Reaching safepoint: 2605312 ns, At safepoint: 124876 ns, Total: 2730188 ns +[2021-01-28T10:41:10.701+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1393790 ns, Reaching safepoint: 3013786 ns, At safepoint: 1314829 ns, Total: 4328615 ns +[2021-01-28T10:41:10.707+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 3907356 ns, Reaching safepoint: 2320811 ns, At safepoint: 332136 ns, Total: 2652947 ns +[2021-01-28T10:41:10.711+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 652412 ns, Reaching safepoint: 2935222 ns, At safepoint: 144118 ns, Total: 3079340 ns +[2021-01-28T10:41:10.720+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 721622 ns, Reaching safepoint: 7890273 ns, At safepoint: 700718 ns, Total: 8590991 ns +[2021-01-28T10:41:10.727+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1009132 ns, Reaching safepoint: 5849638 ns, At safepoint: 171451 ns, Total: 6021089 ns +[2021-01-28T10:41:10.731+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 3087978 ns, Reaching safepoint: 300409 ns, At safepoint: 75283 ns, Total: 375692 ns +[2021-01-28T10:41:10.740+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 974379 ns, Reaching safepoint: 7558577 ns, At safepoint: 177338 ns, Total: 7735915 ns +[2021-01-28T10:41:10.745+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1522606 ns, Reaching safepoint: 1633473 ns, At safepoint: 1963616 ns, Total: 3597089 ns +[2021-01-28T10:41:10.747+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 391416 ns, Reaching safepoint: 1138257 ns, At safepoint: 614458 ns, Total: 1752715 ns +[2021-01-28T10:41:10.754+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1610112 ns, Reaching safepoint: 5922452 ns, At safepoint: 160516 ns, Total: 6082968 ns +[2021-01-28T10:41:10.756+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 429129 ns, Reaching safepoint: 840209 ns, At safepoint: 76312 ns, Total: 916521 ns +[2021-01-28T10:41:10.761+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2763334 ns, Reaching safepoint: 2598719 ns, At safepoint: 101520 ns, Total: 2700239 ns +[2021-01-28T10:41:10.762+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 370964 ns, Reaching safepoint: 555644 ns, At safepoint: 92535 ns, Total: 648179 ns +[2021-01-28T10:41:10.772+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 5591751 ns, Reaching safepoint: 1634683 ns, At safepoint: 2957587 ns, Total: 4592270 ns +[2021-01-28T10:41:10.781+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2736589 ns, Reaching safepoint: 5221577 ns, At safepoint: 166595 ns, Total: 5388172 ns +[2021-01-28T10:41:10.781+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 390951 ns, Reaching safepoint: 345831 ns, At safepoint: 41204 ns, Total: 387035 ns +[2021-01-28T10:41:10.783+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 376882 ns, Reaching safepoint: 636110 ns, At safepoint: 518756 ns, Total: 1154866 ns +[2021-01-28T10:41:10.786+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1656788 ns, Reaching safepoint: 927768 ns, At safepoint: 91376 ns, Total: 1019144 ns +[2021-01-28T10:41:10.789+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 573884 ns, Reaching safepoint: 2322667 ns, At safepoint: 375490 ns, Total: 2698157 ns +[2021-01-28T10:41:10.790+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 199853 ns, Reaching safepoint: 712959 ns, At safepoint: 58373 ns, Total: 771332 ns +[2021-01-28T10:41:10.792+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 705711 ns, Reaching safepoint: 121825 ns, At safepoint: 1051353 ns, Total: 1173178 ns +[2021-01-28T10:41:10.794+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 566541 ns, Reaching safepoint: 688529 ns, At safepoint: 1094015 ns, Total: 1782544 ns +[2021-01-28T10:41:10.799+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2131647 ns, Reaching safepoint: 2429526 ns, At safepoint: 100968 ns, Total: 2530494 ns +[2021-01-28T10:41:10.802+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 277343 ns, Reaching safepoint: 2975563 ns, At safepoint: 54333 ns, Total: 3029896 ns +[2021-01-28T10:41:10.803+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 489750 ns, Reaching safepoint: 715803 ns, At safepoint: 81999 ns, Total: 797802 ns +[2021-01-28T10:41:10.804+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 458447 ns, Reaching safepoint: 255827 ns, At safepoint: 117731 ns, Total: 373558 ns +[2021-01-28T10:41:10.806+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 573599 ns, Reaching safepoint: 668671 ns, At safepoint: 377658 ns, Total: 1046329 ns +[2021-01-28T10:41:10.812+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1063511 ns, Reaching safepoint: 4782810 ns, At safepoint: 270763 ns, Total: 5053573 ns +[2021-01-28T10:41:10.815+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2301629 ns, Reaching safepoint: 1109476 ns, At safepoint: 63573 ns, Total: 1173049 ns +[2021-01-28T10:41:11.526+0000][1][safepoint ] Safepoint "Deoptimize", Time since last: 706675553 ns, Reaching safepoint: 3740974 ns, At safepoint: 183958 ns, Total: 3924932 ns +[2021-01-28T10:41:12.440+0000][1][safepoint ] Safepoint "Deoptimize", Time since last: 910860906 ns, Reaching safepoint: 2548857 ns, At safepoint: 188784 ns, Total: 2737641 ns +[2021-01-28T10:41:13.442+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1001841061 ns, Reaching safepoint: 1040081 ns, At safepoint: 4278 ns, Total: 1044359 ns +[2021-01-28T10:41:13.984+0000][1][safepoint ] Safepoint "Deoptimize", Time since last: 536740929 ns, Reaching safepoint: 4423709 ns, At safepoint: 176260 ns, Total: 4599969 ns +[2021-01-28T10:41:14.995+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1002906764 ns, Reaching safepoint: 8700908 ns, At safepoint: 43059 ns, Total: 8743967 ns +[2021-01-28T10:41:15.002+0000][1][safepoint ] Safepoint "Deoptimize", Time since last: 2525166 ns, Reaching safepoint: 3299005 ns, At safepoint: 506232 ns, Total: 3805237 ns +[2021-01-28T10:41:15.010+0000][1][safepoint ] Safepoint "Deoptimize", Time since last: 7686340 ns, Reaching safepoint: 419222 ns, At safepoint: 357904 ns, Total: 777126 ns +[2021-01-28T10:41:15.101+0000][1][safepoint ] Safepoint "Deoptimize", Time since last: 88219492 ns, Reaching safepoint: 1984769 ns, At safepoint: 215405 ns, Total: 2200174 ns +[2021-01-28T10:41:15.109+0000][1][safepoint ] Safepoint "Deoptimize", Time since last: 204836 ns, Reaching safepoint: 8309631 ns, At safepoint: 215076 ns, Total: 8524707 ns +[2021-01-28T10:41:15.130+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 19843939 ns, Reaching safepoint: 303079 ns, At safepoint: 21512 ns, Total: 324591 ns +[2021-01-28T10:41:15.142+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 64347 ns, Reaching safepoint: 11855694 ns, At safepoint: 61640 ns, Total: 11917334 ns +[2021-01-28T10:41:15.145+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 142423 ns, Reaching safepoint: 2822662 ns, At safepoint: 53578 ns, Total: 2876240 ns +[2021-01-28T10:41:15.162+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 3842138 ns, Reaching safepoint: 13791425 ns, At safepoint: 84432 ns, Total: 13875857 ns +[2021-01-28T10:41:15.163+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 533383 ns, Reaching safepoint: 247033 ns, At safepoint: 72768 ns, Total: 319801 ns +[2021-01-28T10:41:15.200+0000][1][gc,start ] GC(1) Pause Young (Normal) (G1 Evacuation Pause) +[2021-01-28T10:41:15.200+0000][1][gc,task ] GC(1) Using 4 workers of 4 for evacuation +[2021-01-28T10:41:15.200+0000][1][gc,age ] GC(1) Desired survivor size 2097152 bytes, new threshold 1 (max threshold 15) +[2021-01-28T10:41:15.232+0000][1][gc,age ] GC(1) Age table with threshold 1 (max threshold 15) +[2021-01-28T10:41:15.232+0000][1][gc,age ] GC(1) - age 1: 1515008 bytes, 1515008 total +[2021-01-28T10:41:15.232+0000][1][gc,phases ] GC(1) Pre Evacuate Collection Set: 0.0ms +[2021-01-28T10:41:15.232+0000][1][gc,phases ] GC(1) Evacuate Collection Set: 27.7ms +[2021-01-28T10:41:15.232+0000][1][gc,phases ] GC(1) Post Evacuate Collection Set: 4.1ms +[2021-01-28T10:41:15.232+0000][1][gc,phases ] GC(1) Other: 0.2ms +[2021-01-28T10:41:15.232+0000][1][gc,heap ] GC(1) Eden regions: 21->0(29) +[2021-01-28T10:41:15.232+0000][1][gc,heap ] GC(1) Survivor regions: 4->2(4) +[2021-01-28T10:41:15.232+0000][1][gc,heap ] GC(1) Old regions: 1->5 +[2021-01-28T10:41:15.232+0000][1][gc,heap ] GC(1) Archive regions: 2->2 +[2021-01-28T10:41:15.232+0000][1][gc,heap ] GC(1) Humongous regions: 1->1 +[2021-01-28T10:41:15.232+0000][1][gc,metaspace ] GC(1) Metaspace: 11616K->11616K(1060864K) +[2021-01-28T10:41:15.233+0000][1][gc ] GC(1) Pause Young (Normal) (G1 Evacuation Pause) 27M->7M(512M) 32.104ms +[2021-01-28T10:41:15.233+0000][1][gc,cpu ] GC(1) User=0.02s Sys=0.00s Real=0.03s +[2021-01-28T10:41:15.233+0000][1][safepoint ] Safepoint "G1CollectForAllocation", Time since last: 33378716 ns, Reaching safepoint: 3871704 ns, At safepoint: 32178241 ns, Total: 36049945 ns +[2021-01-28T10:41:15.235+0000][1][safepoint ] Safepoint "BulkRevokeBias", Time since last: 736170 ns, Reaching safepoint: 1149955 ns, At safepoint: 141315 ns, Total: 1291270 ns +[2021-01-28T10:41:15.235+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 74191 ns, Reaching safepoint: 709134 ns, At safepoint: 26303 ns, Total: 735437 ns +[2021-01-28T10:41:15.239+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 3124895 ns, Reaching safepoint: 520762 ns, At safepoint: 72086 ns, Total: 592848 ns +[2021-01-28T10:41:15.285+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 39080919 ns, Reaching safepoint: 7244554 ns, At safepoint: 40069 ns, Total: 7284623 ns +[2021-01-28T10:41:16.288+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000179538 ns, Reaching safepoint: 2167621 ns, At safepoint: 30478 ns, Total: 2198099 ns +[2021-01-28T10:41:16.349+0000][1][gc,start ] GC(2) Pause Young (Normal) (G1 Evacuation Pause) +[2021-01-28T10:41:16.349+0000][1][gc,task ] GC(2) Using 4 workers of 4 for evacuation +[2021-01-28T10:41:16.349+0000][1][gc,age ] GC(2) Desired survivor size 2097152 bytes, new threshold 15 (max threshold 15) +[2021-01-28T10:41:16.371+0000][1][gc,age ] GC(2) Age table with threshold 15 (max threshold 15) +[2021-01-28T10:41:16.372+0000][1][gc,age ] GC(2) - age 1: 1159488 bytes, 1159488 total +[2021-01-28T10:41:16.372+0000][1][gc,age ] GC(2) - age 2: 1500184 bytes, 2659672 total +[2021-01-28T10:41:16.372+0000][1][gc,phases ] GC(2) Pre Evacuate Collection Set: 0.0ms +[2021-01-28T10:41:16.372+0000][1][gc,phases ] GC(2) Evacuate Collection Set: 15.4ms +[2021-01-28T10:41:16.372+0000][1][gc,phases ] GC(2) Post Evacuate Collection Set: 6.5ms +[2021-01-28T10:41:16.372+0000][1][gc,phases ] GC(2) Other: 0.2ms +[2021-01-28T10:41:16.372+0000][1][gc,heap ] GC(2) Eden regions: 29->0(37) +[2021-01-28T10:41:16.372+0000][1][gc,heap ] GC(2) Survivor regions: 2->3(4) +[2021-01-28T10:41:16.372+0000][1][gc,heap ] GC(2) Old regions: 5->5 +[2021-01-28T10:41:16.372+0000][1][gc,heap ] GC(2) Archive regions: 2->2 +[2021-01-28T10:41:16.372+0000][1][gc,heap ] GC(2) Humongous regions: 1->1 +[2021-01-28T10:41:16.372+0000][1][gc,metaspace ] GC(2) Metaspace: 13698K->13698K(1062912K) +[2021-01-28T10:41:16.372+0000][1][gc ] GC(2) Pause Young (Normal) (G1 Evacuation Pause) 36M->9M(512M) 22.234ms +[2021-01-28T10:41:16.372+0000][1][gc,cpu ] GC(2) User=0.01s Sys=0.00s Real=0.02s +[2021-01-28T10:41:16.372+0000][1][safepoint ] Safepoint "G1CollectForAllocation", Time since last: 48654424 ns, Reaching safepoint: 12921894 ns, At safepoint: 22367755 ns, Total: 35289649 ns +[2021-01-28T10:41:16.380+0000][1][safepoint ] Safepoint "BulkRevokeBias", Time since last: 3359900 ns, Reaching safepoint: 4297423 ns, At safepoint: 215865 ns, Total: 4513288 ns +[2021-01-28T10:41:16.381+0000][1][safepoint ] Safepoint "BulkRevokeBias", Time since last: 193970 ns, Reaching safepoint: 1345795 ns, At safepoint: 114930 ns, Total: 1460725 ns +[2021-01-28T10:41:16.794+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 412979831 ns, Reaching safepoint: 146821 ns, At safepoint: 36048 ns, Total: 182869 ns +[2021-01-28T10:41:16.880+0000][1][gc,start ] GC(3) Pause Young (Normal) (G1 Evacuation Pause) +[2021-01-28T10:41:16.880+0000][1][gc,task ] GC(3) Using 4 workers of 4 for evacuation +[2021-01-28T10:41:16.880+0000][1][gc,age ] GC(3) Desired survivor size 2621440 bytes, new threshold 2 (max threshold 15) +[2021-01-28T10:41:16.891+0000][1][gc,age ] GC(3) Age table with threshold 2 (max threshold 15) +[2021-01-28T10:41:16.891+0000][1][gc,age ] GC(3) - age 1: 771824 bytes, 771824 total +[2021-01-28T10:41:16.891+0000][1][gc,age ] GC(3) - age 2: 315288 bytes, 1087112 total +[2021-01-28T10:41:16.892+0000][1][gc,phases ] GC(3) Pre Evacuate Collection Set: 0.1ms +[2021-01-28T10:41:16.892+0000][1][gc,phases ] GC(3) Evacuate Collection Set: 4.4ms +[2021-01-28T10:41:16.892+0000][1][gc,phases ] GC(3) Post Evacuate Collection Set: 6.5ms +[2021-01-28T10:41:16.892+0000][1][gc,phases ] GC(3) Other: 0.3ms +[2021-01-28T10:41:16.892+0000][1][gc,heap ] GC(3) Eden regions: 37->0(305) +[2021-01-28T10:41:16.892+0000][1][gc,heap ] GC(3) Survivor regions: 3->2(5) +[2021-01-28T10:41:16.892+0000][1][gc,heap ] GC(3) Old regions: 5->7 +[2021-01-28T10:41:16.892+0000][1][gc,heap ] GC(3) Archive regions: 2->2 +[2021-01-28T10:41:16.892+0000][1][gc,heap ] GC(3) Humongous regions: 1->1 +[2021-01-28T10:41:16.892+0000][1][gc,metaspace ] GC(3) Metaspace: 13874K->13874K(1062912K) +[2021-01-28T10:41:16.892+0000][1][gc ] GC(3) Pause Young (Normal) (G1 Evacuation Pause) 46M->9M(512M) 11.298ms +[2021-01-28T10:41:16.892+0000][1][gc,cpu ] GC(3) User=0.01s Sys=0.01s Real=0.01s +[2021-01-28T10:41:16.892+0000][1][safepoint ] Safepoint "G1CollectForAllocation", Time since last: 82978282 ns, Reaching safepoint: 2837465 ns, At safepoint: 11444257 ns, Total: 14281722 ns +[2021-01-28T10:41:16.904+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 8786045 ns, Reaching safepoint: 2917426 ns, At safepoint: 336371 ns, Total: 3253797 ns +[2021-01-28T10:41:16.917+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 441373 ns, Reaching safepoint: 12995568 ns, At safepoint: 112224 ns, Total: 13107792 ns +[2021-01-28T10:41:16.921+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1139367 ns, Reaching safepoint: 2084978 ns, At safepoint: 91260 ns, Total: 2176238 ns +[2021-01-28T10:41:16.923+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 731277 ns, Reaching safepoint: 1230609 ns, At safepoint: 91839 ns, Total: 1322448 ns +[2021-01-28T10:41:17.305+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 382154777 ns, Reaching safepoint: 156360 ns, At safepoint: 63459 ns, Total: 219819 ns +[2021-01-28T10:41:17.706+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 401206385 ns, Reaching safepoint: 170509 ns, At safepoint: 40669 ns, Total: 211178 ns +[2021-01-28T10:41:17.712+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2787995 ns, Reaching safepoint: 2807017 ns, At safepoint: 117700 ns, Total: 2924717 ns +[2021-01-28T10:41:17.713+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 972776 ns, Reaching safepoint: 227910 ns, At safepoint: 26267 ns, Total: 254177 ns +[2021-01-28T10:41:18.505+0000][1][safepoint ] Safepoint "Deoptimize", Time since last: 783250459 ns, Reaching safepoint: 7692904 ns, At safepoint: 380993 ns, Total: 8073897 ns +[2021-01-28T10:41:19.278+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 770579254 ns, Reaching safepoint: 2258846 ns, At safepoint: 48157 ns, Total: 2307003 ns +[2021-01-28T10:41:19.282+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2381492 ns, Reaching safepoint: 2289595 ns, At safepoint: 45857 ns, Total: 2335452 ns +[2021-01-28T10:41:19.656+0000][1][gc,start ] GC(4) Pause Young (Concurrent Start) (Metadata GC Threshold) +[2021-01-28T10:41:19.656+0000][1][gc,task ] GC(4) Using 4 workers of 4 for evacuation +[2021-01-28T10:41:19.656+0000][1][gc,age ] GC(4) Desired survivor size 20447232 bytes, new threshold 15 (max threshold 15) +[2021-01-28T10:41:19.682+0000][1][gc,age ] GC(4) Age table with threshold 15 (max threshold 15) +[2021-01-28T10:41:19.682+0000][1][gc,age ] GC(4) - age 1: 1691088 bytes, 1691088 total +[2021-01-28T10:41:19.682+0000][1][gc,age ] GC(4) - age 2: 18760 bytes, 1709848 total +[2021-01-28T10:41:19.682+0000][1][gc,age ] GC(4) - age 3: 309568 bytes, 2019416 total +[2021-01-28T10:41:19.682+0000][1][gc,phases ] GC(4) Pre Evacuate Collection Set: 0.1ms +[2021-01-28T10:41:19.682+0000][1][gc,phases ] GC(4) Evacuate Collection Set: 25.2ms +[2021-01-28T10:41:19.682+0000][1][gc,phases ] GC(4) Post Evacuate Collection Set: 1.3ms +[2021-01-28T10:41:19.683+0000][1][gc,phases ] GC(4) Other: 0.3ms +[2021-01-28T10:41:19.683+0000][1][gc,heap ] GC(4) Eden regions: 97->0(304) +[2021-01-28T10:41:19.683+0000][1][gc,heap ] GC(4) Survivor regions: 2->3(39) +[2021-01-28T10:41:19.683+0000][1][gc,heap ] GC(4) Old regions: 7->7 +[2021-01-28T10:41:19.683+0000][1][gc,heap ] GC(4) Archive regions: 2->2 +[2021-01-28T10:41:19.683+0000][1][gc,heap ] GC(4) Humongous regions: 1->1 +[2021-01-28T10:41:19.683+0000][1][gc,metaspace ] GC(4) Metaspace: 20605K->20605K(1067008K) +[2021-01-28T10:41:19.683+0000][1][gc ] GC(4) Pause Young (Concurrent Start) (Metadata GC Threshold) 105M->9M(512M) 26.958ms +[2021-01-28T10:41:19.683+0000][1][gc,cpu ] GC(4) User=0.02s Sys=0.00s Real=0.03s +[2021-01-28T10:41:19.683+0000][1][gc ] GC(5) Concurrent Cycle +[2021-01-28T10:41:19.683+0000][1][gc,marking ] GC(5) Concurrent Clear Claimed Marks +[2021-01-28T10:41:19.683+0000][1][gc,marking ] GC(5) Concurrent Clear Claimed Marks 0.074ms +[2021-01-28T10:41:19.683+0000][1][gc,marking ] GC(5) Concurrent Scan Root Regions +[2021-01-28T10:41:19.686+0000][1][safepoint ] Safepoint "CollectForMetadataAllocation", Time since last: 372975102 ns, Reaching safepoint: 251365 ns, At safepoint: 30550141 ns, Total: 30801506 ns +[2021-01-28T10:41:19.688+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1120231 ns, Reaching safepoint: 520813 ns, At safepoint: 46223 ns, Total: 567036 ns +[2021-01-28T10:41:19.688+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 144808 ns, Reaching safepoint: 200551 ns, At safepoint: 40414 ns, Total: 240965 ns +[2021-01-28T10:41:19.689+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 143829 ns, Reaching safepoint: 416888 ns, At safepoint: 35851 ns, Total: 452739 ns +[2021-01-28T10:41:19.695+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2102736 ns, Reaching safepoint: 3689064 ns, At safepoint: 56289 ns, Total: 3745353 ns +[2021-01-28T10:41:19.697+0000][1][gc,marking ] GC(5) Concurrent Scan Root Regions 13.956ms +[2021-01-28T10:41:19.697+0000][1][gc,marking ] GC(5) Concurrent Mark (13.311s) +[2021-01-28T10:41:19.697+0000][1][gc,marking ] GC(5) Concurrent Mark From Roots +[2021-01-28T10:41:19.697+0000][1][gc,task ] GC(5) Using 1 workers of 1 for marking +[2021-01-28T10:41:19.704+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 226750 ns, Reaching safepoint: 9013859 ns, At safepoint: 113872 ns, Total: 9127731 ns +[2021-01-28T10:41:19.706+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1161303 ns, Reaching safepoint: 508054 ns, At safepoint: 73293 ns, Total: 581347 ns +[2021-01-28T10:41:19.706+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 154207 ns, Reaching safepoint: 73580 ns, At safepoint: 27577 ns, Total: 101157 ns +[2021-01-28T10:41:19.706+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 162019 ns, Reaching safepoint: 73200 ns, At safepoint: 24503 ns, Total: 97703 ns +[2021-01-28T10:41:19.707+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 132406 ns, Reaching safepoint: 112006 ns, At safepoint: 31243 ns, Total: 143249 ns +[2021-01-28T10:41:19.712+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 121930 ns, Reaching safepoint: 5257451 ns, At safepoint: 76572 ns, Total: 5334023 ns +[2021-01-28T10:41:19.713+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 415030 ns, Reaching safepoint: 444020 ns, At safepoint: 56775 ns, Total: 500795 ns +[2021-01-28T10:41:19.715+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 129677 ns, Reaching safepoint: 1385914 ns, At safepoint: 102945 ns, Total: 1488859 ns +[2021-01-28T10:41:19.715+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 199685 ns, Reaching safepoint: 249970 ns, At safepoint: 42382 ns, Total: 292352 ns +[2021-01-28T10:41:19.715+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 176369 ns, Reaching safepoint: 211040 ns, At safepoint: 57198 ns, Total: 268238 ns +[2021-01-28T10:41:19.730+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 265934 ns, Reaching safepoint: 14100868 ns, At safepoint: 141982 ns, Total: 14242850 ns +[2021-01-28T10:41:19.802+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 48932953 ns, Reaching safepoint: 23240190 ns, At safepoint: 74112 ns, Total: 23314302 ns +[2021-01-28T10:41:19.805+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2164134 ns, Reaching safepoint: 875474 ns, At safepoint: 58371 ns, Total: 933845 ns +[2021-01-28T10:41:19.812+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 216370 ns, Reaching safepoint: 6225801 ns, At safepoint: 68987 ns, Total: 6294788 ns +[2021-01-28T10:41:19.817+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1082229 ns, Reaching safepoint: 4398857 ns, At safepoint: 94503 ns, Total: 4493360 ns +[2021-01-28T10:41:19.818+0000][1][gc,marking ] GC(5) Concurrent Mark From Roots 121.615ms +[2021-01-28T10:41:19.818+0000][1][gc,marking ] GC(5) Concurrent Preclean +[2021-01-28T10:41:19.819+0000][1][gc,marking ] GC(5) Concurrent Preclean 0.079ms +[2021-01-28T10:41:19.819+0000][1][gc,marking ] GC(5) Concurrent Mark (13.311s, 13.433s) 121.740ms +[2021-01-28T10:41:19.820+0000][1][gc,start ] GC(5) Pause Remark +[2021-01-28T10:41:19.839+0000][1][gc ] GC(5) Pause Remark 11M->11M(512M) 19.076ms +[2021-01-28T10:41:19.839+0000][1][gc,cpu ] GC(5) User=0.01s Sys=0.00s Real=0.02s +[2021-01-28T10:41:19.839+0000][1][safepoint ] Safepoint "G1Concurrent", Time since last: 1208260 ns, Reaching safepoint: 920747 ns, At safepoint: 19208123 ns, Total: 20128870 ns +[2021-01-28T10:41:19.839+0000][1][gc,marking ] GC(5) Concurrent Rebuild Remembered Sets +[2021-01-28T10:41:19.845+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 4082054 ns, Reaching safepoint: 1810763 ns, At safepoint: 70459 ns, Total: 1881222 ns +[2021-01-28T10:41:19.862+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 9435539 ns, Reaching safepoint: 7439341 ns, At safepoint: 134097 ns, Total: 7573438 ns +[2021-01-28T10:41:19.866+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 236939 ns, Reaching safepoint: 426362 ns, At safepoint: 3260031 ns, Total: 3686393 ns +[2021-01-28T10:41:19.866+0000][1][gc,marking ] GC(5) Concurrent Rebuild Remembered Sets 27.621ms +[2021-01-28T10:41:19.867+0000][1][gc,start ] GC(5) Pause Cleanup +[2021-01-28T10:41:19.867+0000][1][gc ] GC(5) Pause Cleanup 11M->11M(512M) 0.108ms +[2021-01-28T10:41:19.867+0000][1][gc,cpu ] GC(5) User=0.00s Sys=0.00s Real=0.00s +[2021-01-28T10:41:19.867+0000][1][safepoint ] Safepoint "G1Concurrent", Time since last: 910402 ns, Reaching safepoint: 114954 ns, At safepoint: 187084 ns, Total: 302038 ns +[2021-01-28T10:41:19.867+0000][1][gc,marking ] GC(5) Concurrent Cleanup for Next Mark +[2021-01-28T10:41:19.892+0000][1][gc,marking ] GC(5) Concurrent Cleanup for Next Mark 24.849ms +[2021-01-28T10:41:19.892+0000][1][gc ] GC(5) Concurrent Cycle 209.159ms +[2021-01-28T10:41:20.005+0000][1][safepoint ] Safepoint "Deoptimize", Time since last: 137460175 ns, Reaching safepoint: 273264 ns, At safepoint: 435018 ns, Total: 708282 ns +[2021-01-28T10:41:20.067+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 61742114 ns, Reaching safepoint: 113358 ns, At safepoint: 59085 ns, Total: 172443 ns +[2021-01-28T10:41:20.095+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 26773370 ns, Reaching safepoint: 131364 ns, At safepoint: 970215 ns, Total: 1101579 ns +[2021-01-28T10:41:21.103+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1001158170 ns, Reaching safepoint: 7059886 ns, At safepoint: 33623 ns, Total: 7093509 ns +[2021-01-28T10:41:22.104+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000353845 ns, Reaching safepoint: 147459 ns, At safepoint: 2482 ns, Total: 149941 ns +[2021-01-28T10:41:22.192+0000][1][safepoint ] Safepoint "Deoptimize", Time since last: 88168051 ns, Reaching safepoint: 121483 ns, At safepoint: 295266 ns, Total: 416749 ns +[2021-01-28T10:41:22.209+0000][1][safepoint ] Safepoint "Deoptimize", Time since last: 15221039 ns, Reaching safepoint: 1046311 ns, At safepoint: 375178 ns, Total: 1421489 ns +[2021-01-28T10:41:22.357+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 139891284 ns, Reaching safepoint: 7968295 ns, At safepoint: 78310 ns, Total: 8046605 ns +[2021-01-28T10:41:22.358+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 158176 ns, Reaching safepoint: 683053 ns, At safepoint: 111144 ns, Total: 794197 ns +[2021-01-28T10:41:22.361+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 75276 ns, Reaching safepoint: 3100558 ns, At safepoint: 102499 ns, Total: 3203057 ns +[2021-01-28T10:41:22.364+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1230411 ns, Reaching safepoint: 1819837 ns, At safepoint: 14543 ns, Total: 1834380 ns +[2021-01-28T10:41:22.365+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 695419 ns, Reaching safepoint: 291833 ns, At safepoint: 14411 ns, Total: 306244 ns +[2021-01-28T10:41:22.365+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 320231 ns, Reaching safepoint: 61000 ns, At safepoint: 2359 ns, Total: 63359 ns +[2021-01-28T10:41:22.368+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 551149 ns, Reaching safepoint: 2368985 ns, At safepoint: 24933 ns, Total: 2393918 ns +[2021-01-28T10:41:22.370+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1914665 ns, Reaching safepoint: 174276 ns, At safepoint: 15388 ns, Total: 189664 ns +[2021-01-28T10:41:22.740+0000][1][safepoint ] Safepoint "Deoptimize", Time since last: 368822773 ns, Reaching safepoint: 129881 ns, At safepoint: 367894 ns, Total: 497775 ns +[2021-01-28T10:41:23.279+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 539030394 ns, Reaching safepoint: 137327 ns, At safepoint: 45399 ns, Total: 182726 ns +[2021-01-28T10:41:24.279+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000325561 ns, Reaching safepoint: 172148 ns, At safepoint: 3001 ns, Total: 175149 ns +[2021-01-28T10:41:25.281+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000186531 ns, Reaching safepoint: 978334 ns, At safepoint: 3613 ns, Total: 981947 ns +[2021-01-28T10:41:26.285+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000989251 ns, Reaching safepoint: 3283734 ns, At safepoint: 5607 ns, Total: 3289341 ns +[2021-01-28T10:41:27.286+0000][1][gc,start ] GC(6) Pause Young (Concurrent Start) (Metadata GC Threshold) +[2021-01-28T10:41:27.286+0000][1][gc,task ] GC(6) Using 4 workers of 4 for evacuation +[2021-01-28T10:41:27.286+0000][1][gc,age ] GC(6) Desired survivor size 20447232 bytes, new threshold 15 (max threshold 15) +[2021-01-28T10:41:27.329+0000][1][gc,age ] GC(6) Age table with threshold 15 (max threshold 15) +[2021-01-28T10:41:27.329+0000][1][gc,age ] GC(6) - age 1: 5428536 bytes, 5428536 total +[2021-01-28T10:41:27.329+0000][1][gc,age ] GC(6) - age 2: 1604960 bytes, 7033496 total +[2021-01-28T10:41:27.329+0000][1][gc,age ] GC(6) - age 3: 18632 bytes, 7052128 total +[2021-01-28T10:41:27.329+0000][1][gc,age ] GC(6) - age 4: 286648 bytes, 7338776 total +[2021-01-28T10:41:27.329+0000][1][gc,phases ] GC(6) Pre Evacuate Collection Set: 0.2ms +[2021-01-28T10:41:27.329+0000][1][gc,phases ] GC(6) Evacuate Collection Set: 41.5ms +[2021-01-28T10:41:27.329+0000][1][gc,phases ] GC(6) Post Evacuate Collection Set: 1.1ms +[2021-01-28T10:41:27.329+0000][1][gc,phases ] GC(6) Other: 0.3ms +[2021-01-28T10:41:27.329+0000][1][gc,heap ] GC(6) Eden regions: 121->0(299) +[2021-01-28T10:41:27.329+0000][1][gc,heap ] GC(6) Survivor regions: 3->8(39) +[2021-01-28T10:41:27.329+0000][1][gc,heap ] GC(6) Old regions: 7->7 +[2021-01-28T10:41:27.329+0000][1][gc,heap ] GC(6) Archive regions: 2->2 +[2021-01-28T10:41:27.329+0000][1][gc,heap ] GC(6) Humongous regions: 2->1 +[2021-01-28T10:41:27.329+0000][1][gc,metaspace ] GC(6) Metaspace: 34529K->34529K(1081344K) +[2021-01-28T10:41:27.329+0000][1][gc ] GC(6) Pause Young (Concurrent Start) (Metadata GC Threshold) 131M->14M(512M) 43.152ms +[2021-01-28T10:41:27.329+0000][1][gc,cpu ] GC(6) User=0.04s Sys=0.00s Real=0.05s +[2021-01-28T10:41:27.329+0000][1][safepoint ] Safepoint "CollectForMetadataAllocation", Time since last: 1000127593 ns, Reaching safepoint: 568671 ns, At safepoint: 43303986 ns, Total: 43872657 ns +[2021-01-28T10:41:27.329+0000][1][gc ] GC(7) Concurrent Cycle +[2021-01-28T10:41:27.329+0000][1][gc,marking ] GC(7) Concurrent Clear Claimed Marks +[2021-01-28T10:41:27.329+0000][1][gc,marking ] GC(7) Concurrent Clear Claimed Marks 0.156ms +[2021-01-28T10:41:27.329+0000][1][gc,marking ] GC(7) Concurrent Scan Root Regions +[2021-01-28T10:41:27.385+0000][1][safepoint ] Safepoint "BulkRevokeBias", Time since last: 31385901 ns, Reaching safepoint: 24830185 ns, At safepoint: 126829 ns, Total: 24957014 ns +[2021-01-28T10:41:27.386+0000][1][gc,marking ] GC(7) Concurrent Scan Root Regions 57.037ms +[2021-01-28T10:41:27.386+0000][1][gc,marking ] GC(7) Concurrent Mark (21.001s) +[2021-01-28T10:41:27.386+0000][1][gc,marking ] GC(7) Concurrent Mark From Roots +[2021-01-28T10:41:27.386+0000][1][gc,task ] GC(7) Using 1 workers of 1 for marking +[2021-01-28T10:41:27.391+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 3023930 ns, Reaching safepoint: 3130925 ns, At safepoint: 66006 ns, Total: 3196931 ns +[2021-01-28T10:41:27.395+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 918806 ns, Reaching safepoint: 3008096 ns, At safepoint: 49576 ns, Total: 3057672 ns +[2021-01-28T10:41:27.401+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 151168 ns, Reaching safepoint: 5698933 ns, At safepoint: 98862 ns, Total: 5797795 ns +[2021-01-28T10:41:27.405+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 965383 ns, Reaching safepoint: 3025732 ns, At safepoint: 83878 ns, Total: 3109610 ns +[2021-01-28T10:41:27.413+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2006857 ns, Reaching safepoint: 5753745 ns, At safepoint: 85004 ns, Total: 5838749 ns +[2021-01-28T10:41:27.421+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2689987 ns, Reaching safepoint: 4363558 ns, At safepoint: 186201 ns, Total: 4549759 ns +[2021-01-28T10:41:27.427+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 169893 ns, Reaching safepoint: 5685061 ns, At safepoint: 124762 ns, Total: 5809823 ns +[2021-01-28T10:41:27.444+0000][1][safepoint ] Safepoint "BulkRevokeBias", Time since last: 756935 ns, Reaching safepoint: 16913356 ns, At safepoint: 181545 ns, Total: 17094901 ns +[2021-01-28T10:41:27.448+0000][1][safepoint ] Safepoint "BulkRevokeBias", Time since last: 160464 ns, Reaching safepoint: 2904338 ns, At safepoint: 105910 ns, Total: 3010248 ns +[2021-01-28T10:41:27.450+0000][1][gc,marking ] GC(7) Concurrent Mark From Roots 63.791ms +[2021-01-28T10:41:27.450+0000][1][gc,marking ] GC(7) Concurrent Preclean +[2021-01-28T10:41:27.450+0000][1][gc,marking ] GC(7) Concurrent Preclean 0.067ms +[2021-01-28T10:41:27.450+0000][1][gc,marking ] GC(7) Concurrent Mark (21.001s, 21.064s) 63.954ms +[2021-01-28T10:41:27.457+0000][1][gc,start ] GC(7) Pause Remark +[2021-01-28T10:41:27.470+0000][1][gc ] GC(7) Pause Remark 15M->15M(512M) 12.419ms +[2021-01-28T10:41:27.470+0000][1][gc,cpu ] GC(7) User=0.00s Sys=0.00s Real=0.01s +[2021-01-28T10:41:27.470+0000][1][safepoint ] Safepoint "G1Concurrent", Time since last: 3786708 ns, Reaching safepoint: 5932962 ns, At safepoint: 12551824 ns, Total: 18484786 ns +[2021-01-28T10:41:27.470+0000][1][gc,marking ] GC(7) Concurrent Rebuild Remembered Sets +[2021-01-28T10:41:27.488+0000][1][gc,marking ] GC(7) Concurrent Rebuild Remembered Sets 17.779ms +[2021-01-28T10:41:27.504+0000][1][gc,start ] GC(7) Pause Cleanup +[2021-01-28T10:41:27.504+0000][1][gc ] GC(7) Pause Cleanup 15M->15M(512M) 0.206ms +[2021-01-28T10:41:27.504+0000][1][gc,cpu ] GC(7) User=0.00s Sys=0.00s Real=0.00s +[2021-01-28T10:41:27.504+0000][1][safepoint ] Safepoint "G1Concurrent", Time since last: 21362952 ns, Reaching safepoint: 12286962 ns, At safepoint: 313789 ns, Total: 12600751 ns +[2021-01-28T10:41:27.505+0000][1][gc,marking ] GC(7) Concurrent Cleanup for Next Mark +[2021-01-28T10:41:27.513+0000][1][gc,marking ] GC(7) Concurrent Cleanup for Next Mark 8.075ms +[2021-01-28T10:41:27.513+0000][1][gc ] GC(7) Concurrent Cycle 184.034ms +[2021-01-28T10:41:27.611+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 105248527 ns, Reaching safepoint: 1510228 ns, At safepoint: 54437 ns, Total: 1564665 ns +[2021-01-28T10:41:27.966+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 352400930 ns, Reaching safepoint: 2481843 ns, At safepoint: 44436 ns, Total: 2526279 ns +[2021-01-28T10:41:27.981+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 14895444 ns, Reaching safepoint: 108838 ns, At safepoint: 12996 ns, Total: 121834 ns +[2021-01-28T10:41:27.984+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2934050 ns, Reaching safepoint: 165149 ns, At safepoint: 14869 ns, Total: 180018 ns +[2021-01-28T10:41:28.995+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000342787 ns, Reaching safepoint: 10855868 ns, At safepoint: 67222 ns, Total: 10923090 ns +[2021-01-28T10:41:30.000+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1002432477 ns, Reaching safepoint: 3001485 ns, At safepoint: 34310 ns, Total: 3035795 ns +[2021-01-28T10:41:30.598+0000][1][safepoint ] Safepoint "Deoptimize", Time since last: 596586407 ns, Reaching safepoint: 225684 ns, At safepoint: 393129 ns, Total: 618813 ns +[2021-01-28T10:41:31.615+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1012718080 ns, Reaching safepoint: 4660643 ns, At safepoint: 122888 ns, Total: 4783531 ns +[2021-01-28T10:41:32.599+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 982322817 ns, Reaching safepoint: 1128269 ns, At safepoint: 222485 ns, Total: 1350754 ns +[2021-01-28T10:41:32.606+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 5497020 ns, Reaching safepoint: 1060006 ns, At safepoint: 234049 ns, Total: 1294055 ns +[2021-01-28T10:41:32.621+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 196130 ns, Reaching safepoint: 14692380 ns, At safepoint: 139050 ns, Total: 14831430 ns +[2021-01-28T10:41:32.628+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 219973 ns, Reaching safepoint: 6768893 ns, At safepoint: 146800 ns, Total: 6915693 ns +[2021-01-28T10:41:32.631+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 218306 ns, Reaching safepoint: 2460564 ns, At safepoint: 149051 ns, Total: 2609615 ns +[2021-01-28T10:41:32.646+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 373301 ns, Reaching safepoint: 14431494 ns, At safepoint: 146126 ns, Total: 14577620 ns +[2021-01-28T10:41:32.652+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 88233 ns, Reaching safepoint: 5921688 ns, At safepoint: 140176 ns, Total: 6061864 ns +[2021-01-28T10:41:32.660+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 95983 ns, Reaching safepoint: 8554709 ns, At safepoint: 112382 ns, Total: 8667091 ns +[2021-01-28T10:41:32.661+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 170765 ns, Reaching safepoint: 224104 ns, At safepoint: 94710 ns, Total: 318814 ns +[2021-01-28T10:41:32.663+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 132582 ns, Reaching safepoint: 2270203 ns, At safepoint: 104829 ns, Total: 2375032 ns +[2021-01-28T10:41:32.674+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 9420605 ns, Reaching safepoint: 1469928 ns, At safepoint: 73307 ns, Total: 1543235 ns +[2021-01-28T10:41:32.689+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 11894675 ns, Reaching safepoint: 2045069 ns, At safepoint: 210814 ns, Total: 2255883 ns +[2021-01-28T10:41:32.696+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 264194 ns, Reaching safepoint: 6795778 ns, At safepoint: 112304 ns, Total: 6908082 ns +[2021-01-28T10:41:32.710+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 10321742 ns, Reaching safepoint: 3341303 ns, At safepoint: 193323 ns, Total: 3534626 ns +[2021-01-28T10:41:32.717+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 4519513 ns, Reaching safepoint: 2255669 ns, At safepoint: 138079 ns, Total: 2393748 ns +[2021-01-28T10:41:32.727+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 5719811 ns, Reaching safepoint: 4136836 ns, At safepoint: 202767 ns, Total: 4339603 ns +[2021-01-28T10:41:32.729+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 166127 ns, Reaching safepoint: 2491539 ns, At safepoint: 147396 ns, Total: 2638935 ns +[2021-01-28T10:41:32.743+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 10843998 ns, Reaching safepoint: 2704662 ns, At safepoint: 250162 ns, Total: 2954824 ns +[2021-01-28T10:41:32.761+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 17415089 ns, Reaching safepoint: 179431 ns, At safepoint: 160380 ns, Total: 339811 ns +[2021-01-28T10:41:32.787+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 13800887 ns, Reaching safepoint: 11719809 ns, At safepoint: 165457 ns, Total: 11885266 ns +[2021-01-28T10:41:32.844+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 37412945 ns, Reaching safepoint: 14679341 ns, At safepoint: 5595984 ns, Total: 20275325 ns +[2021-01-28T10:41:32.848+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1950392 ns, Reaching safepoint: 2144400 ns, At safepoint: 79674 ns, Total: 2224074 ns +[2021-01-28T10:41:32.867+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 10024232 ns, Reaching safepoint: 8143987 ns, At safepoint: 191329 ns, Total: 8335316 ns +[2021-01-28T10:41:32.877+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 9436011 ns, Reaching safepoint: 551156 ns, At safepoint: 50096 ns, Total: 601252 ns +[2021-01-28T10:41:32.896+0000][1][safepoint ] Safepoint "Deoptimize", Time since last: 7008056 ns, Reaching safepoint: 11442572 ns, At safepoint: 526282 ns, Total: 11968854 ns +[2021-01-28T10:41:32.900+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 719603 ns, Reaching safepoint: 2898001 ns, At safepoint: 100799 ns, Total: 2998800 ns +[2021-01-28T10:41:32.914+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 12633023 ns, Reaching safepoint: 1871087 ns, At safepoint: 84093 ns, Total: 1955180 ns +[2021-01-28T10:41:32.927+0000][1][safepoint ] Safepoint "BulkRevokeBias", Time since last: 7252407 ns, Reaching safepoint: 5064731 ns, At safepoint: 215564 ns, Total: 5280295 ns +[2021-01-28T10:41:33.518+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 591295669 ns, Reaching safepoint: 236323 ns, At safepoint: 202764 ns, Total: 439087 ns +[2021-01-28T10:41:34.521+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000793997 ns, Reaching safepoint: 1957816 ns, At safepoint: 132219 ns, Total: 2090035 ns +[2021-01-28T10:41:35.114+0000][1][safepoint ] Safepoint "Deoptimize", Time since last: 592002667 ns, Reaching safepoint: 146002 ns, At safepoint: 480222 ns, Total: 626224 ns +[2021-01-28T10:41:35.186+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 71439197 ns, Reaching safepoint: 144182 ns, At safepoint: 28399 ns, Total: 172581 ns +[2021-01-28T10:41:35.192+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 6810904 ns, Reaching safepoint: 64289 ns, At safepoint: 25450 ns, Total: 89739 ns +[2021-01-28T10:41:35.201+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 8707626 ns, Reaching safepoint: 166371 ns, At safepoint: 64902 ns, Total: 231273 ns +[2021-01-28T10:41:35.209+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 7854554 ns, Reaching safepoint: 163823 ns, At safepoint: 32795 ns, Total: 196618 ns +[2021-01-28T10:41:35.220+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 10336707 ns, Reaching safepoint: 452824 ns, At safepoint: 36498 ns, Total: 489322 ns +[2021-01-28T10:41:35.226+0000][1][safepoint ] Safepoint "BulkRevokeBias", Time since last: 3094572 ns, Reaching safepoint: 2778069 ns, At safepoint: 116092 ns, Total: 2894161 ns +[2021-01-28T10:41:35.254+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 13877220 ns, Reaching safepoint: 14169469 ns, At safepoint: 70621 ns, Total: 14240090 ns +[2021-01-28T10:41:35.257+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2802372 ns, Reaching safepoint: 152284 ns, At safepoint: 45238 ns, Total: 197522 ns +[2021-01-28T10:41:35.261+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 3769994 ns, Reaching safepoint: 160811 ns, At safepoint: 45445 ns, Total: 206256 ns +[2021-01-28T10:41:35.269+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 7853299 ns, Reaching safepoint: 135964 ns, At safepoint: 26707 ns, Total: 162671 ns +[2021-01-28T10:41:35.280+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 8560781 ns, Reaching safepoint: 2402658 ns, At safepoint: 74400 ns, Total: 2477058 ns +[2021-01-28T10:41:35.282+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 978532 ns, Reaching safepoint: 996306 ns, At safepoint: 68042 ns, Total: 1064348 ns +[2021-01-28T10:41:35.286+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2681786 ns, Reaching safepoint: 495033 ns, At safepoint: 61657 ns, Total: 556690 ns +[2021-01-28T10:41:35.287+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1374091 ns, Reaching safepoint: 97100 ns, At safepoint: 50404 ns, Total: 147504 ns +[2021-01-28T10:41:35.295+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 4091362 ns, Reaching safepoint: 3050574 ns, At safepoint: 276680 ns, Total: 3327254 ns +[2021-01-28T10:41:35.313+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 15577682 ns, Reaching safepoint: 3031430 ns, At safepoint: 86380 ns, Total: 3117810 ns +[2021-01-28T10:41:35.319+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 943770 ns, Reaching safepoint: 5087776 ns, At safepoint: 84441 ns, Total: 5172217 ns +[2021-01-28T10:41:35.321+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 885639 ns, Reaching safepoint: 922362 ns, At safepoint: 69521 ns, Total: 991883 ns +[2021-01-28T10:41:35.325+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 3882067 ns, Reaching safepoint: 93422 ns, At safepoint: 13002 ns, Total: 106424 ns +[2021-01-28T10:41:35.329+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 3942998 ns, Reaching safepoint: 153735 ns, At safepoint: 46652 ns, Total: 200387 ns +[2021-01-28T10:41:35.334+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1109184 ns, Reaching safepoint: 3748365 ns, At safepoint: 81075 ns, Total: 3829440 ns +[2021-01-28T10:41:35.340+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2985201 ns, Reaching safepoint: 2235193 ns, At safepoint: 85304 ns, Total: 2320497 ns +[2021-01-28T10:41:35.343+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2390305 ns, Reaching safepoint: 561048 ns, At safepoint: 16989 ns, Total: 578037 ns +[2021-01-28T10:41:35.350+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2478746 ns, Reaching safepoint: 4888790 ns, At safepoint: 24921 ns, Total: 4913711 ns +[2021-01-28T10:41:35.351+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 657641 ns, Reaching safepoint: 245666 ns, At safepoint: 13509 ns, Total: 259175 ns +[2021-01-28T10:41:35.361+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 5608655 ns, Reaching safepoint: 4481420 ns, At safepoint: 101323 ns, Total: 4582743 ns +[2021-01-28T10:41:35.368+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2598009 ns, Reaching safepoint: 4549882 ns, At safepoint: 58410 ns, Total: 4608292 ns +[2021-01-28T10:41:35.370+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 903792 ns, Reaching safepoint: 468366 ns, At safepoint: 14968 ns, Total: 483334 ns +[2021-01-28T10:41:35.374+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2723541 ns, Reaching safepoint: 1016189 ns, At safepoint: 58185 ns, Total: 1074374 ns +[2021-01-28T10:41:35.378+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2758127 ns, Reaching safepoint: 1445595 ns, At safepoint: 48826 ns, Total: 1494421 ns +[2021-01-28T10:41:35.385+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2434906 ns, Reaching safepoint: 4490729 ns, At safepoint: 35015 ns, Total: 4525744 ns +[2021-01-28T10:41:35.388+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1961136 ns, Reaching safepoint: 1277485 ns, At safepoint: 26886 ns, Total: 1304371 ns +[2021-01-28T10:41:35.392+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1156761 ns, Reaching safepoint: 2490390 ns, At safepoint: 26073 ns, Total: 2516463 ns +[2021-01-28T10:41:35.398+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2697026 ns, Reaching safepoint: 3436338 ns, At safepoint: 59277 ns, Total: 3495615 ns +[2021-01-28T10:41:35.403+0000][1][safepoint ] Safepoint "BulkRevokeBias", Time since last: 2426849 ns, Reaching safepoint: 2322683 ns, At safepoint: 129306 ns, Total: 2451989 ns +[2021-01-28T10:41:35.409+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 4451114 ns, Reaching safepoint: 1206950 ns, At safepoint: 120769 ns, Total: 1327719 ns +[2021-01-28T10:41:35.409+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 512163 ns, Reaching safepoint: 372741 ns, At safepoint: 58264 ns, Total: 431005 ns +[2021-01-28T10:41:35.417+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 832066 ns, Reaching safepoint: 6139944 ns, At safepoint: 74196 ns, Total: 6214140 ns +[2021-01-28T10:41:35.422+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2799411 ns, Reaching safepoint: 2526997 ns, At safepoint: 38128 ns, Total: 2565125 ns +[2021-01-28T10:41:35.425+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 422792 ns, Reaching safepoint: 2860964 ns, At safepoint: 39058 ns, Total: 2900022 ns +[2021-01-28T10:41:35.534+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 102838517 ns, Reaching safepoint: 5668141 ns, At safepoint: 117197 ns, Total: 5785338 ns +[2021-01-28T10:41:35.576+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 39869353 ns, Reaching safepoint: 2298335 ns, At safepoint: 31556 ns, Total: 2329891 ns +[2021-01-28T10:41:35.579+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1371390 ns, Reaching safepoint: 2022937 ns, At safepoint: 40663 ns, Total: 2063600 ns +[2021-01-28T10:41:35.583+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2833995 ns, Reaching safepoint: 395358 ns, At safepoint: 40623 ns, Total: 435981 ns +[2021-01-28T10:41:35.587+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2579532 ns, Reaching safepoint: 1284179 ns, At safepoint: 33756 ns, Total: 1317935 ns +[2021-01-28T10:41:35.594+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 4817134 ns, Reaching safepoint: 2508276 ns, At safepoint: 77289 ns, Total: 2585565 ns +[2021-01-28T10:41:35.596+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 361093 ns, Reaching safepoint: 1490208 ns, At safepoint: 26263 ns, Total: 1516471 ns +[2021-01-28T10:41:35.613+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1404090 ns, Reaching safepoint: 16067579 ns, At safepoint: 37872 ns, Total: 16105451 ns +[2021-01-28T10:41:35.619+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2856233 ns, Reaching safepoint: 2852415 ns, At safepoint: 42252 ns, Total: 2894667 ns +[2021-01-28T10:41:35.663+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 44133593 ns, Reaching safepoint: 136174 ns, At safepoint: 29200 ns, Total: 165374 ns +[2021-01-28T10:41:35.670+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2831227 ns, Reaching safepoint: 3970007 ns, At safepoint: 42165 ns, Total: 4012172 ns +[2021-01-28T10:41:35.675+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2829475 ns, Reaching safepoint: 1675961 ns, At safepoint: 34960 ns, Total: 1710921 ns +[2021-01-28T10:41:35.678+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1802386 ns, Reaching safepoint: 831730 ns, At safepoint: 30976 ns, Total: 862706 ns +[2021-01-28T10:41:35.682+0000][1][safepoint ] Safepoint "Deoptimize", Time since last: 1950939 ns, Reaching safepoint: 1937649 ns, At safepoint: 548910 ns, Total: 2486559 ns +[2021-01-28T10:41:35.688+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 4345696 ns, Reaching safepoint: 1393045 ns, At safepoint: 34703 ns, Total: 1427748 ns +[2021-01-28T10:41:35.691+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 515362 ns, Reaching safepoint: 2877996 ns, At safepoint: 45445 ns, Total: 2923441 ns +[2021-01-28T10:41:35.697+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 3143051 ns, Reaching safepoint: 2992559 ns, At safepoint: 40785 ns, Total: 3033344 ns +[2021-01-28T10:41:35.705+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 3950750 ns, Reaching safepoint: 3996308 ns, At safepoint: 39168 ns, Total: 4035476 ns +[2021-01-28T10:41:35.841+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 130808582 ns, Reaching safepoint: 4333849 ns, At safepoint: 57194 ns, Total: 4391043 ns +[2021-01-28T10:41:35.847+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1439528 ns, Reaching safepoint: 5221097 ns, At safepoint: 96639 ns, Total: 5317736 ns +[2021-01-28T10:41:35.853+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1669581 ns, Reaching safepoint: 4364299 ns, At safepoint: 87051 ns, Total: 4451350 ns +[2021-01-28T10:41:35.859+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1705059 ns, Reaching safepoint: 4155167 ns, At safepoint: 120134 ns, Total: 4275301 ns +[2021-01-28T10:41:35.898+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1587858 ns, Reaching safepoint: 36785280 ns, At safepoint: 115571 ns, Total: 36900851 ns +[2021-01-28T10:41:35.901+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 124120 ns, Reaching safepoint: 2545251 ns, At safepoint: 52494 ns, Total: 2597745 ns +[2021-01-28T10:41:35.902+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 284799 ns, Reaching safepoint: 903126 ns, At safepoint: 50194 ns, Total: 953320 ns +[2021-01-28T10:41:35.912+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1217120 ns, Reaching safepoint: 8922211 ns, At safepoint: 155389 ns, Total: 9077600 ns +[2021-01-28T10:41:35.929+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 10028790 ns, Reaching safepoint: 6771668 ns, At safepoint: 83948 ns, Total: 6855616 ns +[2021-01-28T10:41:35.939+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 3185142 ns, Reaching safepoint: 7191435 ns, At safepoint: 82199 ns, Total: 7273634 ns +[2021-01-28T10:41:35.946+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 6308865 ns, Reaching safepoint: 108383 ns, At safepoint: 19730 ns, Total: 128113 ns +[2021-01-28T10:41:35.959+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 12418564 ns, Reaching safepoint: 165186 ns, At safepoint: 49566 ns, Total: 214752 ns +[2021-01-28T10:41:35.966+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 7764218 ns, Reaching safepoint: 95550 ns, At safepoint: 17315 ns, Total: 112865 ns +[2021-01-28T10:41:35.967+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 765189 ns, Reaching safepoint: 82299 ns, At safepoint: 14092 ns, Total: 96391 ns +[2021-01-28T10:41:35.968+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 622678 ns, Reaching safepoint: 79101 ns, At safepoint: 21915 ns, Total: 101016 ns +[2021-01-28T10:41:35.987+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 18362289 ns, Reaching safepoint: 945817 ns, At safepoint: 55918 ns, Total: 1001735 ns +[2021-01-28T10:41:36.000+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 6579301 ns, Reaching safepoint: 6198136 ns, At safepoint: 54431 ns, Total: 6252567 ns +[2021-01-28T10:41:36.003+0000][1][safepoint ] Safepoint "BulkRevokeBias", Time since last: 775821 ns, Reaching safepoint: 1143922 ns, At safepoint: 1261916 ns, Total: 2405838 ns +[2021-01-28T10:41:36.046+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 20666885 ns, Reaching safepoint: 21831227 ns, At safepoint: 51838 ns, Total: 21883065 ns +[2021-01-28T10:41:36.059+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1690395 ns, Reaching safepoint: 10804747 ns, At safepoint: 71982 ns, Total: 10876729 ns +[2021-01-28T10:41:36.065+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 378525 ns, Reaching safepoint: 6459256 ns, At safepoint: 104366 ns, Total: 6563622 ns +[2021-01-28T10:41:36.088+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 5884452 ns, Reaching safepoint: 16808724 ns, At safepoint: 88643 ns, Total: 16897367 ns +[2021-01-28T10:41:36.097+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 7302620 ns, Reaching safepoint: 982422 ns, At safepoint: 66459 ns, Total: 1048881 ns +[2021-01-28T10:41:36.122+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2145095 ns, Reaching safepoint: 22797296 ns, At safepoint: 79030 ns, Total: 22876326 ns +[2021-01-28T10:41:36.127+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1782729 ns, Reaching safepoint: 3068394 ns, At safepoint: 124620 ns, Total: 3193014 ns +[2021-01-28T10:41:36.129+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 165056 ns, Reaching safepoint: 2052176 ns, At safepoint: 74192 ns, Total: 2126368 ns +[2021-01-28T10:41:36.134+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 333835 ns, Reaching safepoint: 5191591 ns, At safepoint: 79331 ns, Total: 5270922 ns +[2021-01-28T10:41:36.147+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 705613 ns, Reaching safepoint: 11844229 ns, At safepoint: 119715 ns, Total: 11963944 ns +[2021-01-28T10:41:36.155+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 5133562 ns, Reaching safepoint: 3008828 ns, At safepoint: 42378 ns, Total: 3051206 ns +[2021-01-28T10:41:36.157+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 696717 ns, Reaching safepoint: 905448 ns, At safepoint: 60817 ns, Total: 966265 ns +[2021-01-28T10:41:36.172+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 13338186 ns, Reaching safepoint: 1501327 ns, At safepoint: 59084 ns, Total: 1560411 ns +[2021-01-28T10:41:36.172+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 235362 ns, Reaching safepoint: 88371 ns, At safepoint: 13814 ns, Total: 102185 ns +[2021-01-28T10:41:36.178+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 5110605 ns, Reaching safepoint: 203880 ns, At safepoint: 56937 ns, Total: 260817 ns +[2021-01-28T10:41:36.179+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1110860 ns, Reaching safepoint: 234058 ns, At safepoint: 46338 ns, Total: 280396 ns +[2021-01-28T10:41:36.188+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 5769578 ns, Reaching safepoint: 2709515 ns, At safepoint: 77892 ns, Total: 2787407 ns +[2021-01-28T10:41:36.193+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1701990 ns, Reaching safepoint: 3161985 ns, At safepoint: 110358 ns, Total: 3272343 ns +[2021-01-28T10:41:36.195+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 132213 ns, Reaching safepoint: 1795916 ns, At safepoint: 83971 ns, Total: 1879887 ns +[2021-01-28T10:41:36.198+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 85036 ns, Reaching safepoint: 3033278 ns, At safepoint: 75689 ns, Total: 3108967 ns +[2021-01-28T10:41:36.208+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2044979 ns, Reaching safepoint: 7810909 ns, At safepoint: 134414 ns, Total: 7945323 ns +[2021-01-28T10:41:36.217+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 788417 ns, Reaching safepoint: 8469903 ns, At safepoint: 232976 ns, Total: 8702879 ns +[2021-01-28T10:41:36.222+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 205593 ns, Reaching safepoint: 4456257 ns, At safepoint: 301989 ns, Total: 4758246 ns +[2021-01-28T10:41:36.226+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 123082 ns, Reaching safepoint: 3122679 ns, At safepoint: 125887 ns, Total: 3248566 ns +[2021-01-28T10:41:36.237+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 10578748 ns, Reaching safepoint: 483606 ns, At safepoint: 69189 ns, Total: 552795 ns +[2021-01-28T10:41:36.242+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2842497 ns, Reaching safepoint: 2424431 ns, At safepoint: 20593 ns, Total: 2445024 ns +[2021-01-28T10:41:36.244+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 418915 ns, Reaching safepoint: 2066219 ns, At safepoint: 20346 ns, Total: 2086565 ns +[2021-01-28T10:41:36.246+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 108969 ns, Reaching safepoint: 1392338 ns, At safepoint: 19006 ns, Total: 1411344 ns +[2021-01-28T10:41:36.247+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 591589 ns, Reaching safepoint: 416597 ns, At safepoint: 22371 ns, Total: 438968 ns +[2021-01-28T10:41:36.248+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 231548 ns, Reaching safepoint: 931905 ns, At safepoint: 87938 ns, Total: 1019843 ns +[2021-01-28T10:41:36.256+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 4700997 ns, Reaching safepoint: 3293948 ns, At safepoint: 29749 ns, Total: 3323697 ns +[2021-01-28T10:41:36.267+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 6470048 ns, Reaching safepoint: 3768155 ns, At safepoint: 20506 ns, Total: 3788661 ns +[2021-01-28T10:41:36.269+0000][1][safepoint ] Safepoint "BulkRevokeBias", Time since last: 412296 ns, Reaching safepoint: 1715724 ns, At safepoint: 411194 ns, Total: 2126918 ns +[2021-01-28T10:41:36.285+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 899535 ns, Reaching safepoint: 14688093 ns, At safepoint: 52234 ns, Total: 14740327 ns +[2021-01-28T10:41:36.289+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 972986 ns, Reaching safepoint: 2720537 ns, At safepoint: 58696 ns, Total: 2779233 ns +[2021-01-28T10:41:36.299+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 858261 ns, Reaching safepoint: 9360988 ns, At safepoint: 59448 ns, Total: 9420436 ns +[2021-01-28T10:41:36.306+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 424175 ns, Reaching safepoint: 6433215 ns, At safepoint: 66289 ns, Total: 6499504 ns +[2021-01-28T10:41:36.309+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 694129 ns, Reaching safepoint: 2940484 ns, At safepoint: 102468 ns, Total: 3042952 ns +[2021-01-28T10:41:36.319+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2869384 ns, Reaching safepoint: 6821900 ns, At safepoint: 256520 ns, Total: 7078420 ns +[2021-01-28T10:41:36.329+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 642902 ns, Reaching safepoint: 8994505 ns, At safepoint: 88368 ns, Total: 9082873 ns +[2021-01-28T10:41:36.337+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 5651661 ns, Reaching safepoint: 2633073 ns, At safepoint: 85613 ns, Total: 2718686 ns +[2021-01-28T10:41:36.341+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 193036 ns, Reaching safepoint: 2738992 ns, At safepoint: 97468 ns, Total: 2836460 ns +[2021-01-28T10:41:36.352+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 6658552 ns, Reaching safepoint: 4298339 ns, At safepoint: 53589 ns, Total: 4351928 ns +[2021-01-28T10:41:36.354+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2396235 ns, Reaching safepoint: 390853 ns, At safepoint: 28295 ns, Total: 419148 ns +[2021-01-28T10:41:36.358+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 3403245 ns, Reaching safepoint: 198268 ns, At safepoint: 32005 ns, Total: 230273 ns +[2021-01-28T10:41:36.360+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1298242 ns, Reaching safepoint: 680841 ns, At safepoint: 109236 ns, Total: 790077 ns +[2021-01-28T10:41:36.364+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 568908 ns, Reaching safepoint: 3360204 ns, At safepoint: 88003 ns, Total: 3448207 ns +[2021-01-28T10:41:36.371+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2921717 ns, Reaching safepoint: 3567676 ns, At safepoint: 53087 ns, Total: 3620763 ns +[2021-01-28T10:41:36.371+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 480954 ns, Reaching safepoint: 209721 ns, At safepoint: 66291 ns, Total: 276012 ns +[2021-01-28T10:41:36.858+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 485293937 ns, Reaching safepoint: 1148324 ns, At safepoint: 64701 ns, Total: 1213025 ns +[2021-01-28T10:41:36.903+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 35377981 ns, Reaching safepoint: 5901867 ns, At safepoint: 3377574 ns, Total: 9279441 ns +[2021-01-28T10:41:36.911+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 309570 ns, Reaching safepoint: 7554351 ns, At safepoint: 109833 ns, Total: 7664184 ns +[2021-01-28T10:41:36.922+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2023486 ns, Reaching safepoint: 8897060 ns, At safepoint: 121905 ns, Total: 9018965 ns +[2021-01-28T10:41:36.926+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 224231 ns, Reaching safepoint: 3793328 ns, At safepoint: 118945 ns, Total: 3912273 ns +[2021-01-28T10:41:36.930+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1247052 ns, Reaching safepoint: 3446839 ns, At safepoint: 68106 ns, Total: 3514945 ns +[2021-01-28T10:41:36.936+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 165617 ns, Reaching safepoint: 5038572 ns, At safepoint: 88274 ns, Total: 5126846 ns +[2021-01-28T10:41:36.953+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 745253 ns, Reaching safepoint: 16828887 ns, At safepoint: 88164 ns, Total: 16917051 ns +[2021-01-28T10:41:36.975+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 363547 ns, Reaching safepoint: 20651988 ns, At safepoint: 113230 ns, Total: 20765218 ns +[2021-01-28T10:41:36.979+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1228355 ns, Reaching safepoint: 2644246 ns, At safepoint: 79445 ns, Total: 2723691 ns +[2021-01-28T10:41:36.988+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1430841 ns, Reaching safepoint: 7484163 ns, At safepoint: 100382 ns, Total: 7584545 ns +[2021-01-28T10:41:36.991+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2783296 ns, Reaching safepoint: 734810 ns, At safepoint: 98081 ns, Total: 832891 ns +[2021-01-28T10:41:37.010+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 8210316 ns, Reaching safepoint: 10240707 ns, At safepoint: 120104 ns, Total: 10360811 ns +[2021-01-28T10:41:37.019+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 4275532 ns, Reaching safepoint: 5190515 ns, At safepoint: 77793 ns, Total: 5268308 ns +[2021-01-28T10:41:37.859+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 839765851 ns, Reaching safepoint: 348900 ns, At safepoint: 124740 ns, Total: 473640 ns +[2021-01-28T10:41:37.860+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 326379 ns, Reaching safepoint: 346847 ns, At safepoint: 93296 ns, Total: 440143 ns +[2021-01-28T10:41:37.861+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 263399 ns, Reaching safepoint: 489117 ns, At safepoint: 394925 ns, Total: 884042 ns +[2021-01-28T10:41:37.863+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 391786 ns, Reaching safepoint: 612930 ns, At safepoint: 422557 ns, Total: 1035487 ns +[2021-01-28T10:41:37.864+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 62751 ns, Reaching safepoint: 280204 ns, At safepoint: 357503 ns, Total: 637707 ns +[2021-01-28T10:41:37.864+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 125856 ns, Reaching safepoint: 281880 ns, At safepoint: 44534 ns, Total: 326414 ns +[2021-01-28T10:41:37.869+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 641607 ns, Reaching safepoint: 3690533 ns, At safepoint: 295868 ns, Total: 3986401 ns +[2021-01-28T10:41:37.872+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 966141 ns, Reaching safepoint: 2757670 ns, At safepoint: 143176 ns, Total: 2900846 ns +[2021-01-28T10:41:37.876+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 497566 ns, Reaching safepoint: 2554099 ns, At safepoint: 52828 ns, Total: 2606927 ns +[2021-01-28T10:41:37.877+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1266314 ns, Reaching safepoint: 162436 ns, At safepoint: 11342 ns, Total: 173778 ns +[2021-01-28T10:41:38.110+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 232011766 ns, Reaching safepoint: 388505 ns, At safepoint: 101571 ns, Total: 490076 ns +[2021-01-28T10:41:38.112+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1874733 ns, Reaching safepoint: 346660 ns, At safepoint: 73131 ns, Total: 419791 ns +[2021-01-28T10:41:38.116+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 3252029 ns, Reaching safepoint: 428586 ns, At safepoint: 77400 ns, Total: 505986 ns +[2021-01-28T10:41:38.118+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1237643 ns, Reaching safepoint: 1604728 ns, At safepoint: 57271 ns, Total: 1661999 ns +[2021-01-28T10:41:38.121+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 99296 ns, Reaching safepoint: 2855142 ns, At safepoint: 62681 ns, Total: 2917823 ns +[2021-01-28T10:41:38.125+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1829215 ns, Reaching safepoint: 1262665 ns, At safepoint: 53422 ns, Total: 1316087 ns +[2021-01-28T10:41:38.125+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 83301 ns, Reaching safepoint: 516456 ns, At safepoint: 69943 ns, Total: 586399 ns +[2021-01-28T10:41:38.199+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 73590856 ns, Reaching safepoint: 309884 ns, At safepoint: 81930 ns, Total: 391814 ns +[2021-01-28T10:41:38.202+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 85582 ns, Reaching safepoint: 2886078 ns, At safepoint: 86785 ns, Total: 2972863 ns +[2021-01-28T10:41:38.260+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 57536317 ns, Reaching safepoint: 126707 ns, At safepoint: 18336 ns, Total: 145043 ns +[2021-01-28T10:41:38.262+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1794914 ns, Reaching safepoint: 114843 ns, At safepoint: 17804 ns, Total: 132647 ns +[2021-01-28T10:41:38.268+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 6197906 ns, Reaching safepoint: 133728 ns, At safepoint: 14417 ns, Total: 148145 ns +[2021-01-28T10:41:38.275+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2805510 ns, Reaching safepoint: 4134633 ns, At safepoint: 48940 ns, Total: 4183573 ns +[2021-01-28T10:41:38.276+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 299539 ns, Reaching safepoint: 622630 ns, At safepoint: 55352 ns, Total: 677982 ns +[2021-01-28T10:41:38.282+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 4181766 ns, Reaching safepoint: 1854875 ns, At safepoint: 79442 ns, Total: 1934317 ns +[2021-01-28T10:41:38.397+0000][1][safepoint ] Safepoint "Deoptimize", Time since last: 113011056 ns, Reaching safepoint: 1000866 ns, At safepoint: 644811 ns, Total: 1645677 ns +[2021-01-28T10:41:38.415+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 14648080 ns, Reaching safepoint: 2842891 ns, At safepoint: 23935 ns, Total: 2866826 ns +[2021-01-28T10:41:38.420+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 182349 ns, Reaching safepoint: 4716389 ns, At safepoint: 68942 ns, Total: 4785331 ns +[2021-01-28T10:41:38.424+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 147513 ns, Reaching safepoint: 3799686 ns, At safepoint: 52207 ns, Total: 3851893 ns +[2021-01-28T10:41:38.427+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 596652 ns, Reaching safepoint: 3231031 ns, At safepoint: 51430 ns, Total: 3282461 ns +[2021-01-28T10:41:38.430+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 99218 ns, Reaching safepoint: 2938184 ns, At safepoint: 56246 ns, Total: 2994430 ns +[2021-01-28T10:41:38.434+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 562417 ns, Reaching safepoint: 2444939 ns, At safepoint: 51114 ns, Total: 2496053 ns +[2021-01-28T10:41:38.435+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 587502 ns, Reaching safepoint: 465827 ns, At safepoint: 56021 ns, Total: 521848 ns +[2021-01-28T10:41:38.442+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 3841733 ns, Reaching safepoint: 3960397 ns, At safepoint: 25602 ns, Total: 3985999 ns +[2021-01-28T10:41:38.446+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 218182 ns, Reaching safepoint: 3233315 ns, At safepoint: 100941 ns, Total: 3334256 ns +[2021-01-28T10:41:38.452+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 982348 ns, Reaching safepoint: 4745734 ns, At safepoint: 28511 ns, Total: 4774245 ns +[2021-01-28T10:41:38.452+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 362297 ns, Reaching safepoint: 268958 ns, At safepoint: 18386 ns, Total: 287344 ns +[2021-01-28T10:41:38.456+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 943554 ns, Reaching safepoint: 3036386 ns, At safepoint: 28895 ns, Total: 3065281 ns +[2021-01-28T10:41:38.461+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2060271 ns, Reaching safepoint: 2925461 ns, At safepoint: 27129 ns, Total: 2952590 ns +[2021-01-28T10:41:38.468+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2643601 ns, Reaching safepoint: 3409385 ns, At safepoint: 35055 ns, Total: 3444440 ns +[2021-01-28T10:41:38.474+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 3003596 ns, Reaching safepoint: 3732691 ns, At safepoint: 38216 ns, Total: 3770907 ns +[2021-01-28T10:41:38.494+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 17298888 ns, Reaching safepoint: 2809511 ns, At safepoint: 55977 ns, Total: 2865488 ns +[2021-01-28T10:41:38.498+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1962165 ns, Reaching safepoint: 1370206 ns, At safepoint: 60901 ns, Total: 1431107 ns +[2021-01-28T10:41:38.499+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 964987 ns, Reaching safepoint: 328365 ns, At safepoint: 47367 ns, Total: 375732 ns +[2021-01-28T10:41:38.500+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 147569 ns, Reaching safepoint: 944646 ns, At safepoint: 79924 ns, Total: 1024570 ns +[2021-01-28T10:41:38.507+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2939421 ns, Reaching safepoint: 3132924 ns, At safepoint: 119271 ns, Total: 3252195 ns +[2021-01-28T10:41:38.508+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 293773 ns, Reaching safepoint: 1011314 ns, At safepoint: 138095 ns, Total: 1149409 ns +[2021-01-28T10:41:38.514+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1779355 ns, Reaching safepoint: 3611665 ns, At safepoint: 80022 ns, Total: 3691687 ns +[2021-01-28T10:41:38.519+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 919973 ns, Reaching safepoint: 4156578 ns, At safepoint: 107595 ns, Total: 4264173 ns +[2021-01-28T10:41:38.521+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1391684 ns, Reaching safepoint: 1104080 ns, At safepoint: 113228 ns, Total: 1217308 ns +[2021-01-28T10:41:38.525+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 343861 ns, Reaching safepoint: 3491475 ns, At safepoint: 155178 ns, Total: 3646653 ns +[2021-01-28T10:41:38.529+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 236551 ns, Reaching safepoint: 3053241 ns, At safepoint: 125579 ns, Total: 3178820 ns +[2021-01-28T10:41:38.533+0000][1][safepoint ] Safepoint "BulkRevokeBias", Time since last: 523742 ns, Reaching safepoint: 3006624 ns, At safepoint: 630698 ns, Total: 3637322 ns +[2021-01-28T10:41:38.536+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 409089 ns, Reaching safepoint: 3052409 ns, At safepoint: 106329 ns, Total: 3158738 ns +[2021-01-28T10:41:38.538+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 293124 ns, Reaching safepoint: 1543056 ns, At safepoint: 84622 ns, Total: 1627678 ns +[2021-01-28T10:41:38.541+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1325976 ns, Reaching safepoint: 897268 ns, At safepoint: 332520 ns, Total: 1229788 ns +[2021-01-28T10:41:38.543+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 405339 ns, Reaching safepoint: 1430273 ns, At safepoint: 110382 ns, Total: 1540655 ns +[2021-01-28T10:41:38.554+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2950403 ns, Reaching safepoint: 8492274 ns, At safepoint: 129757 ns, Total: 8622031 ns +[2021-01-28T10:41:38.559+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 282437 ns, Reaching safepoint: 4395890 ns, At safepoint: 157456 ns, Total: 4553346 ns +[2021-01-28T10:41:38.562+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 370331 ns, Reaching safepoint: 2404937 ns, At safepoint: 160190 ns, Total: 2565127 ns +[2021-01-28T10:41:38.568+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1759275 ns, Reaching safepoint: 3573527 ns, At safepoint: 82613 ns, Total: 3656140 ns +[2021-01-28T10:41:38.569+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 278459 ns, Reaching safepoint: 640741 ns, At safepoint: 79352 ns, Total: 720093 ns +[2021-01-28T10:41:38.572+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 173967 ns, Reaching safepoint: 3511821 ns, At safepoint: 109873 ns, Total: 3621694 ns +[2021-01-28T10:41:38.575+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 225430 ns, Reaching safepoint: 2377429 ns, At safepoint: 130817 ns, Total: 2508246 ns +[2021-01-28T10:41:38.576+0000][1][safepoint ] Safepoint "BulkRevokeBias", Time since last: 230000 ns, Reaching safepoint: 346174 ns, At safepoint: 359387 ns, Total: 705561 ns +[2021-01-28T10:41:38.675+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 89490787 ns, Reaching safepoint: 9199976 ns, At safepoint: 127789 ns, Total: 9327765 ns +[2021-01-28T10:41:38.680+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 211247 ns, Reaching safepoint: 5156760 ns, At safepoint: 111705 ns, Total: 5268465 ns +[2021-01-28T10:41:38.683+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 666523 ns, Reaching safepoint: 1722526 ns, At safepoint: 140072 ns, Total: 1862598 ns +[2021-01-28T10:41:38.685+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 155842 ns, Reaching safepoint: 1451503 ns, At safepoint: 108045 ns, Total: 1559548 ns +[2021-01-28T10:41:38.692+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2144402 ns, Reaching safepoint: 4905807 ns, At safepoint: 156034 ns, Total: 5061841 ns +[2021-01-28T10:41:38.695+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 454531 ns, Reaching safepoint: 2982514 ns, At safepoint: 188302 ns, Total: 3170816 ns +[2021-01-28T10:41:38.697+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 211073 ns, Reaching safepoint: 1524097 ns, At safepoint: 131136 ns, Total: 1655233 ns +[2021-01-28T10:41:38.700+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 193117 ns, Reaching safepoint: 2799680 ns, At safepoint: 128319 ns, Total: 2927999 ns +[2021-01-28T10:41:38.702+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 350866 ns, Reaching safepoint: 872327 ns, At safepoint: 75947 ns, Total: 948274 ns +[2021-01-28T10:41:38.703+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 89873 ns, Reaching safepoint: 1242060 ns, At safepoint: 114489 ns, Total: 1356549 ns +[2021-01-28T10:41:38.726+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 22746152 ns, Reaching safepoint: 524003 ns, At safepoint: 20932 ns, Total: 544935 ns +[2021-01-28T10:41:38.728+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 431251 ns, Reaching safepoint: 1046685 ns, At safepoint: 67314 ns, Total: 1113999 ns +[2021-01-28T10:41:38.775+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 44590976 ns, Reaching safepoint: 2165661 ns, At safepoint: 24111 ns, Total: 2189772 ns +[2021-01-28T10:41:38.884+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 104818039 ns, Reaching safepoint: 2823532 ns, At safepoint: 1314437 ns, Total: 4137969 ns +[2021-01-28T10:41:38.904+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 11479339 ns, Reaching safepoint: 7635972 ns, At safepoint: 710480 ns, Total: 8346452 ns +[2021-01-28T10:41:38.930+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 14396973 ns, Reaching safepoint: 11454373 ns, At safepoint: 93312 ns, Total: 11547685 ns +[2021-01-28T10:41:38.944+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 7002895 ns, Reaching safepoint: 6864060 ns, At safepoint: 117883 ns, Total: 6981943 ns +[2021-01-28T10:41:38.964+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 14723232 ns, Reaching safepoint: 5322759 ns, At safepoint: 109903 ns, Total: 5432662 ns +[2021-01-28T10:41:38.971+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2708666 ns, Reaching safepoint: 4126726 ns, At safepoint: 105059 ns, Total: 4231785 ns +[2021-01-28T10:41:38.986+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 9636786 ns, Reaching safepoint: 5152950 ns, At safepoint: 125482 ns, Total: 5278432 ns +[2021-01-28T10:41:38.988+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2082184 ns, Reaching safepoint: 837101 ns, At safepoint: 57156 ns, Total: 894257 ns +[2021-01-28T10:41:38.990+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 427108 ns, Reaching safepoint: 742286 ns, At safepoint: 63340 ns, Total: 805626 ns +[2021-01-28T10:41:38.997+0000][1][safepoint ] Safepoint "BulkRevokeBias", Time since last: 466619 ns, Reaching safepoint: 6319706 ns, At safepoint: 407925 ns, Total: 6727631 ns +[2021-01-28T10:41:39.058+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 58386875 ns, Reaching safepoint: 3088091 ns, At safepoint: 24170 ns, Total: 3112261 ns +[2021-01-28T10:41:39.064+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 4716976 ns, Reaching safepoint: 639757 ns, At safepoint: 20980 ns, Total: 660737 ns +[2021-01-28T10:41:39.083+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 13776304 ns, Reaching safepoint: 4996606 ns, At safepoint: 55276 ns, Total: 5051882 ns +[2021-01-28T10:41:39.128+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 35024854 ns, Reaching safepoint: 10365846 ns, At safepoint: 118505 ns, Total: 10484351 ns +[2021-01-28T10:41:39.192+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 60074122 ns, Reaching safepoint: 4075907 ns, At safepoint: 65825 ns, Total: 4141732 ns +[2021-01-28T10:41:39.220+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 18196061 ns, Reaching safepoint: 9353155 ns, At safepoint: 144182 ns, Total: 9497337 ns +[2021-01-28T10:41:39.351+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 97429688 ns, Reaching safepoint: 33038343 ns, At safepoint: 80340 ns, Total: 33118683 ns +[2021-01-28T10:41:39.376+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1811046 ns, Reaching safepoint: 24017459 ns, At safepoint: 30986 ns, Total: 24048445 ns +[2021-01-28T10:41:39.423+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 40146411 ns, Reaching safepoint: 5941138 ns, At safepoint: 78621 ns, Total: 6019759 ns +[2021-01-28T10:41:39.436+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 10574781 ns, Reaching safepoint: 2523178 ns, At safepoint: 106468 ns, Total: 2629646 ns +[2021-01-28T10:41:39.482+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 27545325 ns, Reaching safepoint: 18940671 ns, At safepoint: 92924 ns, Total: 19033595 ns +[2021-01-28T10:41:39.490+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2242554 ns, Reaching safepoint: 5612908 ns, At safepoint: 92633 ns, Total: 5705541 ns +[2021-01-28T10:41:39.517+0000][1][safepoint ] Safepoint "BulkRevokeBias", Time since last: 16900660 ns, Reaching safepoint: 9231007 ns, At safepoint: 444674 ns, Total: 9675681 ns +[2021-01-28T10:41:39.589+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 71668450 ns, Reaching safepoint: 272068 ns, At safepoint: 45035 ns, Total: 317103 ns +[2021-01-28T10:41:39.619+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 29806145 ns, Reaching safepoint: 129584 ns, At safepoint: 39927 ns, Total: 169511 ns +[2021-01-28T10:41:39.644+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 18535515 ns, Reaching safepoint: 6050758 ns, At safepoint: 55342 ns, Total: 6106100 ns +[2021-01-28T10:41:39.670+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2790317 ns, Reaching safepoint: 24080588 ns, At safepoint: 51397 ns, Total: 24131985 ns +[2021-01-28T10:41:39.762+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 83831287 ns, Reaching safepoint: 1379954 ns, At safepoint: 6551235 ns, Total: 7931189 ns +[2021-01-28T10:41:39.834+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 64105840 ns, Reaching safepoint: 7611786 ns, At safepoint: 53291 ns, Total: 7665077 ns +[2021-01-28T10:41:39.872+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 35997897 ns, Reaching safepoint: 1844069 ns, At safepoint: 52491 ns, Total: 1896560 ns +[2021-01-28T10:41:39.899+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 15702746 ns, Reaching safepoint: 11842834 ns, At safepoint: 50877 ns, Total: 11893711 ns +[2021-01-28T10:41:39.910+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 4674166 ns, Reaching safepoint: 5344648 ns, At safepoint: 65074 ns, Total: 5409722 ns +[2021-01-28T10:41:39.920+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 6283275 ns, Reaching safepoint: 4336854 ns, At safepoint: 50088 ns, Total: 4386942 ns +[2021-01-28T10:41:39.928+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1444632 ns, Reaching safepoint: 5913173 ns, At safepoint: 51577 ns, Total: 5964750 ns +[2021-01-28T10:41:39.931+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 645594 ns, Reaching safepoint: 2900201 ns, At safepoint: 53320 ns, Total: 2953521 ns +[2021-01-28T10:41:40.070+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 124050703 ns, Reaching safepoint: 14202553 ns, At safepoint: 45227 ns, Total: 14247780 ns +[2021-01-28T10:41:40.126+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 56216742 ns, Reaching safepoint: 134150 ns, At safepoint: 5674 ns, Total: 139824 ns +[2021-01-28T10:41:40.135+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 9392719 ns, Reaching safepoint: 154780 ns, At safepoint: 6915 ns, Total: 161695 ns +[2021-01-28T10:41:40.141+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 4976541 ns, Reaching safepoint: 183801 ns, At safepoint: 5913 ns, Total: 189714 ns +[2021-01-28T10:41:40.157+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 16104326 ns, Reaching safepoint: 212108 ns, At safepoint: 8496 ns, Total: 220604 ns +[2021-01-28T10:41:40.157+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 136040 ns, Reaching safepoint: 358358 ns, At safepoint: 6379 ns, Total: 364737 ns +[2021-01-28T10:41:40.158+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 53717 ns, Reaching safepoint: 292643 ns, At safepoint: 5026 ns, Total: 297669 ns +[2021-01-28T10:41:40.158+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 51930 ns, Reaching safepoint: 299361 ns, At safepoint: 5403 ns, Total: 304764 ns +[2021-01-28T10:41:40.159+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 535422 ns, Reaching safepoint: 271705 ns, At safepoint: 6212 ns, Total: 277917 ns +[2021-01-28T10:41:40.159+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 48931 ns, Reaching safepoint: 273147 ns, At safepoint: 5098 ns, Total: 278245 ns +[2021-01-28T10:41:40.160+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 49112 ns, Reaching safepoint: 285165 ns, At safepoint: 5041 ns, Total: 290206 ns +[2021-01-28T10:41:40.160+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 68762 ns, Reaching safepoint: 286736 ns, At safepoint: 5189 ns, Total: 291925 ns +[2021-01-28T10:41:40.320+0000][1][safepoint ] Safepoint "Deoptimize", Time since last: 159019848 ns, Reaching safepoint: 316805 ns, At safepoint: 578407 ns, Total: 895212 ns +[2021-01-28T10:41:40.327+0000][1][safepoint ] Safepoint "Deoptimize", Time since last: 5946477 ns, Reaching safepoint: 388303 ns, At safepoint: 519733 ns, Total: 908036 ns +[2021-01-28T10:41:40.442+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 114960095 ns, Reaching safepoint: 434718 ns, At safepoint: 54368 ns, Total: 489086 ns +[2021-01-28T10:41:40.520+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 77070201 ns, Reaching safepoint: 318315 ns, At safepoint: 16652 ns, Total: 334967 ns +[2021-01-28T10:41:40.522+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1327591 ns, Reaching safepoint: 666457 ns, At safepoint: 18775 ns, Total: 685232 ns +[2021-01-28T10:41:40.526+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 3732019 ns, Reaching safepoint: 402665 ns, At safepoint: 101583 ns, Total: 504248 ns +[2021-01-28T10:41:40.529+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 3436901 ns, Reaching safepoint: 157090 ns, At safepoint: 20591 ns, Total: 177681 ns +[2021-01-28T10:41:40.531+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 562908 ns, Reaching safepoint: 755973 ns, At safepoint: 30085 ns, Total: 786058 ns +[2021-01-28T10:41:40.534+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 3500987 ns, Reaching safepoint: 130501 ns, At safepoint: 14469 ns, Total: 144970 ns +[2021-01-28T10:41:41.535+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000793578 ns, Reaching safepoint: 170982 ns, At safepoint: 3127 ns, Total: 174109 ns +[2021-01-28T10:41:42.536+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000240250 ns, Reaching safepoint: 145223 ns, At safepoint: 2741 ns, Total: 147964 ns +[2021-01-28T10:41:43.536+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000211036 ns, Reaching safepoint: 258822 ns, At safepoint: 3801 ns, Total: 262623 ns +[2021-01-28T10:41:44.170+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 632702545 ns, Reaching safepoint: 749160 ns, At safepoint: 211739 ns, Total: 960899 ns +[2021-01-28T10:41:44.174+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 742600 ns, Reaching safepoint: 2952031 ns, At safepoint: 168099 ns, Total: 3120130 ns +[2021-01-28T10:41:44.193+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 465618 ns, Reaching safepoint: 18995468 ns, At safepoint: 138294 ns, Total: 19133762 ns +[2021-01-28T10:41:44.199+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2287580 ns, Reaching safepoint: 2745379 ns, At safepoint: 236631 ns, Total: 2982010 ns +[2021-01-28T10:41:44.203+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 649019 ns, Reaching safepoint: 3009662 ns, At safepoint: 158197 ns, Total: 3167859 ns +[2021-01-28T10:41:44.218+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 441424 ns, Reaching safepoint: 14951768 ns, At safepoint: 163805 ns, Total: 15115573 ns +[2021-01-28T10:41:44.249+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 976093 ns, Reaching safepoint: 28116092 ns, At safepoint: 1645292 ns, Total: 29761384 ns +[2021-01-28T10:41:44.258+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 423966 ns, Reaching safepoint: 8098148 ns, At safepoint: 263404 ns, Total: 8361552 ns +[2021-01-28T10:41:44.267+0000][1][safepoint ] Safepoint "BulkRevokeBias", Time since last: 534975 ns, Reaching safepoint: 8222124 ns, At safepoint: 667973 ns, Total: 8890097 ns +[2021-01-28T10:41:44.276+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 5279511 ns, Reaching safepoint: 2967400 ns, At safepoint: 140418 ns, Total: 3107818 ns +[2021-01-28T10:41:44.294+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1979108 ns, Reaching safepoint: 15918008 ns, At safepoint: 119931 ns, Total: 16037939 ns +[2021-01-28T10:41:44.300+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1203274 ns, Reaching safepoint: 4620741 ns, At safepoint: 516927 ns, Total: 5137668 ns +[2021-01-28T10:41:44.322+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 6887125 ns, Reaching safepoint: 15431229 ns, At safepoint: 195979 ns, Total: 15627208 ns +[2021-01-28T10:41:44.470+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 134065958 ns, Reaching safepoint: 12993262 ns, At safepoint: 229511 ns, Total: 13222773 ns +[2021-01-28T10:41:44.478+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1624952 ns, Reaching safepoint: 6391698 ns, At safepoint: 196904 ns, Total: 6588602 ns +[2021-01-28T10:41:44.507+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 25362142 ns, Reaching safepoint: 3472715 ns, At safepoint: 340106 ns, Total: 3812821 ns +[2021-01-28T10:41:44.596+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 47300808 ns, Reaching safepoint: 41259035 ns, At safepoint: 242837 ns, Total: 41501872 ns +[2021-01-28T10:41:44.605+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1356274 ns, Reaching safepoint: 6936460 ns, At safepoint: 497486 ns, Total: 7433946 ns +[2021-01-28T10:41:44.615+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 4605194 ns, Reaching safepoint: 5441806 ns, At safepoint: 112799 ns, Total: 5554605 ns +[2021-01-28T10:41:44.622+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 6016315 ns, Reaching safepoint: 620690 ns, At safepoint: 89610 ns, Total: 710300 ns +[2021-01-28T10:41:44.636+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 889212 ns, Reaching safepoint: 13059235 ns, At safepoint: 80943 ns, Total: 13140178 ns +[2021-01-28T10:41:44.802+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 149717707 ns, Reaching safepoint: 16177407 ns, At safepoint: 162375 ns, Total: 16339782 ns +[2021-01-28T10:41:44.809+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 832386 ns, Reaching safepoint: 5973537 ns, At safepoint: 141104 ns, Total: 6114641 ns +[2021-01-28T10:41:44.823+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 6836861 ns, Reaching safepoint: 6642638 ns, At safepoint: 1275539 ns, Total: 7918177 ns +[2021-01-28T10:41:44.837+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2308197 ns, Reaching safepoint: 10765542 ns, At safepoint: 139090 ns, Total: 10904632 ns +[2021-01-28T10:41:44.892+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 37999581 ns, Reaching safepoint: 17162400 ns, At safepoint: 113658 ns, Total: 17276058 ns +[2021-01-28T10:41:44.916+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 8582211 ns, Reaching safepoint: 15080574 ns, At safepoint: 63750 ns, Total: 15144324 ns +[2021-01-28T10:41:44.961+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2199378 ns, Reaching safepoint: 42987257 ns, At safepoint: 29586 ns, Total: 43016843 ns +[2021-01-28T10:41:44.962+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 864434 ns, Reaching safepoint: 162509 ns, At safepoint: 44466 ns, Total: 206975 ns +[2021-01-28T10:41:44.978+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 424405 ns, Reaching safepoint: 15370338 ns, At safepoint: 220016 ns, Total: 15590354 ns +[2021-01-28T10:41:44.998+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 19730889 ns, Reaching safepoint: 166481 ns, At safepoint: 16932 ns, Total: 183413 ns +[2021-01-28T10:41:46.002+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000347223 ns, Reaching safepoint: 3693302 ns, At safepoint: 25237 ns, Total: 3718539 ns +[2021-01-28T10:41:47.002+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000390990 ns, Reaching safepoint: 186972 ns, At safepoint: 4398 ns, Total: 191370 ns +[2021-01-28T10:41:48.003+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000142443 ns, Reaching safepoint: 154608 ns, At safepoint: 3646 ns, Total: 158254 ns +[2021-01-28T10:41:49.003+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000178362 ns, Reaching safepoint: 155116 ns, At safepoint: 3120 ns, Total: 158236 ns +[2021-01-28T10:41:49.155+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 151671036 ns, Reaching safepoint: 184409 ns, At safepoint: 17939 ns, Total: 202348 ns +[2021-01-28T10:41:49.184+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 17026094 ns, Reaching safepoint: 11515726 ns, At safepoint: 137178 ns, Total: 11652904 ns +[2021-01-28T10:41:49.190+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1068426 ns, Reaching safepoint: 4924272 ns, At safepoint: 233223 ns, Total: 5157495 ns +[2021-01-28T10:41:49.192+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 78911 ns, Reaching safepoint: 1583272 ns, At safepoint: 234411 ns, Total: 1817683 ns +[2021-01-28T10:41:49.195+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2521622 ns, Reaching safepoint: 564523 ns, At safepoint: 194031 ns, Total: 758554 ns +[2021-01-28T10:41:49.281+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 64932863 ns, Reaching safepoint: 20675165 ns, At safepoint: 127959 ns, Total: 20803124 ns +[2021-01-28T10:41:49.283+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1872687 ns, Reaching safepoint: 407893 ns, At safepoint: 48284 ns, Total: 456177 ns +[2021-01-28T10:41:49.297+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 6277376 ns, Reaching safepoint: 7424062 ns, At safepoint: 76619 ns, Total: 7500681 ns +[2021-01-28T10:41:49.345+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 47455869 ns, Reaching safepoint: 535792 ns, At safepoint: 47207 ns, Total: 582999 ns +[2021-01-28T10:41:49.348+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 3256654 ns, Reaching safepoint: 193225 ns, At safepoint: 68958 ns, Total: 262183 ns +[2021-01-28T10:41:49.351+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1822142 ns, Reaching safepoint: 268069 ns, At safepoint: 22530 ns, Total: 290599 ns +[2021-01-28T10:41:50.351+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000511898 ns, Reaching safepoint: 246148 ns, At safepoint: 4806 ns, Total: 250954 ns +[2021-01-28T10:41:51.352+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000273081 ns, Reaching safepoint: 233512 ns, At safepoint: 11146 ns, Total: 244658 ns +[2021-01-28T10:41:52.352+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000149625 ns, Reaching safepoint: 136883 ns, At safepoint: 2493 ns, Total: 139376 ns +[2021-01-28T10:41:53.353+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000421145 ns, Reaching safepoint: 180771 ns, At safepoint: 7646 ns, Total: 188417 ns +[2021-01-28T10:41:54.156+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 802761073 ns, Reaching safepoint: 156449 ns, At safepoint: 16196 ns, Total: 172645 ns +[2021-01-28T10:41:54.177+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 20294274 ns, Reaching safepoint: 748451 ns, At safepoint: 617499 ns, Total: 1365950 ns +[2021-01-28T10:41:54.190+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 5003640 ns, Reaching safepoint: 7438636 ns, At safepoint: 110873 ns, Total: 7549509 ns +[2021-01-28T10:41:54.212+0000][1][safepoint ] Safepoint "BulkRevokeBias", Time since last: 9303226 ns, Reaching safepoint: 2916482 ns, At safepoint: 9582777 ns, Total: 12499259 ns +[2021-01-28T10:41:54.234+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2381974 ns, Reaching safepoint: 19505659 ns, At safepoint: 106360 ns, Total: 19612019 ns +[2021-01-28T10:41:54.236+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1905851 ns, Reaching safepoint: 417297 ns, At safepoint: 278873 ns, Total: 696170 ns +[2021-01-28T10:41:54.244+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 7245630 ns, Reaching safepoint: 536313 ns, At safepoint: 43052 ns, Total: 579365 ns +[2021-01-28T10:41:54.336+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 91249089 ns, Reaching safepoint: 196201 ns, At safepoint: 16086 ns, Total: 212287 ns +[2021-01-28T10:41:55.336+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000232367 ns, Reaching safepoint: 135950 ns, At safepoint: 27858 ns, Total: 163808 ns +[2021-01-28T10:41:56.336+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000375611 ns, Reaching safepoint: 169511 ns, At safepoint: 8446 ns, Total: 177957 ns +[2021-01-28T10:41:57.337+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000221275 ns, Reaching safepoint: 190061 ns, At safepoint: 4156 ns, Total: 194217 ns +[2021-01-28T10:41:58.337+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000322256 ns, Reaching safepoint: 237603 ns, At safepoint: 5329 ns, Total: 242932 ns +[2021-01-28T10:41:59.157+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 819224802 ns, Reaching safepoint: 237919 ns, At safepoint: 41671 ns, Total: 279590 ns +[2021-01-28T10:41:59.183+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 19432511 ns, Reaching safepoint: 5991868 ns, At safepoint: 122341 ns, Total: 6114209 ns +[2021-01-28T10:41:59.205+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 5446060 ns, Reaching safepoint: 16495740 ns, At safepoint: 108345 ns, Total: 16604085 ns +[2021-01-28T10:41:59.207+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2138020 ns, Reaching safepoint: 332332 ns, At safepoint: 96348 ns, Total: 428680 ns +[2021-01-28T10:41:59.234+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 18360616 ns, Reaching safepoint: 7954251 ns, At safepoint: 146116 ns, Total: 8100367 ns +[2021-01-28T10:41:59.248+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 7941671 ns, Reaching safepoint: 6237671 ns, At safepoint: 145758 ns, Total: 6383429 ns +[2021-01-28T10:41:59.250+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1913568 ns, Reaching safepoint: 389962 ns, At safepoint: 151186 ns, Total: 541148 ns +[2021-01-28T10:41:59.251+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 300134 ns, Reaching safepoint: 263159 ns, At safepoint: 156098 ns, Total: 419257 ns +[2021-01-28T10:41:59.302+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 49807115 ns, Reaching safepoint: 575950 ns, At safepoint: 49721 ns, Total: 625671 ns +[2021-01-28T10:42:00.302+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000200150 ns, Reaching safepoint: 180311 ns, At safepoint: 3603 ns, Total: 183914 ns +[2021-01-28T10:42:01.302+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000331915 ns, Reaching safepoint: 186716 ns, At safepoint: 17732 ns, Total: 204448 ns +[2021-01-28T10:42:02.303+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000193934 ns, Reaching safepoint: 190786 ns, At safepoint: 4026 ns, Total: 194812 ns +[2021-01-28T10:42:03.303+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000323738 ns, Reaching safepoint: 209980 ns, At safepoint: 4041 ns, Total: 214021 ns +[2021-01-28T10:42:04.182+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 872311671 ns, Reaching safepoint: 5977701 ns, At safepoint: 190129 ns, Total: 6167830 ns +[2021-01-28T10:42:04.204+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 19502379 ns, Reaching safepoint: 2254258 ns, At safepoint: 85254 ns, Total: 2339512 ns +[2021-01-28T10:42:04.237+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 18010220 ns, Reaching safepoint: 15563981 ns, At safepoint: 155733 ns, Total: 15719714 ns +[2021-01-28T10:42:04.242+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1387965 ns, Reaching safepoint: 2658958 ns, At safepoint: 110357 ns, Total: 2769315 ns +[2021-01-28T10:42:04.243+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1422891 ns, Reaching safepoint: 375812 ns, At safepoint: 69194 ns, Total: 445006 ns +[2021-01-28T10:42:05.244+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000211753 ns, Reaching safepoint: 158324 ns, At safepoint: 25450 ns, Total: 183774 ns +[2021-01-28T10:42:06.244+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000284518 ns, Reaching safepoint: 176845 ns, At safepoint: 3020 ns, Total: 179865 ns +[2021-01-28T10:42:07.245+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000186034 ns, Reaching safepoint: 117824 ns, At safepoint: 3508 ns, Total: 121332 ns +[2021-01-28T10:42:08.245+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000147196 ns, Reaching safepoint: 130743 ns, At safepoint: 3233 ns, Total: 133976 ns +[2021-01-28T10:42:09.177+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 931108717 ns, Reaching safepoint: 455635 ns, At safepoint: 51420 ns, Total: 507055 ns +[2021-01-28T10:42:09.189+0000][1][safepoint ] Safepoint "BulkRevokeBias", Time since last: 7078189 ns, Reaching safepoint: 4843449 ns, At safepoint: 625725 ns, Total: 5469174 ns +[2021-01-28T10:42:10.189+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000172698 ns, Reaching safepoint: 152071 ns, At safepoint: 2952 ns, Total: 155023 ns +[2021-01-28T10:42:11.190+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000164565 ns, Reaching safepoint: 250418 ns, At safepoint: 6183 ns, Total: 256601 ns +[2021-01-28T10:42:12.192+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1001468806 ns, Reaching safepoint: 1174612 ns, At safepoint: 35040 ns, Total: 1209652 ns +[2021-01-28T10:42:13.193+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000218360 ns, Reaching safepoint: 170958 ns, At safepoint: 3241 ns, Total: 174199 ns +[2021-01-28T10:42:14.183+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 987703120 ns, Reaching safepoint: 2673807 ns, At safepoint: 180526 ns, Total: 2854333 ns +[2021-01-28T10:42:14.267+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 72196433 ns, Reaching safepoint: 11290235 ns, At safepoint: 106953 ns, Total: 11397188 ns +[2021-01-28T10:42:15.268+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000475627 ns, Reaching safepoint: 165401 ns, At safepoint: 2522 ns, Total: 167923 ns +[2021-01-28T10:42:16.268+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000258273 ns, Reaching safepoint: 151094 ns, At safepoint: 3591 ns, Total: 154685 ns +[2021-01-28T10:42:17.268+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000158821 ns, Reaching safepoint: 139840 ns, At safepoint: 2691 ns, Total: 142531 ns +[2021-01-28T10:42:18.270+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1001261409 ns, Reaching safepoint: 678261 ns, At safepoint: 15040 ns, Total: 693301 ns +[2021-01-28T10:42:19.271+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000235319 ns, Reaching safepoint: 167112 ns, At safepoint: 3585 ns, Total: 170697 ns +[2021-01-28T10:42:20.271+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000294791 ns, Reaching safepoint: 134603 ns, At safepoint: 3243 ns, Total: 137846 ns +[2021-01-28T10:42:21.272+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000264025 ns, Reaching safepoint: 170410 ns, At safepoint: 3119 ns, Total: 173529 ns +[2021-01-28T10:42:22.272+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000264646 ns, Reaching safepoint: 161534 ns, At safepoint: 3659 ns, Total: 165193 ns +[2021-01-28T10:42:23.273+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000227102 ns, Reaching safepoint: 193401 ns, At safepoint: 3781 ns, Total: 197182 ns +[2021-01-28T10:42:24.274+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000941371 ns, Reaching safepoint: 126158 ns, At safepoint: 25180 ns, Total: 151338 ns +[2021-01-28T10:42:25.274+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000347574 ns, Reaching safepoint: 170009 ns, At safepoint: 3849 ns, Total: 173858 ns +[2021-01-28T10:42:26.275+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000526296 ns, Reaching safepoint: 291274 ns, At safepoint: 8378 ns, Total: 299652 ns +[2021-01-28T10:42:27.276+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000778011 ns, Reaching safepoint: 252317 ns, At safepoint: 6885 ns, Total: 259202 ns +[2021-01-28T10:42:28.277+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000271903 ns, Reaching safepoint: 342997 ns, At safepoint: 7863 ns, Total: 350860 ns +[2021-01-28T10:42:29.178+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 900312460 ns, Reaching safepoint: 599393 ns, At safepoint: 525737 ns, Total: 1125130 ns +[2021-01-28T10:42:29.222+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 43437257 ns, Reaching safepoint: 529703 ns, At safepoint: 22207 ns, Total: 551910 ns +[2021-01-28T10:42:30.223+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000295772 ns, Reaching safepoint: 262678 ns, At safepoint: 5229 ns, Total: 267907 ns +[2021-01-28T10:42:31.223+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000222982 ns, Reaching safepoint: 159833 ns, At safepoint: 4476 ns, Total: 164309 ns +[2021-01-28T10:42:32.224+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000363266 ns, Reaching safepoint: 229406 ns, At safepoint: 9667 ns, Total: 239073 ns +[2021-01-28T10:42:33.224+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000199052 ns, Reaching safepoint: 154719 ns, At safepoint: 5090 ns, Total: 159809 ns +[2021-01-28T10:42:34.225+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000425871 ns, Reaching safepoint: 174997 ns, At safepoint: 35528 ns, Total: 210525 ns +[2021-01-28T10:42:35.225+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000480918 ns, Reaching safepoint: 409160 ns, At safepoint: 8957 ns, Total: 418117 ns +[2021-01-28T10:42:36.227+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000777786 ns, Reaching safepoint: 260134 ns, At safepoint: 6754 ns, Total: 266888 ns +[2021-01-28T10:42:37.227+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000391137 ns, Reaching safepoint: 253493 ns, At safepoint: 7915 ns, Total: 261408 ns +[2021-01-28T10:42:38.229+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1001708836 ns, Reaching safepoint: 578342 ns, At safepoint: 9232 ns, Total: 587574 ns +[2021-01-28T10:42:39.236+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1005450412 ns, Reaching safepoint: 836308 ns, At safepoint: 32665 ns, Total: 868973 ns +[2021-01-28T10:42:39.962+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 718695181 ns, Reaching safepoint: 7405168 ns, At safepoint: 47533 ns, Total: 7452701 ns +[2021-01-28T10:42:39.984+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 21331636 ns, Reaching safepoint: 358857 ns, At safepoint: 18510 ns, Total: 377367 ns +[2021-01-28T10:42:40.985+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000465710 ns, Reaching safepoint: 373081 ns, At safepoint: 5846 ns, Total: 378927 ns +[2021-01-28T10:42:42.986+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 2000859820 ns, Reaching safepoint: 374504 ns, At safepoint: 4738 ns, Total: 379242 ns +[2021-01-28T10:42:44.987+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 2000317799 ns, Reaching safepoint: 378119 ns, At safepoint: 35713 ns, Total: 413832 ns +[2021-01-28T10:42:45.987+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000429147 ns, Reaching safepoint: 282218 ns, At safepoint: 13554 ns, Total: 295772 ns +[2021-01-28T10:42:47.988+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 2000379809 ns, Reaching safepoint: 237310 ns, At safepoint: 9252 ns, Total: 246562 ns +[2021-01-28T10:42:49.989+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 2000637405 ns, Reaching safepoint: 211307 ns, At safepoint: 4577 ns, Total: 215884 ns +[2021-01-28T10:42:50.990+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000328439 ns, Reaching safepoint: 542522 ns, At safepoint: 31327 ns, Total: 573849 ns +[2021-01-28T10:42:51.991+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000368501 ns, Reaching safepoint: 535609 ns, At safepoint: 11186 ns, Total: 546795 ns +[2021-01-28T10:42:52.992+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000686963 ns, Reaching safepoint: 328409 ns, At safepoint: 5397 ns, Total: 333806 ns +[2021-01-28T10:42:53.993+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000855200 ns, Reaching safepoint: 313142 ns, At safepoint: 7240 ns, Total: 320382 ns +[2021-01-28T10:42:54.994+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000864017 ns, Reaching safepoint: 273358 ns, At safepoint: 4116 ns, Total: 277474 ns +[2021-01-28T10:42:55.996+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1001815872 ns, Reaching safepoint: 544165 ns, At safepoint: 15167 ns, Total: 559332 ns +[2021-01-28T10:42:56.997+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000589681 ns, Reaching safepoint: 355185 ns, At safepoint: 13311 ns, Total: 368496 ns +[2021-01-28T10:42:57.998+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000348979 ns, Reaching safepoint: 545016 ns, At safepoint: 16535 ns, Total: 561551 ns +[2021-01-28T10:42:58.999+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000283174 ns, Reaching safepoint: 308944 ns, At safepoint: 10847 ns, Total: 319791 ns +[2021-01-28T10:42:59.999+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000303132 ns, Reaching safepoint: 175773 ns, At safepoint: 32729 ns, Total: 208502 ns +[2021-01-28T10:43:01.000+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000210022 ns, Reaching safepoint: 362273 ns, At safepoint: 9976 ns, Total: 372249 ns +[2021-01-28T10:43:02.000+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000259699 ns, Reaching safepoint: 193798 ns, At safepoint: 4325 ns, Total: 198123 ns +[2021-01-28T10:43:03.001+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000337965 ns, Reaching safepoint: 349103 ns, At safepoint: 7416 ns, Total: 356519 ns +[2021-01-28T10:43:04.002+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000388798 ns, Reaching safepoint: 222195 ns, At safepoint: 5439 ns, Total: 227634 ns +[2021-01-28T10:43:05.016+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000230277 ns, Reaching safepoint: 14440934 ns, At safepoint: 158800 ns, Total: 14599734 ns +[2021-01-28T10:43:06.017+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000229834 ns, Reaching safepoint: 295965 ns, At safepoint: 34169 ns, Total: 330134 ns +[2021-01-28T10:43:07.018+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000264115 ns, Reaching safepoint: 265945 ns, At safepoint: 3255 ns, Total: 269200 ns +[2021-01-28T10:43:08.018+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000212909 ns, Reaching safepoint: 218741 ns, At safepoint: 4595 ns, Total: 223336 ns +[2021-01-28T10:43:09.019+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000410381 ns, Reaching safepoint: 186043 ns, At safepoint: 4895 ns, Total: 190938 ns +[2021-01-28T10:43:10.022+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000243172 ns, Reaching safepoint: 3193420 ns, At safepoint: 120032 ns, Total: 3313452 ns +[2021-01-28T10:43:10.027+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 4380658 ns, Reaching safepoint: 161201 ns, At safepoint: 64450 ns, Total: 225651 ns +[2021-01-28T10:43:11.027+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000197465 ns, Reaching safepoint: 216255 ns, At safepoint: 30890 ns, Total: 247145 ns +[2021-01-28T10:43:12.028+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000463185 ns, Reaching safepoint: 393732 ns, At safepoint: 10990 ns, Total: 404722 ns +[2021-01-28T10:43:13.029+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000338242 ns, Reaching safepoint: 376342 ns, At safepoint: 9891 ns, Total: 386233 ns +[2021-01-28T10:43:14.030+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000407670 ns, Reaching safepoint: 276067 ns, At safepoint: 10937 ns, Total: 287004 ns +[2021-01-28T10:43:15.031+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000221937 ns, Reaching safepoint: 735624 ns, At safepoint: 116556 ns, Total: 852180 ns +[2021-01-28T10:43:16.031+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000288594 ns, Reaching safepoint: 308651 ns, At safepoint: 37185 ns, Total: 345836 ns +[2021-01-28T10:43:17.032+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000744266 ns, Reaching safepoint: 310606 ns, At safepoint: 6281 ns, Total: 316887 ns +[2021-01-28T10:43:18.033+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000568508 ns, Reaching safepoint: 156592 ns, At safepoint: 3277 ns, Total: 159869 ns +[2021-01-28T10:43:19.034+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000149612 ns, Reaching safepoint: 290420 ns, At safepoint: 4577 ns, Total: 294997 ns +[2021-01-28T10:43:20.036+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1002294463 ns, Reaching safepoint: 414382 ns, At safepoint: 44730 ns, Total: 459112 ns +[2021-01-28T10:43:21.038+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000417636 ns, Reaching safepoint: 374048 ns, At safepoint: 651273 ns, Total: 1025321 ns +[2021-01-28T10:43:22.039+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000408555 ns, Reaching safepoint: 385249 ns, At safepoint: 11303 ns, Total: 396552 ns +[2021-01-28T10:43:23.039+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000296817 ns, Reaching safepoint: 320843 ns, At safepoint: 8089 ns, Total: 328932 ns +[2021-01-28T10:43:24.040+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000466303 ns, Reaching safepoint: 294199 ns, At safepoint: 6670 ns, Total: 300869 ns +[2021-01-28T10:43:25.040+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000250426 ns, Reaching safepoint: 205577 ns, At safepoint: 6979 ns, Total: 212556 ns +[2021-01-28T10:43:26.041+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000346862 ns, Reaching safepoint: 198524 ns, At safepoint: 4473 ns, Total: 202997 ns +[2021-01-28T10:43:27.042+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000302629 ns, Reaching safepoint: 383932 ns, At safepoint: 9699 ns, Total: 393631 ns +[2021-01-28T10:43:28.042+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000334512 ns, Reaching safepoint: 166180 ns, At safepoint: 3623 ns, Total: 169803 ns +[2021-01-28T10:43:29.043+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000223301 ns, Reaching safepoint: 466116 ns, At safepoint: 5581 ns, Total: 471697 ns +[2021-01-28T10:43:30.044+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000189094 ns, Reaching safepoint: 367752 ns, At safepoint: 1135090 ns, Total: 1502842 ns +[2021-01-28T10:43:30.077+0000][1][gc,start ] GC(8) Pause Young (Concurrent Start) (Metadata GC Threshold) +[2021-01-28T10:43:30.077+0000][1][gc,task ] GC(8) Using 4 workers of 4 for evacuation +[2021-01-28T10:43:30.077+0000][1][gc,age ] GC(8) Desired survivor size 20447232 bytes, new threshold 15 (max threshold 15) +[2021-01-28T10:43:30.102+0000][1][gc,age ] GC(8) Age table with threshold 15 (max threshold 15) +[2021-01-28T10:43:30.102+0000][1][gc,age ] GC(8) - age 1: 11354232 bytes, 11354232 total +[2021-01-28T10:43:30.102+0000][1][gc,age ] GC(8) - age 2: 5099664 bytes, 16453896 total +[2021-01-28T10:43:30.102+0000][1][gc,age ] GC(8) - age 3: 1543728 bytes, 17997624 total +[2021-01-28T10:43:30.102+0000][1][gc,age ] GC(8) - age 4: 18216 bytes, 18015840 total +[2021-01-28T10:43:30.102+0000][1][gc,age ] GC(8) - age 5: 271056 bytes, 18286896 total +[2021-01-28T10:43:30.102+0000][1][gc,phases ] GC(8) Pre Evacuate Collection Set: 0.5ms +[2021-01-28T10:43:30.102+0000][1][gc,phases ] GC(8) Evacuate Collection Set: 22.8ms +[2021-01-28T10:43:30.102+0000][1][gc,phases ] GC(8) Post Evacuate Collection Set: 2.3ms +[2021-01-28T10:43:30.102+0000][1][gc,phases ] GC(8) Other: 0.4ms +[2021-01-28T10:43:30.102+0000][1][gc,heap ] GC(8) Eden regions: 162->0(268) +[2021-01-28T10:43:30.102+0000][1][gc,heap ] GC(8) Survivor regions: 8->18(39) +[2021-01-28T10:43:30.103+0000][1][gc,heap ] GC(8) Old regions: 7->7 +[2021-01-28T10:43:30.103+0000][1][gc,heap ] GC(8) Archive regions: 2->2 +[2021-01-28T10:43:30.103+0000][1][gc,heap ] GC(8) Humongous regions: 41->21 +[2021-01-28T10:43:30.103+0000][1][gc,metaspace ] GC(8) Metaspace: 57209K->57209K(1099776K) +[2021-01-28T10:43:30.103+0000][1][gc ] GC(8) Pause Young (Concurrent Start) (Metadata GC Threshold) 216M->45M(512M) 26.058ms +[2021-01-28T10:43:30.103+0000][1][gc,cpu ] GC(8) User=0.05s Sys=0.01s Real=0.03s +[2021-01-28T10:43:30.103+0000][1][gc ] GC(9) Concurrent Cycle +[2021-01-28T10:43:30.103+0000][1][gc,marking ] GC(9) Concurrent Clear Claimed Marks +[2021-01-28T10:43:30.103+0000][1][gc,marking ] GC(9) Concurrent Clear Claimed Marks 0.356ms +[2021-01-28T10:43:30.103+0000][1][gc,marking ] GC(9) Concurrent Scan Root Regions +[2021-01-28T10:43:30.103+0000][1][safepoint ] Safepoint "CollectForMetadataAllocation", Time since last: 31484520 ns, Reaching safepoint: 484779 ns, At safepoint: 26291284 ns, Total: 26776063 ns +[2021-01-28T10:43:30.122+0000][1][gc,marking ] GC(9) Concurrent Scan Root Regions 18.363ms +[2021-01-28T10:43:30.122+0000][1][gc,marking ] GC(9) Concurrent Mark (143.736s) +[2021-01-28T10:43:30.122+0000][1][gc,marking ] GC(9) Concurrent Mark From Roots +[2021-01-28T10:43:30.122+0000][1][gc,task ] GC(9) Using 1 workers of 1 for marking +[2021-01-28T10:43:30.132+0000][1][gc,marking ] GC(9) Concurrent Mark From Roots 10.880ms +[2021-01-28T10:43:30.133+0000][1][gc,marking ] GC(9) Concurrent Preclean +[2021-01-28T10:43:30.133+0000][1][gc,marking ] GC(9) Concurrent Preclean 0.053ms +[2021-01-28T10:43:30.133+0000][1][gc,marking ] GC(9) Concurrent Mark (143.736s, 143.747s) 10.990ms +[2021-01-28T10:43:30.133+0000][1][gc,start ] GC(9) Pause Remark +[2021-01-28T10:43:30.137+0000][1][gc ] GC(9) Pause Remark 46M->26M(512M) 4.584ms +[2021-01-28T10:43:30.138+0000][1][gc,cpu ] GC(9) User=0.01s Sys=0.00s Real=0.01s +[2021-01-28T10:43:30.138+0000][1][safepoint ] Safepoint "G1Concurrent", Time since last: 29897830 ns, Reaching safepoint: 205833 ns, At safepoint: 4723480 ns, Total: 4929313 ns +[2021-01-28T10:43:30.138+0000][1][gc,marking ] GC(9) Concurrent Rebuild Remembered Sets +[2021-01-28T10:43:30.143+0000][1][gc,marking ] GC(9) Concurrent Rebuild Remembered Sets 4.955ms +[2021-01-28T10:43:30.144+0000][1][gc,start ] GC(9) Pause Cleanup +[2021-01-28T10:43:30.144+0000][1][gc ] GC(9) Pause Cleanup 26M->26M(512M) 0.220ms +[2021-01-28T10:43:30.144+0000][1][gc,cpu ] GC(9) User=0.00s Sys=0.00s Real=0.00s +[2021-01-28T10:43:30.144+0000][1][safepoint ] Safepoint "G1Concurrent", Time since last: 5125383 ns, Reaching safepoint: 794438 ns, At safepoint: 280527 ns, Total: 1074965 ns +[2021-01-28T10:43:30.144+0000][1][gc,marking ] GC(9) Concurrent Cleanup for Next Mark +[2021-01-28T10:43:30.145+0000][1][gc,marking ] GC(9) Concurrent Cleanup for Next Mark 0.873ms +[2021-01-28T10:43:30.145+0000][1][gc ] GC(9) Concurrent Cycle 42.045ms +[2021-01-28T10:43:31.144+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000190000 ns, Reaching safepoint: 322246 ns, At safepoint: 9537 ns, Total: 331783 ns +[2021-01-28T10:43:32.145+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000121237 ns, Reaching safepoint: 196961 ns, At safepoint: 4110 ns, Total: 201071 ns +[2021-01-28T10:43:33.145+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000283541 ns, Reaching safepoint: 442811 ns, At safepoint: 9489 ns, Total: 452300 ns +[2021-01-28T10:43:34.146+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000350466 ns, Reaching safepoint: 258211 ns, At safepoint: 9401 ns, Total: 267612 ns +[2021-01-28T10:43:35.148+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1001551454 ns, Reaching safepoint: 603628 ns, At safepoint: 26233 ns, Total: 629861 ns +[2021-01-28T10:43:36.149+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000478833 ns, Reaching safepoint: 394131 ns, At safepoint: 48898 ns, Total: 443029 ns +[2021-01-28T10:43:37.151+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1001137003 ns, Reaching safepoint: 593274 ns, At safepoint: 6198 ns, Total: 599472 ns +[2021-01-28T10:43:38.152+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000322010 ns, Reaching safepoint: 352757 ns, At safepoint: 35612 ns, Total: 388369 ns +[2021-01-28T10:43:39.152+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000220965 ns, Reaching safepoint: 256087 ns, At safepoint: 37147 ns, Total: 293234 ns +[2021-01-28T10:43:40.153+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000445981 ns, Reaching safepoint: 452645 ns, At safepoint: 14334 ns, Total: 466979 ns +[2021-01-28T10:43:41.154+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000614312 ns, Reaching safepoint: 290281 ns, At safepoint: 5816 ns, Total: 296097 ns +[2021-01-28T10:43:42.155+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000272672 ns, Reaching safepoint: 463153 ns, At safepoint: 8373 ns, Total: 471526 ns +[2021-01-28T10:43:43.155+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000209986 ns, Reaching safepoint: 209965 ns, At safepoint: 4725 ns, Total: 214690 ns +[2021-01-28T10:43:44.156+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000290803 ns, Reaching safepoint: 663433 ns, At safepoint: 9574 ns, Total: 673007 ns +[2021-01-28T10:43:45.157+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000283221 ns, Reaching safepoint: 307109 ns, At safepoint: 35271 ns, Total: 342380 ns +[2021-01-28T10:43:46.157+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000203336 ns, Reaching safepoint: 180602 ns, At safepoint: 4284 ns, Total: 184886 ns +[2021-01-28T10:43:47.158+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000520008 ns, Reaching safepoint: 165840 ns, At safepoint: 4364 ns, Total: 170204 ns +[2021-01-28T10:43:48.158+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000281286 ns, Reaching safepoint: 164106 ns, At safepoint: 4464 ns, Total: 168570 ns +[2021-01-28T10:43:49.160+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1001452240 ns, Reaching safepoint: 291466 ns, At safepoint: 7446 ns, Total: 298912 ns +[2021-01-28T10:43:50.161+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000316241 ns, Reaching safepoint: 562259 ns, At safepoint: 7701 ns, Total: 569960 ns +[2021-01-28T10:43:51.165+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1002230763 ns, Reaching safepoint: 2204270 ns, At safepoint: 32564 ns, Total: 2236834 ns +[2021-01-28T10:43:52.166+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000596737 ns, Reaching safepoint: 409296 ns, At safepoint: 16737 ns, Total: 426033 ns +[2021-01-28T10:43:53.167+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000366627 ns, Reaching safepoint: 150352 ns, At safepoint: 3551 ns, Total: 153903 ns +[2021-01-28T10:43:54.168+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000716870 ns, Reaching safepoint: 227292 ns, At safepoint: 3980 ns, Total: 231272 ns +[2021-01-28T10:43:55.168+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000248841 ns, Reaching safepoint: 207046 ns, At safepoint: 6868 ns, Total: 213914 ns +[2021-01-28T10:43:56.169+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000576496 ns, Reaching safepoint: 326828 ns, At safepoint: 6619 ns, Total: 333447 ns +[2021-01-28T10:43:57.170+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000597799 ns, Reaching safepoint: 402744 ns, At safepoint: 23274 ns, Total: 426018 ns +[2021-01-28T10:43:58.171+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000292872 ns, Reaching safepoint: 314061 ns, At safepoint: 4906 ns, Total: 318967 ns +[2021-01-28T10:43:59.173+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1001320359 ns, Reaching safepoint: 370109 ns, At safepoint: 7142 ns, Total: 377251 ns +[2021-01-28T10:44:00.173+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000190503 ns, Reaching safepoint: 273225 ns, At safepoint: 8279 ns, Total: 281504 ns +[2021-01-28T10:44:01.181+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1008234031 ns, Reaching safepoint: 145203 ns, At safepoint: 27332 ns, Total: 172535 ns +[2021-01-28T10:44:02.183+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000796834 ns, Reaching safepoint: 370851 ns, At safepoint: 10200 ns, Total: 381051 ns +[2021-01-28T10:44:03.183+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000350203 ns, Reaching safepoint: 310903 ns, At safepoint: 9622 ns, Total: 320525 ns +[2021-01-28T10:44:04.184+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000330279 ns, Reaching safepoint: 218206 ns, At safepoint: 6466 ns, Total: 224672 ns +[2021-01-28T10:44:05.185+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000527903 ns, Reaching safepoint: 365054 ns, At safepoint: 9153 ns, Total: 374207 ns +[2021-01-28T10:44:06.185+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000304392 ns, Reaching safepoint: 230605 ns, At safepoint: 11383 ns, Total: 241988 ns +[2021-01-28T10:44:07.186+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000383115 ns, Reaching safepoint: 230998 ns, At safepoint: 5685 ns, Total: 236683 ns +[2021-01-28T10:44:08.186+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000302439 ns, Reaching safepoint: 154684 ns, At safepoint: 3811 ns, Total: 158495 ns +[2021-01-28T10:44:09.187+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000191771 ns, Reaching safepoint: 139226 ns, At safepoint: 3280 ns, Total: 142506 ns +[2021-01-28T10:44:10.187+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000448651 ns, Reaching safepoint: 217544 ns, At safepoint: 5169 ns, Total: 222713 ns +[2021-01-28T10:44:11.188+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000530747 ns, Reaching safepoint: 197158 ns, At safepoint: 3987 ns, Total: 201145 ns +[2021-01-28T10:44:12.189+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000622500 ns, Reaching safepoint: 298596 ns, At safepoint: 7372 ns, Total: 305968 ns +[2021-01-28T10:44:13.190+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000281569 ns, Reaching safepoint: 270984 ns, At safepoint: 14391 ns, Total: 285375 ns +[2021-01-28T10:44:14.190+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000178481 ns, Reaching safepoint: 127625 ns, At safepoint: 4507 ns, Total: 132132 ns +[2021-01-28T10:44:15.190+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000199255 ns, Reaching safepoint: 191432 ns, At safepoint: 3812 ns, Total: 195244 ns +[2021-01-28T10:44:16.191+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000194892 ns, Reaching safepoint: 297855 ns, At safepoint: 126311 ns, Total: 424166 ns +[2021-01-28T10:44:17.192+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000573878 ns, Reaching safepoint: 492416 ns, At safepoint: 8578 ns, Total: 500994 ns +[2021-01-28T10:44:18.193+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000324166 ns, Reaching safepoint: 167049 ns, At safepoint: 3732 ns, Total: 170781 ns +[2021-01-28T10:44:18.722+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 529691361 ns, Reaching safepoint: 211778 ns, At safepoint: 18324 ns, Total: 230102 ns +[2021-01-28T10:44:18.723+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 618282 ns, Reaching safepoint: 181190 ns, At safepoint: 18965 ns, Total: 200155 ns +[2021-01-28T10:44:18.725+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1155265 ns, Reaching safepoint: 201093 ns, At safepoint: 22035 ns, Total: 223128 ns +[2021-01-28T10:44:18.725+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 481622 ns, Reaching safepoint: 186877 ns, At safepoint: 19291 ns, Total: 206168 ns +[2021-01-28T10:44:18.808+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 82352919 ns, Reaching safepoint: 282352 ns, At safepoint: 12566 ns, Total: 294918 ns +[2021-01-28T10:44:18.808+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 229025 ns, Reaching safepoint: 100994 ns, At safepoint: 4960 ns, Total: 105954 ns +[2021-01-28T10:44:18.825+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 16034639 ns, Reaching safepoint: 448622 ns, At safepoint: 154850 ns, Total: 603472 ns +[2021-01-28T10:44:18.827+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1486746 ns, Reaching safepoint: 354348 ns, At safepoint: 30376 ns, Total: 384724 ns +[2021-01-28T10:44:18.828+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1089281 ns, Reaching safepoint: 149908 ns, At safepoint: 76856 ns, Total: 226764 ns +[2021-01-28T10:44:18.832+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 3130253 ns, Reaching safepoint: 596183 ns, At safepoint: 72265 ns, Total: 668448 ns +[2021-01-28T10:44:18.869+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 37126119 ns, Reaching safepoint: 124855 ns, At safepoint: 27299 ns, Total: 152154 ns +[2021-01-28T10:44:18.870+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 210372 ns, Reaching safepoint: 144025 ns, At safepoint: 4138 ns, Total: 148163 ns +[2021-01-28T10:44:18.914+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 44230623 ns, Reaching safepoint: 108849 ns, At safepoint: 40736 ns, Total: 149585 ns +[2021-01-28T10:44:18.925+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 11364300 ns, Reaching safepoint: 146308 ns, At safepoint: 17454 ns, Total: 163762 ns +[2021-01-28T10:44:18.926+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 505887 ns, Reaching safepoint: 106838 ns, At safepoint: 4007 ns, Total: 110845 ns +[2021-01-28T10:44:18.926+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 278561 ns, Reaching safepoint: 97115 ns, At safepoint: 3413 ns, Total: 100528 ns +[2021-01-28T10:44:18.932+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 5242072 ns, Reaching safepoint: 114667 ns, At safepoint: 38296 ns, Total: 152963 ns +[2021-01-28T10:44:18.932+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 463382 ns, Reaching safepoint: 84516 ns, At safepoint: 37699 ns, Total: 122215 ns +[2021-01-28T10:44:18.934+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1805688 ns, Reaching safepoint: 194376 ns, At safepoint: 39838 ns, Total: 234214 ns +[2021-01-28T10:44:18.935+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 323580 ns, Reaching safepoint: 92440 ns, At safepoint: 61167 ns, Total: 153607 ns +[2021-01-28T10:44:18.935+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 134092 ns, Reaching safepoint: 137344 ns, At safepoint: 39819 ns, Total: 177163 ns +[2021-01-28T10:44:18.936+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 174763 ns, Reaching safepoint: 387447 ns, At safepoint: 36997 ns, Total: 424444 ns +[2021-01-28T10:44:18.936+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 159524 ns, Reaching safepoint: 316306 ns, At safepoint: 33499 ns, Total: 349805 ns +[2021-01-28T10:44:18.937+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 164059 ns, Reaching safepoint: 142420 ns, At safepoint: 40926 ns, Total: 183346 ns +[2021-01-28T10:44:18.937+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 168355 ns, Reaching safepoint: 365650 ns, At safepoint: 38549 ns, Total: 404199 ns +[2021-01-28T10:44:18.938+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 413602 ns, Reaching safepoint: 207968 ns, At safepoint: 34729 ns, Total: 242697 ns +[2021-01-28T10:44:18.938+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 157822 ns, Reaching safepoint: 74332 ns, At safepoint: 33431 ns, Total: 107763 ns +[2021-01-28T10:44:18.939+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 124055 ns, Reaching safepoint: 120547 ns, At safepoint: 67368 ns, Total: 187915 ns +[2021-01-28T10:44:18.939+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 251423 ns, Reaching safepoint: 122316 ns, At safepoint: 18982 ns, Total: 141298 ns +[2021-01-28T10:44:18.939+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 116748 ns, Reaching safepoint: 201511 ns, At safepoint: 33994 ns, Total: 235505 ns +[2021-01-28T10:44:18.940+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 115936 ns, Reaching safepoint: 74588 ns, At safepoint: 90435 ns, Total: 165023 ns +[2021-01-28T10:44:18.940+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 163559 ns, Reaching safepoint: 75433 ns, At safepoint: 34916 ns, Total: 110349 ns +[2021-01-28T10:44:18.941+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 459366 ns, Reaching safepoint: 246830 ns, At safepoint: 36141 ns, Total: 282971 ns +[2021-01-28T10:44:18.941+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 136671 ns, Reaching safepoint: 198755 ns, At safepoint: 33598 ns, Total: 232353 ns +[2021-01-28T10:44:18.941+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 130845 ns, Reaching safepoint: 243806 ns, At safepoint: 13373 ns, Total: 257179 ns +[2021-01-28T10:44:18.942+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 123732 ns, Reaching safepoint: 113440 ns, At safepoint: 11156 ns, Total: 124596 ns +[2021-01-28T10:44:18.942+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 94751 ns, Reaching safepoint: 72054 ns, At safepoint: 9168 ns, Total: 81222 ns +[2021-01-28T10:44:18.942+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 255254 ns, Reaching safepoint: 157230 ns, At safepoint: 13137 ns, Total: 170367 ns +[2021-01-28T10:44:18.943+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 224950 ns, Reaching safepoint: 226083 ns, At safepoint: 13300 ns, Total: 239383 ns +[2021-01-28T10:44:18.943+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 251272 ns, Reaching safepoint: 93934 ns, At safepoint: 10774 ns, Total: 104708 ns +[2021-01-28T10:44:18.943+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 98054 ns, Reaching safepoint: 91004 ns, At safepoint: 10210 ns, Total: 101214 ns +[2021-01-28T10:44:18.943+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 124243 ns, Reaching safepoint: 90857 ns, At safepoint: 10478 ns, Total: 101335 ns +[2021-01-28T10:44:18.944+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 310207 ns, Reaching safepoint: 91851 ns, At safepoint: 10692 ns, Total: 102543 ns +[2021-01-28T10:44:18.944+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 95068 ns, Reaching safepoint: 165650 ns, At safepoint: 13215 ns, Total: 178865 ns +[2021-01-28T10:44:18.944+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 131039 ns, Reaching safepoint: 90639 ns, At safepoint: 9840 ns, Total: 100479 ns +[2021-01-28T10:44:18.945+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 124993 ns, Reaching safepoint: 150423 ns, At safepoint: 10126 ns, Total: 160549 ns +[2021-01-28T10:44:18.945+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 134215 ns, Reaching safepoint: 90716 ns, At safepoint: 9976 ns, Total: 100692 ns +[2021-01-28T10:44:18.945+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 130696 ns, Reaching safepoint: 90678 ns, At safepoint: 10603 ns, Total: 101281 ns +[2021-01-28T10:44:18.945+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 235660 ns, Reaching safepoint: 90736 ns, At safepoint: 10492 ns, Total: 101228 ns +[2021-01-28T10:44:18.946+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 132689 ns, Reaching safepoint: 90909 ns, At safepoint: 10500 ns, Total: 101409 ns +[2021-01-28T10:44:18.946+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 104450 ns, Reaching safepoint: 91428 ns, At safepoint: 9740 ns, Total: 101168 ns +[2021-01-28T10:44:18.946+0000][1][safepoint ] Safepoint "BulkRevokeBias", Time since last: 130689 ns, Reaching safepoint: 90513 ns, At safepoint: 380240 ns, Total: 470753 ns +[2021-01-28T10:44:18.977+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 30597649 ns, Reaching safepoint: 166902 ns, At safepoint: 61188 ns, Total: 228090 ns +[2021-01-28T10:44:18.978+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 162792 ns, Reaching safepoint: 154412 ns, At safepoint: 26427 ns, Total: 180839 ns +[2021-01-28T10:44:19.031+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 53234679 ns, Reaching safepoint: 326815 ns, At safepoint: 38657 ns, Total: 365472 ns +[2021-01-28T10:44:19.032+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 619927 ns, Reaching safepoint: 290403 ns, At safepoint: 59609 ns, Total: 350012 ns +[2021-01-28T10:44:19.033+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1043487 ns, Reaching safepoint: 122574 ns, At safepoint: 11401 ns, Total: 133975 ns +[2021-01-28T10:44:19.042+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 8369938 ns, Reaching safepoint: 352440 ns, At safepoint: 141433 ns, Total: 493873 ns +[2021-01-28T10:44:19.045+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2103105 ns, Reaching safepoint: 279823 ns, At safepoint: 85740 ns, Total: 365563 ns +[2021-01-28T10:44:19.046+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1350680 ns, Reaching safepoint: 278356 ns, At safepoint: 61350 ns, Total: 339706 ns +[2021-01-28T10:44:19.047+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 237293 ns, Reaching safepoint: 225030 ns, At safepoint: 78002 ns, Total: 303032 ns +[2021-01-28T10:44:19.048+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 349862 ns, Reaching safepoint: 239877 ns, At safepoint: 79545 ns, Total: 319422 ns +[2021-01-28T10:44:19.048+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 527438 ns, Reaching safepoint: 259343 ns, At safepoint: 73494 ns, Total: 332837 ns +[2021-01-28T10:44:19.049+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 356276 ns, Reaching safepoint: 266482 ns, At safepoint: 74652 ns, Total: 341134 ns +[2021-01-28T10:44:19.050+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 42400 ns, Reaching safepoint: 260772 ns, At safepoint: 105421 ns, Total: 366193 ns +[2021-01-28T10:44:19.050+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 48513 ns, Reaching safepoint: 275935 ns, At safepoint: 104164 ns, Total: 380099 ns +[2021-01-28T10:44:19.058+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 7918496 ns, Reaching safepoint: 246767 ns, At safepoint: 70340 ns, Total: 317107 ns +[2021-01-28T10:44:19.072+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 13906006 ns, Reaching safepoint: 261807 ns, At safepoint: 53502 ns, Total: 315309 ns +[2021-01-28T10:44:19.094+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 20717867 ns, Reaching safepoint: 446546 ns, At safepoint: 76614 ns, Total: 523160 ns +[2021-01-28T10:44:19.135+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 40489145 ns, Reaching safepoint: 483466 ns, At safepoint: 44863 ns, Total: 528329 ns +[2021-01-28T10:44:19.142+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 6887029 ns, Reaching safepoint: 261471 ns, At safepoint: 44670 ns, Total: 306141 ns +[2021-01-28T10:44:19.143+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 296179 ns, Reaching safepoint: 222401 ns, At safepoint: 144409 ns, Total: 366810 ns +[2021-01-28T10:44:19.156+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 13582662 ns, Reaching safepoint: 126365 ns, At safepoint: 27405 ns, Total: 153770 ns +[2021-01-28T10:44:19.157+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 401393 ns, Reaching safepoint: 273014 ns, At safepoint: 39012 ns, Total: 312026 ns +[2021-01-28T10:44:19.160+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2859868 ns, Reaching safepoint: 105860 ns, At safepoint: 55653 ns, Total: 161513 ns +[2021-01-28T10:44:19.161+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 572605 ns, Reaching safepoint: 140456 ns, At safepoint: 55084 ns, Total: 195540 ns +[2021-01-28T10:44:19.162+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 572663 ns, Reaching safepoint: 302257 ns, At safepoint: 38469 ns, Total: 340726 ns +[2021-01-28T10:44:19.177+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 14628185 ns, Reaching safepoint: 346957 ns, At safepoint: 64717 ns, Total: 411674 ns +[2021-01-28T10:44:19.186+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 8667498 ns, Reaching safepoint: 189677 ns, At safepoint: 4889 ns, Total: 194566 ns +[2021-01-28T10:44:19.205+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 19367067 ns, Reaching safepoint: 122089 ns, At safepoint: 17158 ns, Total: 139247 ns +[2021-01-28T10:44:19.226+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 19997261 ns, Reaching safepoint: 283751 ns, At safepoint: 138164 ns, Total: 421915 ns +[2021-01-28T10:44:19.266+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 39837120 ns, Reaching safepoint: 305322 ns, At safepoint: 37671 ns, Total: 342993 ns +[2021-01-28T10:44:19.266+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 69606 ns, Reaching safepoint: 209871 ns, At safepoint: 56825 ns, Total: 266696 ns +[2021-01-28T10:44:19.267+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 66973 ns, Reaching safepoint: 490098 ns, At safepoint: 56358 ns, Total: 546456 ns +[2021-01-28T10:44:19.267+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 57849 ns, Reaching safepoint: 224340 ns, At safepoint: 53886 ns, Total: 278226 ns +[2021-01-28T10:44:19.267+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 40880 ns, Reaching safepoint: 241257 ns, At safepoint: 53081 ns, Total: 294338 ns +[2021-01-28T10:44:19.269+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 39207 ns, Reaching safepoint: 1062941 ns, At safepoint: 97261 ns, Total: 1160202 ns +[2021-01-28T10:44:19.269+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 58091 ns, Reaching safepoint: 226069 ns, At safepoint: 57041 ns, Total: 283110 ns +[2021-01-28T10:44:19.269+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 44218 ns, Reaching safepoint: 191498 ns, At safepoint: 53978 ns, Total: 245476 ns +[2021-01-28T10:44:19.270+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 43445 ns, Reaching safepoint: 186267 ns, At safepoint: 101235 ns, Total: 287502 ns +[2021-01-28T10:44:19.270+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 313736 ns, Reaching safepoint: 249630 ns, At safepoint: 36397 ns, Total: 286027 ns +[2021-01-28T10:44:19.270+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 43789 ns, Reaching safepoint: 227481 ns, At safepoint: 37185 ns, Total: 264666 ns +[2021-01-28T10:44:19.271+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 41431 ns, Reaching safepoint: 111741 ns, At safepoint: 31587 ns, Total: 143328 ns +[2021-01-28T10:44:19.271+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 39735 ns, Reaching safepoint: 227992 ns, At safepoint: 124968 ns, Total: 352960 ns +[2021-01-28T10:44:19.272+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 294849 ns, Reaching safepoint: 236424 ns, At safepoint: 55994 ns, Total: 292418 ns +[2021-01-28T10:44:19.272+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 48689 ns, Reaching safepoint: 208799 ns, At safepoint: 59811 ns, Total: 268610 ns +[2021-01-28T10:44:19.272+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 200247 ns, Reaching safepoint: 200828 ns, At safepoint: 35207 ns, Total: 236035 ns +[2021-01-28T10:44:19.273+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 46718 ns, Reaching safepoint: 277092 ns, At safepoint: 73573 ns, Total: 350665 ns +[2021-01-28T10:44:19.273+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 47334 ns, Reaching safepoint: 261923 ns, At safepoint: 65069 ns, Total: 326992 ns +[2021-01-28T10:44:19.274+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 57077 ns, Reaching safepoint: 280346 ns, At safepoint: 108958 ns, Total: 389304 ns +[2021-01-28T10:44:19.274+0000][1][safepoint ] Safepoint "BulkRevokeBias", Time since last: 50538 ns, Reaching safepoint: 219642 ns, At safepoint: 364509 ns, Total: 584151 ns +[2021-01-28T10:44:19.348+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 73794508 ns, Reaching safepoint: 319796 ns, At safepoint: 49140 ns, Total: 368936 ns +[2021-01-28T10:44:19.350+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1120580 ns, Reaching safepoint: 413744 ns, At safepoint: 26110 ns, Total: 439854 ns +[2021-01-28T10:44:19.369+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 18839349 ns, Reaching safepoint: 449551 ns, At safepoint: 27701 ns, Total: 477252 ns +[2021-01-28T10:44:19.370+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 293975 ns, Reaching safepoint: 392802 ns, At safepoint: 19704 ns, Total: 412506 ns +[2021-01-28T10:44:19.397+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 27032611 ns, Reaching safepoint: 352159 ns, At safepoint: 9200 ns, Total: 361359 ns +[2021-01-28T10:44:19.408+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 10254070 ns, Reaching safepoint: 323542 ns, At safepoint: 25482 ns, Total: 349024 ns +[2021-01-28T10:44:19.411+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2860624 ns, Reaching safepoint: 363737 ns, At safepoint: 25889 ns, Total: 389626 ns +[2021-01-28T10:44:19.416+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 4730310 ns, Reaching safepoint: 454349 ns, At safepoint: 25682 ns, Total: 480031 ns +[2021-01-28T10:44:19.422+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 5501653 ns, Reaching safepoint: 344072 ns, At safepoint: 26109 ns, Total: 370181 ns +[2021-01-28T10:44:19.429+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 5986328 ns, Reaching safepoint: 430051 ns, At safepoint: 59726 ns, Total: 489777 ns +[2021-01-28T10:44:19.429+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 289564 ns, Reaching safepoint: 268900 ns, At safepoint: 67672 ns, Total: 336572 ns +[2021-01-28T10:44:19.431+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 796703 ns, Reaching safepoint: 301797 ns, At safepoint: 22036 ns, Total: 323833 ns +[2021-01-28T10:44:19.441+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 10363354 ns, Reaching safepoint: 388259 ns, At safepoint: 195390 ns, Total: 583649 ns +[2021-01-28T10:44:19.452+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 9227031 ns, Reaching safepoint: 767633 ns, At safepoint: 124789 ns, Total: 892422 ns +[2021-01-28T10:44:19.462+0000][1][safepoint ] Safepoint "BulkRevokeBias", Time since last: 9446074 ns, Reaching safepoint: 341864 ns, At safepoint: 387939 ns, Total: 729803 ns +[2021-01-28T10:44:19.462+0000][1][safepoint ] Safepoint "BulkRevokeBias", Time since last: 78631 ns, Reaching safepoint: 308254 ns, At safepoint: 320935 ns, Total: 629189 ns +[2021-01-28T10:44:19.490+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 27356398 ns, Reaching safepoint: 199440 ns, At safepoint: 75434 ns, Total: 274874 ns +[2021-01-28T10:44:19.507+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 16762874 ns, Reaching safepoint: 273354 ns, At safepoint: 88559 ns, Total: 361913 ns +[2021-01-28T10:44:19.519+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 11717501 ns, Reaching safepoint: 241172 ns, At safepoint: 99740 ns, Total: 340912 ns +[2021-01-28T10:44:19.551+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 31356125 ns, Reaching safepoint: 348452 ns, At safepoint: 60371 ns, Total: 408823 ns +[2021-01-28T10:44:19.557+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 5797783 ns, Reaching safepoint: 499297 ns, At safepoint: 89304 ns, Total: 588601 ns +[2021-01-28T10:44:19.565+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 6798223 ns, Reaching safepoint: 346314 ns, At safepoint: 62389 ns, Total: 408703 ns +[2021-01-28T10:44:19.567+0000][1][safepoint ] Safepoint "BulkRevokeBias", Time since last: 1776154 ns, Reaching safepoint: 615099 ns, At safepoint: 401816 ns, Total: 1016915 ns +[2021-01-28T10:44:19.590+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 22067741 ns, Reaching safepoint: 626655 ns, At safepoint: 76679 ns, Total: 703334 ns +[2021-01-28T10:44:19.592+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 482623 ns, Reaching safepoint: 1091131 ns, At safepoint: 75970 ns, Total: 1167101 ns +[2021-01-28T10:44:19.601+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 8658049 ns, Reaching safepoint: 340871 ns, At safepoint: 165888 ns, Total: 506759 ns +[2021-01-28T10:44:19.603+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1559527 ns, Reaching safepoint: 345917 ns, At safepoint: 86068 ns, Total: 431985 ns +[2021-01-28T10:44:19.606+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2587738 ns, Reaching safepoint: 265040 ns, At safepoint: 86201 ns, Total: 351241 ns +[2021-01-28T10:44:19.609+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2338548 ns, Reaching safepoint: 631349 ns, At safepoint: 71542 ns, Total: 702891 ns +[2021-01-28T10:44:19.637+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 27063439 ns, Reaching safepoint: 440009 ns, At safepoint: 141690 ns, Total: 581699 ns +[2021-01-28T10:44:19.660+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 23442636 ns, Reaching safepoint: 204449 ns, At safepoint: 133227 ns, Total: 337676 ns +[2021-01-28T10:44:19.661+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 335314 ns, Reaching safepoint: 252561 ns, At safepoint: 36394 ns, Total: 288955 ns +[2021-01-28T10:44:19.678+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 16459073 ns, Reaching safepoint: 226302 ns, At safepoint: 16951 ns, Total: 243253 ns +[2021-01-28T10:44:19.678+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 180607 ns, Reaching safepoint: 142205 ns, At safepoint: 10463 ns, Total: 152668 ns +[2021-01-28T10:44:19.680+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2208992 ns, Reaching safepoint: 184537 ns, At safepoint: 13442 ns, Total: 197979 ns +[2021-01-28T10:44:19.681+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 153638 ns, Reaching safepoint: 167303 ns, At safepoint: 10838 ns, Total: 178141 ns +[2021-01-28T10:44:19.682+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1296700 ns, Reaching safepoint: 172198 ns, At safepoint: 4879 ns, Total: 177077 ns +[2021-01-28T10:44:19.683+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 400214 ns, Reaching safepoint: 170849 ns, At safepoint: 4467 ns, Total: 175316 ns +[2021-01-28T10:44:19.686+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 3144350 ns, Reaching safepoint: 311966 ns, At safepoint: 34260 ns, Total: 346226 ns +[2021-01-28T10:44:19.714+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 27240720 ns, Reaching safepoint: 263212 ns, At safepoint: 46552 ns, Total: 309764 ns +[2021-01-28T10:44:19.715+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 430244 ns, Reaching safepoint: 303082 ns, At safepoint: 58706 ns, Total: 361788 ns +[2021-01-28T10:44:19.719+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 3807081 ns, Reaching safepoint: 240432 ns, At safepoint: 39364 ns, Total: 279796 ns +[2021-01-28T10:44:19.719+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 237026 ns, Reaching safepoint: 339420 ns, At safepoint: 11817 ns, Total: 351237 ns +[2021-01-28T10:44:19.720+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 319581 ns, Reaching safepoint: 252647 ns, At safepoint: 11610 ns, Total: 264257 ns +[2021-01-28T10:44:19.723+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2720028 ns, Reaching safepoint: 247998 ns, At safepoint: 18795 ns, Total: 266793 ns +[2021-01-28T10:44:19.724+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 557750 ns, Reaching safepoint: 293195 ns, At safepoint: 76937 ns, Total: 370132 ns +[2021-01-28T10:44:19.726+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1981369 ns, Reaching safepoint: 273568 ns, At safepoint: 60589 ns, Total: 334157 ns +[2021-01-28T10:44:19.950+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 223874220 ns, Reaching safepoint: 206422 ns, At safepoint: 22046 ns, Total: 228468 ns +[2021-01-28T10:44:19.951+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 519060 ns, Reaching safepoint: 148569 ns, At safepoint: 35410 ns, Total: 183979 ns +[2021-01-28T10:44:19.952+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 350504 ns, Reaching safepoint: 192055 ns, At safepoint: 17503 ns, Total: 209558 ns +[2021-01-28T10:44:19.952+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 604852 ns, Reaching safepoint: 212099 ns, At safepoint: 23006 ns, Total: 235105 ns +[2021-01-28T10:44:19.965+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 12654366 ns, Reaching safepoint: 349588 ns, At safepoint: 49491 ns, Total: 399079 ns +[2021-01-28T10:44:19.995+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 29348839 ns, Reaching safepoint: 350247 ns, At safepoint: 19770 ns, Total: 370017 ns +[2021-01-28T10:44:19.997+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2039036 ns, Reaching safepoint: 244357 ns, At safepoint: 16540 ns, Total: 260897 ns +[2021-01-28T10:44:19.998+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 383973 ns, Reaching safepoint: 291674 ns, At safepoint: 14023 ns, Total: 305697 ns +[2021-01-28T10:44:19.999+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 116965 ns, Reaching safepoint: 408638 ns, At safepoint: 19100 ns, Total: 427738 ns +[2021-01-28T10:44:20.036+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 37391705 ns, Reaching safepoint: 133895 ns, At safepoint: 6880 ns, Total: 140775 ns +[2021-01-28T10:44:20.039+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2997591 ns, Reaching safepoint: 158700 ns, At safepoint: 46703 ns, Total: 205403 ns +[2021-01-28T10:44:20.040+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 416028 ns, Reaching safepoint: 106318 ns, At safepoint: 42621 ns, Total: 148939 ns +[2021-01-28T10:44:20.041+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 977491 ns, Reaching safepoint: 220339 ns, At safepoint: 57601 ns, Total: 277940 ns +[2021-01-28T10:44:20.047+0000][1][safepoint ] Safepoint "Deoptimize", Time since last: 5185599 ns, Reaching safepoint: 250411 ns, At safepoint: 700613 ns, Total: 951024 ns +[2021-01-28T10:44:20.078+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 30041071 ns, Reaching safepoint: 215833 ns, At safepoint: 17756 ns, Total: 233589 ns +[2021-01-28T10:44:20.082+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 4069331 ns, Reaching safepoint: 380859 ns, At safepoint: 28266 ns, Total: 409125 ns +[2021-01-28T10:44:20.083+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 293766 ns, Reaching safepoint: 361265 ns, At safepoint: 15684 ns, Total: 376949 ns +[2021-01-28T10:44:20.083+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 269161 ns, Reaching safepoint: 110258 ns, At safepoint: 12718 ns, Total: 122976 ns +[2021-01-28T10:44:20.084+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 232155 ns, Reaching safepoint: 154427 ns, At safepoint: 13971 ns, Total: 168398 ns +[2021-01-28T10:44:20.084+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 212108 ns, Reaching safepoint: 90974 ns, At safepoint: 12388 ns, Total: 103362 ns +[2021-01-28T10:44:20.085+0000][1][safepoint ] Safepoint "BulkRevokeBias", Time since last: 238991 ns, Reaching safepoint: 87297 ns, At safepoint: 304587 ns, Total: 391884 ns +[2021-01-28T10:44:20.085+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 217663 ns, Reaching safepoint: 86089 ns, At safepoint: 12170 ns, Total: 98259 ns +[2021-01-28T10:44:20.085+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 192969 ns, Reaching safepoint: 93218 ns, At safepoint: 11650 ns, Total: 104868 ns +[2021-01-28T10:44:20.497+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 411614841 ns, Reaching safepoint: 216620 ns, At safepoint: 26023 ns, Total: 242643 ns +[2021-01-28T10:44:20.498+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 729538 ns, Reaching safepoint: 451671 ns, At safepoint: 67290 ns, Total: 518961 ns +[2021-01-28T10:44:20.499+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 428203 ns, Reaching safepoint: 316992 ns, At safepoint: 22123 ns, Total: 339115 ns +[2021-01-28T10:44:20.500+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 915818 ns, Reaching safepoint: 144053 ns, At safepoint: 19058 ns, Total: 163111 ns +[2021-01-28T10:44:20.509+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 8681405 ns, Reaching safepoint: 198276 ns, At safepoint: 17928 ns, Total: 216204 ns +[2021-01-28T10:44:20.510+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 689327 ns, Reaching safepoint: 389830 ns, At safepoint: 19881 ns, Total: 409711 ns +[2021-01-28T10:44:20.511+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 288911 ns, Reaching safepoint: 248784 ns, At safepoint: 18858 ns, Total: 267642 ns +[2021-01-28T10:44:20.511+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 365072 ns, Reaching safepoint: 263664 ns, At safepoint: 16435 ns, Total: 280099 ns +[2021-01-28T10:44:20.519+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 6783733 ns, Reaching safepoint: 546584 ns, At safepoint: 58546 ns, Total: 605130 ns +[2021-01-28T10:44:20.519+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 369289 ns, Reaching safepoint: 363824 ns, At safepoint: 51625 ns, Total: 415449 ns +[2021-01-28T10:44:20.521+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1183518 ns, Reaching safepoint: 356835 ns, At safepoint: 67002 ns, Total: 423837 ns +[2021-01-28T10:44:20.524+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2998495 ns, Reaching safepoint: 217361 ns, At safepoint: 57898 ns, Total: 275259 ns +[2021-01-28T10:44:20.526+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1050833 ns, Reaching safepoint: 328271 ns, At safepoint: 17012 ns, Total: 345283 ns +[2021-01-28T10:44:20.526+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 265094 ns, Reaching safepoint: 121922 ns, At safepoint: 12176 ns, Total: 134098 ns +[2021-01-28T10:44:20.527+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 210845 ns, Reaching safepoint: 514114 ns, At safepoint: 13813 ns, Total: 527927 ns +[2021-01-28T10:44:20.527+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 198690 ns, Reaching safepoint: 220814 ns, At safepoint: 11307 ns, Total: 232121 ns +[2021-01-28T10:44:21.185+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 657224430 ns, Reaching safepoint: 610221 ns, At safepoint: 145885 ns, Total: 756106 ns +[2021-01-28T10:44:21.207+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 20799020 ns, Reaching safepoint: 351695 ns, At safepoint: 279358 ns, Total: 631053 ns +[2021-01-28T10:44:21.207+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 290961 ns, Reaching safepoint: 277673 ns, At safepoint: 142449 ns, Total: 420122 ns +[2021-01-28T10:44:21.208+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 71228 ns, Reaching safepoint: 167287 ns, At safepoint: 135416 ns, Total: 302703 ns +[2021-01-28T10:44:21.208+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 125498 ns, Reaching safepoint: 307101 ns, At safepoint: 145508 ns, Total: 452609 ns +[2021-01-28T10:44:21.209+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 66954 ns, Reaching safepoint: 251541 ns, At safepoint: 124867 ns, Total: 376408 ns +[2021-01-28T10:44:21.210+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 227182 ns, Reaching safepoint: 347846 ns, At safepoint: 215175 ns, Total: 563021 ns +[2021-01-28T10:44:21.216+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 5510022 ns, Reaching safepoint: 487149 ns, At safepoint: 38487 ns, Total: 525636 ns +[2021-01-28T10:44:21.219+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 3255999 ns, Reaching safepoint: 321473 ns, At safepoint: 55859 ns, Total: 377332 ns +[2021-01-28T10:44:21.222+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2705615 ns, Reaching safepoint: 177451 ns, At safepoint: 98461 ns, Total: 275912 ns +[2021-01-28T10:44:21.223+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 197430 ns, Reaching safepoint: 269789 ns, At safepoint: 44510 ns, Total: 314299 ns +[2021-01-28T10:44:21.224+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 278446 ns, Reaching safepoint: 482231 ns, At safepoint: 69166 ns, Total: 551397 ns +[2021-01-28T10:44:21.224+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 223331 ns, Reaching safepoint: 207008 ns, At safepoint: 75091 ns, Total: 282099 ns +[2021-01-28T10:44:21.225+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 258162 ns, Reaching safepoint: 271415 ns, At safepoint: 69314 ns, Total: 340729 ns +[2021-01-28T10:44:21.225+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 144849 ns, Reaching safepoint: 243088 ns, At safepoint: 77651 ns, Total: 320739 ns +[2021-01-28T10:44:21.226+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 300569 ns, Reaching safepoint: 120664 ns, At safepoint: 45415 ns, Total: 166079 ns +[2021-01-28T10:44:21.226+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 276103 ns, Reaching safepoint: 219250 ns, At safepoint: 71682 ns, Total: 290932 ns +[2021-01-28T10:44:21.227+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 312927 ns, Reaching safepoint: 475498 ns, At safepoint: 51530 ns, Total: 527028 ns +[2021-01-28T10:44:21.228+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 205678 ns, Reaching safepoint: 159395 ns, At safepoint: 131789 ns, Total: 291184 ns +[2021-01-28T10:44:21.228+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 284593 ns, Reaching safepoint: 99953 ns, At safepoint: 42501 ns, Total: 142454 ns +[2021-01-28T10:44:21.228+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 153797 ns, Reaching safepoint: 86788 ns, At safepoint: 38336 ns, Total: 125124 ns +[2021-01-28T10:44:21.229+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 195925 ns, Reaching safepoint: 179551 ns, At safepoint: 63928 ns, Total: 243479 ns +[2021-01-28T10:44:21.229+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 142991 ns, Reaching safepoint: 219703 ns, At safepoint: 69332 ns, Total: 289035 ns +[2021-01-28T10:44:21.230+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 223503 ns, Reaching safepoint: 375674 ns, At safepoint: 46109 ns, Total: 421783 ns +[2021-01-28T10:44:21.230+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 157781 ns, Reaching safepoint: 180801 ns, At safepoint: 43314 ns, Total: 224115 ns +[2021-01-28T10:44:22.235+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1004397551 ns, Reaching safepoint: 289831 ns, At safepoint: 6331 ns, Total: 296162 ns +[2021-01-28T10:44:22.931+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 696404980 ns, Reaching safepoint: 152296 ns, At safepoint: 22208 ns, Total: 174504 ns +[2021-01-28T10:44:22.932+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 255583 ns, Reaching safepoint: 268952 ns, At safepoint: 44515 ns, Total: 313467 ns +[2021-01-28T10:44:22.932+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 62905 ns, Reaching safepoint: 125787 ns, At safepoint: 42655 ns, Total: 168442 ns +[2021-01-28T10:44:22.932+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 61530 ns, Reaching safepoint: 124059 ns, At safepoint: 40865 ns, Total: 164924 ns +[2021-01-28T10:44:22.933+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 126613 ns, Reaching safepoint: 140551 ns, At safepoint: 41947 ns, Total: 182498 ns +[2021-01-28T10:44:22.933+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 62016 ns, Reaching safepoint: 250761 ns, At safepoint: 41884 ns, Total: 292645 ns +[2021-01-28T10:44:23.935+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1001055987 ns, Reaching safepoint: 538367 ns, At safepoint: 8623 ns, Total: 546990 ns +[2021-01-28T10:44:24.935+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000243555 ns, Reaching safepoint: 151332 ns, At safepoint: 2946 ns, Total: 154278 ns +[2021-01-28T10:44:25.936+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000210459 ns, Reaching safepoint: 224122 ns, At safepoint: 7651 ns, Total: 231773 ns +[2021-01-28T10:44:26.936+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000349485 ns, Reaching safepoint: 323934 ns, At safepoint: 34725 ns, Total: 358659 ns +[2021-01-28T10:44:27.937+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000311580 ns, Reaching safepoint: 198026 ns, At safepoint: 3476 ns, Total: 201502 ns +[2021-01-28T10:44:28.937+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000308243 ns, Reaching safepoint: 272648 ns, At safepoint: 4043 ns, Total: 276691 ns +[2021-01-28T10:44:29.291+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 353003766 ns, Reaching safepoint: 165653 ns, At safepoint: 41610 ns, Total: 207263 ns +[2021-01-28T10:44:29.291+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 593942 ns, Reaching safepoint: 146475 ns, At safepoint: 37768 ns, Total: 184243 ns +[2021-01-28T10:44:29.302+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 10323357 ns, Reaching safepoint: 384102 ns, At safepoint: 45512 ns, Total: 429614 ns +[2021-01-28T10:44:30.303+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000417800 ns, Reaching safepoint: 264070 ns, At safepoint: 31330 ns, Total: 295400 ns +[2021-01-28T10:44:31.303+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000293311 ns, Reaching safepoint: 168648 ns, At safepoint: 3313 ns, Total: 171961 ns +[2021-01-28T10:44:32.304+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000203568 ns, Reaching safepoint: 159554 ns, At safepoint: 3514 ns, Total: 163068 ns +[2021-01-28T10:44:33.304+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000240298 ns, Reaching safepoint: 255199 ns, At safepoint: 3978 ns, Total: 259177 ns +[2021-01-28T10:44:34.305+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000263157 ns, Reaching safepoint: 290348 ns, At safepoint: 12810 ns, Total: 303158 ns +[2021-01-28T10:44:35.306+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1001059130 ns, Reaching safepoint: 361968 ns, At safepoint: 23447 ns, Total: 385415 ns +[2021-01-28T10:44:36.188+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 881158638 ns, Reaching safepoint: 294578 ns, At safepoint: 119471 ns, Total: 414049 ns +[2021-01-28T10:44:36.188+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 288942 ns, Reaching safepoint: 308409 ns, At safepoint: 104268 ns, Total: 412677 ns +[2021-01-28T10:44:36.190+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 463211 ns, Reaching safepoint: 509895 ns, At safepoint: 200205 ns, Total: 710100 ns +[2021-01-28T10:44:36.191+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 541416 ns, Reaching safepoint: 282932 ns, At safepoint: 158409 ns, Total: 441341 ns +[2021-01-28T10:44:36.192+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 427074 ns, Reaching safepoint: 707301 ns, At safepoint: 96350 ns, Total: 803651 ns +[2021-01-28T10:44:36.193+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 274241 ns, Reaching safepoint: 632328 ns, At safepoint: 79319 ns, Total: 711647 ns +[2021-01-28T10:44:36.194+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 536663 ns, Reaching safepoint: 368329 ns, At safepoint: 181837 ns, Total: 550166 ns +[2021-01-28T10:44:36.197+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 893685 ns, Reaching safepoint: 2355001 ns, At safepoint: 86687 ns, Total: 2441688 ns +[2021-01-28T10:44:37.198+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000186095 ns, Reaching safepoint: 235780 ns, At safepoint: 5353 ns, Total: 241133 ns +[2021-01-28T10:44:38.198+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000325658 ns, Reaching safepoint: 327960 ns, At safepoint: 10686 ns, Total: 338646 ns +[2021-01-28T10:44:39.199+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000363884 ns, Reaching safepoint: 430827 ns, At safepoint: 18047 ns, Total: 448874 ns +[2021-01-28T10:44:40.201+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1001252944 ns, Reaching safepoint: 599887 ns, At safepoint: 9209 ns, Total: 609096 ns +[2021-01-28T10:44:41.202+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000185328 ns, Reaching safepoint: 739992 ns, At safepoint: 88312 ns, Total: 828304 ns +[2021-01-28T10:44:42.196+0000][1][safepoint ] Safepoint "BulkRevokeBias", Time since last: 992774347 ns, Reaching safepoint: 280648 ns, At safepoint: 649980 ns, Total: 930628 ns +[2021-01-28T10:44:42.235+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 39010889 ns, Reaching safepoint: 588102 ns, At safepoint: 50413 ns, Total: 638515 ns +[2021-01-28T10:44:42.243+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 7328181 ns, Reaching safepoint: 551014 ns, At safepoint: 47589 ns, Total: 598603 ns +[2021-01-28T10:44:42.245+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1287243 ns, Reaching safepoint: 326838 ns, At safepoint: 46777 ns, Total: 373615 ns +[2021-01-28T10:44:42.249+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 3175751 ns, Reaching safepoint: 378894 ns, At safepoint: 53380 ns, Total: 432274 ns +[2021-01-28T10:44:42.252+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2611095 ns, Reaching safepoint: 512703 ns, At safepoint: 84553 ns, Total: 597256 ns +[2021-01-28T10:44:42.254+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 402927 ns, Reaching safepoint: 1459451 ns, At safepoint: 234945 ns, Total: 1694396 ns +[2021-01-28T10:44:42.255+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 424088 ns, Reaching safepoint: 363705 ns, At safepoint: 22057 ns, Total: 385762 ns +[2021-01-28T10:44:42.255+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 305395 ns, Reaching safepoint: 318486 ns, At safepoint: 19022 ns, Total: 337508 ns +[2021-01-28T10:44:42.260+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 4552921 ns, Reaching safepoint: 500377 ns, At safepoint: 46430 ns, Total: 546807 ns +[2021-01-28T10:44:42.262+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 822917 ns, Reaching safepoint: 315657 ns, At safepoint: 85282 ns, Total: 400939 ns +[2021-01-28T10:44:42.262+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 259547 ns, Reaching safepoint: 341286 ns, At safepoint: 99394 ns, Total: 440680 ns +[2021-01-28T10:44:42.547+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 283989931 ns, Reaching safepoint: 303781 ns, At safepoint: 79952 ns, Total: 383733 ns +[2021-01-28T10:44:42.547+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 191483 ns, Reaching safepoint: 218468 ns, At safepoint: 47159 ns, Total: 265627 ns +[2021-01-28T10:44:42.549+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 960803 ns, Reaching safepoint: 546954 ns, At safepoint: 33875 ns, Total: 580829 ns +[2021-01-28T10:44:42.554+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 5293132 ns, Reaching safepoint: 352272 ns, At safepoint: 20950 ns, Total: 373222 ns +[2021-01-28T10:44:42.555+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 633661 ns, Reaching safepoint: 251322 ns, At safepoint: 55786 ns, Total: 307108 ns +[2021-01-28T10:44:42.556+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 291888 ns, Reaching safepoint: 300781 ns, At safepoint: 47977 ns, Total: 348758 ns +[2021-01-28T10:44:42.556+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 85976 ns, Reaching safepoint: 318886 ns, At safepoint: 43161 ns, Total: 362047 ns +[2021-01-28T10:44:42.562+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 5063569 ns, Reaching safepoint: 509085 ns, At safepoint: 81152 ns, Total: 590237 ns +[2021-01-28T10:44:42.563+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 141122 ns, Reaching safepoint: 250388 ns, At safepoint: 87064 ns, Total: 337452 ns +[2021-01-28T10:44:42.567+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 3492152 ns, Reaching safepoint: 491130 ns, At safepoint: 51159 ns, Total: 542289 ns +[2021-01-28T10:44:42.568+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 560971 ns, Reaching safepoint: 298256 ns, At safepoint: 80385 ns, Total: 378641 ns +[2021-01-28T10:44:43.568+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000291651 ns, Reaching safepoint: 280773 ns, At safepoint: 56934 ns, Total: 337707 ns +[2021-01-28T10:44:44.569+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000218328 ns, Reaching safepoint: 266866 ns, At safepoint: 11517 ns, Total: 278383 ns +[2021-01-28T10:44:45.230+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 660126977 ns, Reaching safepoint: 538990 ns, At safepoint: 83679 ns, Total: 622669 ns +[2021-01-28T10:44:45.231+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1159974 ns, Reaching safepoint: 342823 ns, At safepoint: 99966 ns, Total: 442789 ns +[2021-01-28T10:44:45.233+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1203343 ns, Reaching safepoint: 167525 ns, At safepoint: 61654 ns, Total: 229179 ns +[2021-01-28T10:44:46.233+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000325381 ns, Reaching safepoint: 361235 ns, At safepoint: 5851 ns, Total: 367086 ns +[2021-01-28T10:44:47.234+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000207808 ns, Reaching safepoint: 302521 ns, At safepoint: 6294 ns, Total: 308815 ns +[2021-01-28T10:44:48.235+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000520712 ns, Reaching safepoint: 675687 ns, At safepoint: 13392 ns, Total: 689079 ns +[2021-01-28T10:44:48.952+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 716462175 ns, Reaching safepoint: 268668 ns, At safepoint: 40266 ns, Total: 308934 ns +[2021-01-28T10:44:48.953+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 783540 ns, Reaching safepoint: 286972 ns, At safepoint: 54908 ns, Total: 341880 ns +[2021-01-28T10:44:48.954+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 242642 ns, Reaching safepoint: 276585 ns, At safepoint: 118251 ns, Total: 394836 ns +[2021-01-28T10:44:48.954+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 336310 ns, Reaching safepoint: 277979 ns, At safepoint: 84684 ns, Total: 362663 ns +[2021-01-28T10:44:48.955+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 199627 ns, Reaching safepoint: 349369 ns, At safepoint: 90762 ns, Total: 440131 ns +[2021-01-28T10:44:48.956+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 288875 ns, Reaching safepoint: 325733 ns, At safepoint: 107872 ns, Total: 433605 ns +[2021-01-28T10:44:48.956+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 230345 ns, Reaching safepoint: 315518 ns, At safepoint: 91359 ns, Total: 406877 ns +[2021-01-28T10:44:49.498+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 541091514 ns, Reaching safepoint: 352884 ns, At safepoint: 74152 ns, Total: 427036 ns +[2021-01-28T10:44:49.499+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 641064 ns, Reaching safepoint: 410600 ns, At safepoint: 49567 ns, Total: 460167 ns +[2021-01-28T10:44:49.499+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 285366 ns, Reaching safepoint: 150981 ns, At safepoint: 48985 ns, Total: 199966 ns +[2021-01-28T10:44:49.500+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 401595 ns, Reaching safepoint: 221651 ns, At safepoint: 55118 ns, Total: 276769 ns +[2021-01-28T10:44:50.501+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000771400 ns, Reaching safepoint: 366511 ns, At safepoint: 7066 ns, Total: 373577 ns +[2021-01-28T10:44:51.502+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000328971 ns, Reaching safepoint: 236256 ns, At safepoint: 3866 ns, Total: 240122 ns +[2021-01-28T10:44:52.502+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000232649 ns, Reaching safepoint: 331267 ns, At safepoint: 5874 ns, Total: 337141 ns +[2021-01-28T10:44:53.503+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000574803 ns, Reaching safepoint: 370493 ns, At safepoint: 7499 ns, Total: 377992 ns +[2021-01-28T10:44:54.110+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 606322091 ns, Reaching safepoint: 204866 ns, At safepoint: 20365 ns, Total: 225231 ns +[2021-01-28T10:44:54.110+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 388689 ns, Reaching safepoint: 201112 ns, At safepoint: 67483 ns, Total: 268595 ns +[2021-01-28T10:44:54.125+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 14148969 ns, Reaching safepoint: 397863 ns, At safepoint: 47487 ns, Total: 445350 ns +[2021-01-28T10:44:54.155+0000][1][safepoint ] Safepoint "BulkRevokeBias", Time since last: 29227096 ns, Reaching safepoint: 155060 ns, At safepoint: 384239 ns, Total: 539299 ns +[2021-01-28T10:44:54.174+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 19207189 ns, Reaching safepoint: 121617 ns, At safepoint: 66877 ns, Total: 188494 ns +[2021-01-28T10:44:54.181+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 6819102 ns, Reaching safepoint: 156248 ns, At safepoint: 17308 ns, Total: 173556 ns +[2021-01-28T10:44:54.211+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 28898042 ns, Reaching safepoint: 648213 ns, At safepoint: 87445 ns, Total: 735658 ns +[2021-01-28T10:44:54.266+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 55169753 ns, Reaching safepoint: 339564 ns, At safepoint: 38199 ns, Total: 377763 ns +[2021-01-28T10:44:54.267+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 106601 ns, Reaching safepoint: 372717 ns, At safepoint: 58169 ns, Total: 430886 ns +[2021-01-28T10:44:54.283+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 15575461 ns, Reaching safepoint: 162619 ns, At safepoint: 20152 ns, Total: 182771 ns +[2021-01-28T10:44:54.285+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2314441 ns, Reaching safepoint: 362913 ns, At safepoint: 68116 ns, Total: 431029 ns +[2021-01-28T10:44:55.286+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000391730 ns, Reaching safepoint: 374052 ns, At safepoint: 15055 ns, Total: 389107 ns +[2021-01-28T10:44:56.287+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000146595 ns, Reaching safepoint: 238331 ns, At safepoint: 5639 ns, Total: 243970 ns +[2021-01-28T10:44:57.287+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000349046 ns, Reaching safepoint: 420192 ns, At safepoint: 20310 ns, Total: 440502 ns +[2021-01-28T10:44:58.289+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000921270 ns, Reaching safepoint: 251478 ns, At safepoint: 5772 ns, Total: 257250 ns +[2021-01-28T10:44:59.289+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000449698 ns, Reaching safepoint: 234670 ns, At safepoint: 6110 ns, Total: 240780 ns +[2021-01-28T10:45:00.290+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000331624 ns, Reaching safepoint: 311912 ns, At safepoint: 5573 ns, Total: 317485 ns +[2021-01-28T10:45:01.291+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000430761 ns, Reaching safepoint: 182604 ns, At safepoint: 4057 ns, Total: 186661 ns +[2021-01-28T10:45:02.292+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000667488 ns, Reaching safepoint: 652641 ns, At safepoint: 7752 ns, Total: 660393 ns +[2021-01-28T10:45:03.293+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000965466 ns, Reaching safepoint: 466734 ns, At safepoint: 8844 ns, Total: 475578 ns +[2021-01-28T10:45:04.295+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1001288976 ns, Reaching safepoint: 648704 ns, At safepoint: 10899 ns, Total: 659603 ns +[2021-01-28T10:45:05.296+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000352669 ns, Reaching safepoint: 334674 ns, At safepoint: 5458 ns, Total: 340132 ns +[2021-01-28T10:45:05.911+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 615181027 ns, Reaching safepoint: 310667 ns, At safepoint: 20481 ns, Total: 331148 ns +[2021-01-28T10:45:05.912+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 304029 ns, Reaching safepoint: 253800 ns, At safepoint: 14118 ns, Total: 267918 ns +[2021-01-28T10:45:05.933+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 20271652 ns, Reaching safepoint: 371974 ns, At safepoint: 33569 ns, Total: 405543 ns +[2021-01-28T10:45:06.934+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000799131 ns, Reaching safepoint: 450019 ns, At safepoint: 10004 ns, Total: 460023 ns +[2021-01-28T10:45:07.935+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000310826 ns, Reaching safepoint: 262626 ns, At safepoint: 4480 ns, Total: 267106 ns +[2021-01-28T10:45:08.935+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000284324 ns, Reaching safepoint: 498187 ns, At safepoint: 24778 ns, Total: 522965 ns +[2021-01-28T10:45:09.936+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000588613 ns, Reaching safepoint: 224021 ns, At safepoint: 7162 ns, Total: 231183 ns +[2021-01-28T10:45:10.937+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000538539 ns, Reaching safepoint: 299417 ns, At safepoint: 6401 ns, Total: 305818 ns +[2021-01-28T10:45:11.938+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000658291 ns, Reaching safepoint: 160412 ns, At safepoint: 3102 ns, Total: 163514 ns +[2021-01-28T10:45:12.938+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000220517 ns, Reaching safepoint: 149033 ns, At safepoint: 3249 ns, Total: 152282 ns +[2021-01-28T10:45:13.472+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 533413738 ns, Reaching safepoint: 259971 ns, At safepoint: 22828 ns, Total: 282799 ns +[2021-01-28T10:45:13.473+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 814139 ns, Reaching safepoint: 302927 ns, At safepoint: 58890 ns, Total: 361817 ns +[2021-01-28T10:45:13.501+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 27591161 ns, Reaching safepoint: 291051 ns, At safepoint: 52718 ns, Total: 343769 ns +[2021-01-28T10:45:13.503+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1256705 ns, Reaching safepoint: 394608 ns, At safepoint: 69051 ns, Total: 463659 ns +[2021-01-28T10:45:13.510+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 6680130 ns, Reaching safepoint: 388209 ns, At safepoint: 26395 ns, Total: 414604 ns +[2021-01-28T10:45:13.516+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 5448540 ns, Reaching safepoint: 331394 ns, At safepoint: 92227 ns, Total: 423621 ns +[2021-01-28T10:45:13.518+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 2365941 ns, Reaching safepoint: 340025 ns, At safepoint: 29330 ns, Total: 369355 ns +[2021-01-28T10:45:13.520+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 865231 ns, Reaching safepoint: 264010 ns, At safepoint: 54366 ns, Total: 318376 ns +[2021-01-28T10:45:13.521+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 978160 ns, Reaching safepoint: 565038 ns, At safepoint: 100678 ns, Total: 665716 ns +[2021-01-28T10:45:13.526+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 4170013 ns, Reaching safepoint: 441456 ns, At safepoint: 44824 ns, Total: 486280 ns +[2021-01-28T10:45:13.528+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1765802 ns, Reaching safepoint: 491886 ns, At safepoint: 131612 ns, Total: 623498 ns +[2021-01-28T10:45:13.592+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 63249832 ns, Reaching safepoint: 324838 ns, At safepoint: 40543 ns, Total: 365381 ns +[2021-01-28T10:45:13.592+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 303347 ns, Reaching safepoint: 213754 ns, At safepoint: 22164 ns, Total: 235918 ns +[2021-01-28T10:45:13.594+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1257540 ns, Reaching safepoint: 409106 ns, At safepoint: 39138 ns, Total: 448244 ns +[2021-01-28T10:45:13.603+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 8109657 ns, Reaching safepoint: 562351 ns, At safepoint: 25051 ns, Total: 587402 ns +[2021-01-28T10:45:13.604+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 482967 ns, Reaching safepoint: 287664 ns, At safepoint: 51035 ns, Total: 338699 ns +[2021-01-28T10:45:13.604+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 346216 ns, Reaching safepoint: 237705 ns, At safepoint: 49659 ns, Total: 287364 ns +[2021-01-28T10:45:13.605+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 429245 ns, Reaching safepoint: 460632 ns, At safepoint: 20419 ns, Total: 481051 ns +[2021-01-28T10:45:13.614+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 8022641 ns, Reaching safepoint: 331348 ns, At safepoint: 26033 ns, Total: 357381 ns +[2021-01-28T10:45:13.614+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 359558 ns, Reaching safepoint: 362086 ns, At safepoint: 19870 ns, Total: 381956 ns +[2021-01-28T10:45:13.621+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 6341835 ns, Reaching safepoint: 535968 ns, At safepoint: 65296 ns, Total: 601264 ns +[2021-01-28T10:45:13.623+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1438224 ns, Reaching safepoint: 165812 ns, At safepoint: 75005 ns, Total: 240817 ns +[2021-01-28T10:45:14.623+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000217651 ns, Reaching safepoint: 148590 ns, At safepoint: 3538 ns, Total: 152128 ns +[2021-01-28T10:45:15.387+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 763473857 ns, Reaching safepoint: 413821 ns, At safepoint: 72782 ns, Total: 486603 ns +[2021-01-28T10:45:15.389+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 1116102 ns, Reaching safepoint: 105405 ns, At safepoint: 39896 ns, Total: 145301 ns +[2021-01-28T10:45:16.389+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000442653 ns, Reaching safepoint: 230149 ns, At safepoint: 5158 ns, Total: 235307 ns +[2021-01-28T10:45:17.390+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000301826 ns, Reaching safepoint: 231736 ns, At safepoint: 4787 ns, Total: 236523 ns +[2021-01-28T10:45:18.391+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000727985 ns, Reaching safepoint: 560503 ns, At safepoint: 9260 ns, Total: 569763 ns +[2021-01-28T10:45:19.392+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000754110 ns, Reaching safepoint: 172903 ns, At safepoint: 4518 ns, Total: 177421 ns +[2021-01-28T10:45:20.392+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000193339 ns, Reaching safepoint: 138191 ns, At safepoint: 2969 ns, Total: 141160 ns +[2021-01-28T10:45:21.393+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000506628 ns, Reaching safepoint: 208326 ns, At safepoint: 5247 ns, Total: 213573 ns +[2021-01-28T10:45:22.394+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000830799 ns, Reaching safepoint: 312058 ns, At safepoint: 8740 ns, Total: 320798 ns +[2021-01-28T10:45:23.395+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000476681 ns, Reaching safepoint: 265575 ns, At safepoint: 7357 ns, Total: 272932 ns +[2021-01-28T10:45:24.396+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000539658 ns, Reaching safepoint: 571823 ns, At safepoint: 5750 ns, Total: 577573 ns +[2021-01-28T10:45:25.397+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000461240 ns, Reaching safepoint: 356257 ns, At safepoint: 5343 ns, Total: 361600 ns +[2021-01-28T10:45:26.398+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000725816 ns, Reaching safepoint: 302450 ns, At safepoint: 5140 ns, Total: 307590 ns +[2021-01-28T10:45:27.399+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000258904 ns, Reaching safepoint: 279380 ns, At safepoint: 6683 ns, Total: 286063 ns +[2021-01-28T10:45:28.399+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000234663 ns, Reaching safepoint: 201260 ns, At safepoint: 5043 ns, Total: 206303 ns +[2021-01-28T10:45:29.400+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000773661 ns, Reaching safepoint: 212675 ns, At safepoint: 4550 ns, Total: 217225 ns +[2021-01-28T10:45:30.316+0000][1][safepoint ] Safepoint "RevokeBias", Time since last: 915129579 ns, Reaching safepoint: 383108 ns, At safepoint: 136621 ns, Total: 519729 ns +[2021-01-28T10:45:31.316+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000216430 ns, Reaching safepoint: 147809 ns, At safepoint: 3241 ns, Total: 151050 ns +[2021-01-28T10:45:32.316+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000189170 ns, Reaching safepoint: 154746 ns, At safepoint: 3522 ns, Total: 158268 ns +[2021-01-28T10:45:33.317+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000205882 ns, Reaching safepoint: 618106 ns, At safepoint: 8600 ns, Total: 626706 ns +[2021-01-28T10:45:34.318+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000803610 ns, Reaching safepoint: 200159 ns, At safepoint: 5169 ns, Total: 205328 ns +[2021-01-28T10:45:35.319+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000261132 ns, Reaching safepoint: 160614 ns, At safepoint: 3626 ns, Total: 164240 ns +[2021-01-28T10:45:36.319+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000375442 ns, Reaching safepoint: 315628 ns, At safepoint: 7115 ns, Total: 322743 ns +[2021-01-28T10:45:37.320+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000329850 ns, Reaching safepoint: 217814 ns, At safepoint: 3076 ns, Total: 220890 ns +[2021-01-28T10:45:38.321+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000459103 ns, Reaching safepoint: 224588 ns, At safepoint: 4929 ns, Total: 229517 ns +[2021-01-28T10:45:39.323+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1001283211 ns, Reaching safepoint: 1075525 ns, At safepoint: 100629 ns, Total: 1176154 ns +[2021-01-28T10:45:40.324+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000337308 ns, Reaching safepoint: 263214 ns, At safepoint: 4943 ns, Total: 268157 ns +[2021-01-28T10:45:41.324+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000324530 ns, Reaching safepoint: 283650 ns, At safepoint: 6412 ns, Total: 290062 ns +[2021-01-28T10:45:42.325+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000314363 ns, Reaching safepoint: 141293 ns, At safepoint: 3140 ns, Total: 144433 ns +[2021-01-28T10:45:43.326+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000480451 ns, Reaching safepoint: 320207 ns, At safepoint: 5936 ns, Total: 326143 ns +[2021-01-28T10:45:44.326+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000678454 ns, Reaching safepoint: 250227 ns, At safepoint: 7448 ns, Total: 257675 ns +[2021-01-28T10:45:45.327+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000303193 ns, Reaching safepoint: 182327 ns, At safepoint: 4276 ns, Total: 186603 ns +[2021-01-28T10:45:46.327+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000177133 ns, Reaching safepoint: 270418 ns, At safepoint: 4833 ns, Total: 275251 ns +[2021-01-28T10:45:47.328+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000352714 ns, Reaching safepoint: 284272 ns, At safepoint: 5472 ns, Total: 289744 ns +[2021-01-28T10:45:48.328+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000187953 ns, Reaching safepoint: 158654 ns, At safepoint: 3227 ns, Total: 161881 ns +[2021-01-28T10:45:49.329+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000189291 ns, Reaching safepoint: 229039 ns, At safepoint: 3812 ns, Total: 232851 ns +[2021-01-28T10:45:50.329+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000220899 ns, Reaching safepoint: 252019 ns, At safepoint: 4632 ns, Total: 256651 ns +[2021-01-28T10:45:51.330+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000179960 ns, Reaching safepoint: 191509 ns, At safepoint: 4062 ns, Total: 195571 ns +[2021-01-28T10:45:52.330+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000178736 ns, Reaching safepoint: 148291 ns, At safepoint: 3001 ns, Total: 151292 ns +[2021-01-28T10:45:53.332+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1002033328 ns, Reaching safepoint: 197074 ns, At safepoint: 3906 ns, Total: 200980 ns +[2021-01-28T10:45:54.333+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000350264 ns, Reaching safepoint: 331428 ns, At safepoint: 9365 ns, Total: 340793 ns +[2021-01-28T10:45:55.334+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000473210 ns, Reaching safepoint: 231816 ns, At safepoint: 5443 ns, Total: 237259 ns +[2021-01-28T10:45:56.336+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1001362414 ns, Reaching safepoint: 556264 ns, At safepoint: 9181 ns, Total: 565445 ns +[2021-01-28T10:45:57.337+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1001087041 ns, Reaching safepoint: 637212 ns, At safepoint: 6656 ns, Total: 643868 ns +[2021-01-28T10:45:58.338+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000193681 ns, Reaching safepoint: 209552 ns, At safepoint: 4710 ns, Total: 214262 ns +[2021-01-28T10:45:59.339+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000501646 ns, Reaching safepoint: 361608 ns, At safepoint: 11561 ns, Total: 373169 ns +[2021-01-28T10:46:00.339+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000305084 ns, Reaching safepoint: 217416 ns, At safepoint: 10904 ns, Total: 228320 ns +[2021-01-28T10:46:01.340+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000245922 ns, Reaching safepoint: 298914 ns, At safepoint: 10133 ns, Total: 309047 ns +[2021-01-28T10:46:02.340+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000450602 ns, Reaching safepoint: 190677 ns, At safepoint: 8106 ns, Total: 198783 ns +[2021-01-28T10:46:03.341+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000336853 ns, Reaching safepoint: 263384 ns, At safepoint: 8044 ns, Total: 271428 ns +[2021-01-28T10:46:04.341+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000189194 ns, Reaching safepoint: 189275 ns, At safepoint: 6624 ns, Total: 195899 ns +[2021-01-28T10:46:05.342+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000563001 ns, Reaching safepoint: 356321 ns, At safepoint: 6755 ns, Total: 363076 ns +[2021-01-28T10:46:06.344+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000858376 ns, Reaching safepoint: 450100 ns, At safepoint: 8291 ns, Total: 458391 ns +[2021-01-28T10:46:07.345+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000764809 ns, Reaching safepoint: 458731 ns, At safepoint: 14283 ns, Total: 473014 ns +[2021-01-28T10:46:08.346+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000503686 ns, Reaching safepoint: 351132 ns, At safepoint: 7249 ns, Total: 358381 ns +[2021-01-28T10:46:09.347+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1001021872 ns, Reaching safepoint: 414801 ns, At safepoint: 8032 ns, Total: 422833 ns +[2021-01-28T10:46:10.348+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000717665 ns, Reaching safepoint: 349463 ns, At safepoint: 66760 ns, Total: 416223 ns +[2021-01-28T10:46:11.349+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000300344 ns, Reaching safepoint: 401352 ns, At safepoint: 6310 ns, Total: 407662 ns +[2021-01-28T10:46:12.350+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000325566 ns, Reaching safepoint: 360366 ns, At safepoint: 8234 ns, Total: 368600 ns +[2021-01-28T10:46:13.350+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000400838 ns, Reaching safepoint: 273773 ns, At safepoint: 4300 ns, Total: 278073 ns +[2021-01-28T10:46:14.351+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000278583 ns, Reaching safepoint: 317269 ns, At safepoint: 3947 ns, Total: 321216 ns +[2021-01-28T10:46:15.352+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000277706 ns, Reaching safepoint: 220039 ns, At safepoint: 6106 ns, Total: 226145 ns +[2021-01-28T10:46:16.352+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000353817 ns, Reaching safepoint: 219361 ns, At safepoint: 10511 ns, Total: 229872 ns +[2021-01-28T10:46:17.353+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000702221 ns, Reaching safepoint: 242443 ns, At safepoint: 4406 ns, Total: 246849 ns +[2021-01-28T10:46:18.354+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000922485 ns, Reaching safepoint: 413016 ns, At safepoint: 18596 ns, Total: 431612 ns +[2021-01-28T10:46:19.355+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000720326 ns, Reaching safepoint: 298198 ns, At safepoint: 8686 ns, Total: 306884 ns +[2021-01-28T10:46:20.357+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1001061754 ns, Reaching safepoint: 359684 ns, At safepoint: 7235 ns, Total: 366919 ns +[2021-01-28T10:46:21.358+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1001299045 ns, Reaching safepoint: 223538 ns, At safepoint: 4391 ns, Total: 227929 ns +[2021-01-28T10:46:22.360+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000768978 ns, Reaching safepoint: 365729 ns, At safepoint: 21555 ns, Total: 387284 ns +[2021-01-28T10:46:23.361+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1001157672 ns, Reaching safepoint: 557342 ns, At safepoint: 6430 ns, Total: 563772 ns +[2021-01-28T10:46:24.362+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000360344 ns, Reaching safepoint: 342045 ns, At safepoint: 4927 ns, Total: 346972 ns +[2021-01-28T10:46:25.363+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000666596 ns, Reaching safepoint: 581209 ns, At safepoint: 8806 ns, Total: 590015 ns +[2021-01-28T10:46:26.364+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000668009 ns, Reaching safepoint: 379327 ns, At safepoint: 8200 ns, Total: 387527 ns +[2021-01-28T10:46:27.365+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000531513 ns, Reaching safepoint: 405930 ns, At safepoint: 7068 ns, Total: 412998 ns +[2021-01-28T10:46:28.367+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1001192001 ns, Reaching safepoint: 785711 ns, At safepoint: 81775 ns, Total: 867486 ns +[2021-01-28T10:46:29.368+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000703251 ns, Reaching safepoint: 352670 ns, At safepoint: 6755 ns, Total: 359425 ns +[2021-01-28T10:46:30.369+0000][1][safepoint ] Safepoint "Cleanup", Time since last: 1000664041 ns, Reaching safepoint: 362994 ns, At safepoint: 9260 ns, Total: 372254 ns diff --git a/deploy/deploy.sh b/deploy/deploy.sh old mode 100644 new mode 100755 index e69de29..53b39b5 --- a/deploy/deploy.sh +++ b/deploy/deploy.sh @@ -0,0 +1,7 @@ +#!/bin/bash +docker-compose up -d +echo "Starting docker containers, giving them some time to start..." +sleep 120 +# Restore dbs in Mongo with a default setup, apis and Oauth +docker cp ./mongodump deploy_mongo_1:/home/dump +docker exec -it deploy_mongo_1 mongorestore /home/dump diff --git a/deploy/docker-compose.yaml b/deploy/docker-compose.yaml index 1124234..02eb629 100644 --- a/deploy/docker-compose.yaml +++ b/deploy/docker-compose.yaml @@ -16,6 +16,9 @@ services: - cluster.name=elasticsearch - bootstrap.memory_lock=true - "ES_JAVA_OPTS=-Xms512m -Xmx512m" + ports: + - 9200:9200 + - 9300:9300 ulimits: memlock: soft: -1 @@ -23,28 +26,29 @@ services: nofile: 65536 networks: - storage + - frontend gateway: - image: graviteeio/gateway:${APIM_VERSION:-1} + image: graviteeio/gateway:${APIM_VERSION:-1.23.1} container_name: gio_apim_gateway restart: always ports: - "8082:8082" depends_on: - - mongodb + - mongo - elasticsearch volumes: - ./logs/apim-gateway:/opt/graviteeio-gateway/logs environment: - - gravitee_management_mongodb_uri=mongodb://mongodb:27017/gravitee?serverSelectionTimeoutMS=5000&connectTimeoutMS=5000&socketTimeoutMS=5000 - - gravitee_ratelimit_mongodb_uri=mongodb://mongodb:27017/gravitee?serverSelectionTimeoutMS=5000&connectTimeoutMS=5000&socketTimeoutMS=5000 + - gravitee_management_mongodb_uri=mongodb://mongo:27017/gravitee?serverSelectionTimeoutMS=5000&connectTimeoutMS=5000&socketTimeoutMS=5000 + - gravitee_ratelimit_mongodb_uri=mongodb://mongo:27017/gravitee?serverSelectionTimeoutMS=5000&connectTimeoutMS=5000&socketTimeoutMS=5000 - gravitee_reporters_elasticsearch_endpoints_0=http://elasticsearch:9200 networks: - storage - frontend management_api: - image: graviteeio/management-api:${APIM_VERSION:-1} + image: graviteeio/management-api:${APIM_VERSION:-1.23.1} container_name: gio_apim_management_api restart: always ports: @@ -65,7 +69,7 @@ services: - frontend management_ui: - image: graviteeio/management-ui:${APIM_VERSION:-1} + image: graviteeio/management-ui:${APIM_VERSION:-1.23.1} container_name: gio_apim_management_ui restart: always ports: @@ -120,16 +124,16 @@ services: - storage crate: - image: crate:${CRATE_VERSION:-3.1.2} - command: crate -Clicense.enterprise=false -Cauth.host_based.enabled=false - -Ccluster.name=democluster -Chttp.cors.enabled=true -Chttp.cors.allow-origin="*" + image: crate:${CRATE_VERSION:-4.1.4} + command: crate -Cnode.name=crate ports: # Admin UI - "4200:4200" # Transport protocol - "4300:4300" + - "5432:5432" volumes: - - cratedata:/data + - ./cratedata:/data networks: - storage @@ -138,25 +142,53 @@ services: environment: - IOTA_MONGO_HOST=mongo ports: - - "8082:8082" + - "8086:8082" + networks: + - storage + - frontend + + iot-agent: + image: fiware/iotagent-ul + depends_on: + - mongo + - iot-manager + ports: + - "4061:4061" + - "7896:7896" + environment: + - "IOTA_CB_HOST=orion" + - "IOTA_CB_PORT=1026" + - "IOTA_NORTH_PORT=4061" + - "IOTA_REGISTRY_TYPE=mongodb" + - "IOTA_MONGO_HOST=mongo" + - "IOTA_MONGO_PORT=27017" + - "IOTA_MONGO_DB=iotagent-ul" + - "IOTA_HTTP_PORT=7896" + - "IOTA_PROVIDER_URL=http://iot-agent:4061" + volumes: + - ./iotagent-ul-config.js:/opt/iotaul/config.js + networks: + - storage + - frontend grafana: - image: grafana/grafana + image: grafana/grafana:7.3.7 ports: - "3000:3000" environment: - GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-worldmap-panel + volumes: + - ./crate-datasource:/var/lib/grafana/plugins/crate-datasource + - ./grafana-map-plugin:/var/lib/grafana/plugins/map-panel + - ./grafana.db:/var/lib/grafana/grafana.db depends_on: - crate networks: - frontend + - storage redis: image: redis - deploy: - # Scaling Redis requires some extra work. - # See https://get-reddie.com/blog/redis4-cluster-docker-compose/ - replicas: 1 ports: - "6379:6379" volumes: @@ -165,7 +197,7 @@ services: - storage portal: - image: orchestracities/portal:dev + image: orchestracities/portal:${PORTAL_VERSION:-0.1.30} depends_on: - portaldb environment: @@ -173,20 +205,20 @@ services: - DJANGO_SETTINGS_MODULE=portal.settings.production - KEYCLOAK_FRONTEND_CLIENT_ID=portal - KEYCLOAK_OIDC_CLIENT_ID=resource_server - - KEYCLOAK_OIDC_CLIENT_SECRET=006ce147-dd78-42db-a78a-1b5b0f3a723f - - KEYCLOAK_BASE=https://auth.s.orchestracities.com/auth + - KEYCLOAK_OIDC_CLIENT_SECRET=98dabcef-960a-4474-8c11-e8807a92ec94 + - KEYCLOAK_BASE=http://keycloak:8080/auth - KEYCLOAK_REALM=default - - KEYCLOAK_ADMIN_URI=https://auth.s.orchestracities.com/auth/ + - KEYCLOAK_ADMIN_URI=http://keycloak:8080/auth/ - KEYCLOAK_ADMIN_CLIENT_ID=admin-cli - - KEYCLOAK_ADMIN_CLIENT_SECRET=6fad563f-8e1c-4cb7-9ade-9734909dfb90 - - KEYCLOAK_ADMIN_USERNAME=portaladmin - - KEYCLOAK_ADMIN_PASSWORD=portaladminpass - - KEYCLOAK_OIDC_ENDPOINT=https://auth.s.orchestracities.com/auth + - KEYCLOAK_ADMIN_CLIENT_SECRET=cc4ffe2a-c660-4547-b3b4-5d1c93305047 + - KEYCLOAK_ADMIN_USERNAME=admin + - KEYCLOAK_ADMIN_PASSWORD=password + - KEYCLOAK_OIDC_ENDPOINT=http://keycloak:8080/auth - KEYCLOAK_OIDC_REALM=default - - KEYCLOAK_OIDC_AUTHORIZATION_ENDPOINT=https://auth.s.orchestracities.com/auth/realms/default/protocol/openid-connect/auth - - KEYCLOAK_OIDC_TOKEN_ENDPOINT=https://auth.s.orchestracities.com/auth/realms/default/protocol/openid-connect/token - - KEYCLOAK_OIDC_USER_ENDPOINT=https://auth.s.orchestracities.com/auth/realms/default/protocol/openid-connect/userinfo - - KEYCLOAK_OIDC_JWKS_ENDPOINT=https://auth.s.orchestracities.com/auth/realms/default/protocol/openid-connect/certs + - KEYCLOAK_OIDC_AUTHORIZATION_ENDPOINT=http://keycloak:8080/auth/realms/default/protocol/openid-connect/auth + - KEYCLOAK_OIDC_TOKEN_ENDPOINT=http://keycloak:8080/auth/realms/default/protocol/openid-connect/token + - KEYCLOAK_OIDC_USER_ENDPOINT=http://keycloak:8080/auth/realms/default/protocol/openid-connect/userinfo + - KEYCLOAK_OIDC_JWKS_ENDPOINT=http://keycloak:8080/auth/realms/default/protocol/openid-connect/certs - PORTAL_DB_HOST=portaldb - PORTAL_DB_PORT=5432 - PORTAL_DB_NAME=portal @@ -204,6 +236,12 @@ services: - KIBANA_URL=# - NO_SQUL_URL=# - GRAVITEE_URL=# + - EMAIL_HOST=smtp.gmail.com + - EMAIL_USE_TLS=True + - EMAIL_PORT=587 + - EMAIL_HOST_USER=ocportalmail@gmail.com + - EMAIL_HOST_PASSWORD=password + - REDIS_BROKER_URL=redis://redis:6379 #- UI_CUSTOM_CSS_URL=https://raw.githubusercontent.com/orchestracities/shared-resources/master/oc-portal/css/ekz_css.css #- UI_CUSTOM_LOGO_URL=https://github.com/orchestracities/shared-resources/raw/master/oc-portal/images/ekz_logo.png ports: @@ -218,6 +256,24 @@ services: - POSTGRES_USER=portal - POSTGRES_PASSWORD=password - POSTGRES_DB=portal + networks: + - storage + - frontend + + keycloak: + image: jboss/keycloak:${KEYCLOAK_VERSION:-5.0.0} + ports: + - "8080:8080" + volumes: + - ./realm-export.json:/tmp/realm-export.json + environment: + - KEYCLOAK_USER=admin + - KEYCLOAK_PASSWORD=password + - KEYCLOAK_IMPORT=/tmp/realm-export.json + networks: + - storage + - frontend + volumes: portal_db: @@ -230,6 +286,4 @@ volumes: networks: frontend: - name: frontend storage: - name: storage \ No newline at end of file diff --git a/deploy/grafana-map-plugin/.eslintignore b/deploy/grafana-map-plugin/.eslintignore new file mode 100755 index 0000000..e61de8a --- /dev/null +++ b/deploy/grafana-map-plugin/.eslintignore @@ -0,0 +1,2 @@ +dist/* +src/libs/leaflet.js diff --git a/deploy/grafana-map-plugin/.eslintrc b/deploy/grafana-map-plugin/.eslintrc new file mode 100755 index 0000000..c65b5e9 --- /dev/null +++ b/deploy/grafana-map-plugin/.eslintrc @@ -0,0 +1,50 @@ +{ + "root": true, + "extends": "airbnb/base", + "env": { + "browser": true + }, + "parser": "babel-eslint", + "parserOptions": { + "ecmaVersion": 6 + }, + "rules": { + "array-bracket-spacing": 0, + "arrow-body-style": 0, + "comma-dangle": 0, // not sure why airbnb turned this on. gross! + "computed-property-spacing": 0, + "consistent-return": 0, + "global-require": 0, + "id-length": [2, {"min": 2, "max": 30, "properties": "never", "exceptions": ["_", "t", "a", "b"]}], + "import/default": 0, + "import/named": 0, + "import/namespace": 0, + "import/no-duplicates": 0, + "import/no-named-as-default": 2, + "import/no-unresolved": 0, + "import/extensions": 0, + "indent": [2, 2, {"SwitchCase": 1}], + "max-len": [0, 120, 2], + "no-alert": 0, + "no-console": 0, + "no-param-reassign": [2, {"props": false}], + "no-use-before-define": 0, // disabled until https://github.com/babel/babel-eslint/issues/249 is fixed + "no-underscore-dangle": 0, + "object-curly-spacing": 0, + "object-shorthand": 0, + "prefer-arrow-callback": 0, + "prefer-template": 0, + "quote-props": [2, "consistent"] + }, + "plugins": [ + "import" + ], + "settings": { + "import/parser": "babel-eslint", + "import/resolve": { + "moduleDirectory": ["node_modules", "src"] + } + }, + "globals": { + } +} diff --git a/deploy/grafana-map-plugin/.gitignore b/deploy/grafana-map-plugin/.gitignore new file mode 100755 index 0000000..3bb7e5c --- /dev/null +++ b/deploy/grafana-map-plugin/.gitignore @@ -0,0 +1,5 @@ +node_modules +npm-debug.log +.DS_Store +crate-datasource +package-lock.json \ No newline at end of file diff --git a/deploy/grafana-map-plugin/.gitlab-ci.yml b/deploy/grafana-map-plugin/.gitlab-ci.yml new file mode 100755 index 0000000..603ada8 --- /dev/null +++ b/deploy/grafana-map-plugin/.gitlab-ci.yml @@ -0,0 +1,29 @@ +image: node:9.11 +cache: + paths: + - node_modules/ + +stages: + - build + - deploy + +build frontend: + stage: build + script: + - yarn install + - yarn build + +pages: + stage: deploy + script: + - echo "Creating artifact / Deploying" + - yarn install + - yarn build + - rm -rf public + - mv dist public + artifacts: + paths: + - public + expire_in: 1 month + only: + - master diff --git a/deploy/grafana-map-plugin/CHANGELOG.md b/deploy/grafana-map-plugin/CHANGELOG.md new file mode 100755 index 0000000..72456e8 --- /dev/null +++ b/deploy/grafana-map-plugin/CHANGELOG.md @@ -0,0 +1,118 @@ +# Changelog + +## v1.3.1 +- Map centered at location updated when changing coordinates. + +## v1.3.0 +- New option for centering map at user geolocation + +## v1.2.0 +- Suport for leaflet markercluster +- Suport for leaflet sleep to avoid auto scroll when hover big dashboards. +- Resize panel improvements for mobile. +- min zoom level set to 3. + +## v1.1.0 +- In the editor metrics tab, a query result can be 'format as' 'table' + +## v1.0.0 + +### New features / Fix +- Changed the plugin's working process. Any datasource query with a group by clause will result in layers. +- Map rendering faster. +- Removal of polylines for data point of type traffic flow observed. +- Data points of type air quality, traffic flow and other have now distinct shapes (circle, square and triangle). +- Added missing snapshot functionality (Not tested). +- New option on editor for cityenv variable support. If we choose this option the map centers on the selected city. +- Fix problem with multiple map panels in the same dashboard. +- Ability to change the icon associated to the layer (with leaflet.awesome-markers). +- When adding this panel for the first time to a dashboard, metrics are filled with predefined values. +- Dark theme improvements. + +### Development +- Improvements based on grafana development guide best practices. +- New project structure. Improved DRY. +- Updated project packages. Leaflet version updated from 0.7 to 1.3. +- Updated project packages. Highcharts updated from 5.0.15 to 6.1.0. +- Fix app bugs introduced by Leaflet update. +- Gruntfile improvements. + +## v0.1.0 + +- Project structure improvements. Leaflet and highstock went out from project src and are now a dependency. +- Support for light and dark themes. +- From now on this file contents are reverse ordered to get last features on top. + +## v0.0.2 + +- Fixes bug where time series with a country code not found in the country data crashes the panel. +- Adds some extra country codes to the country data to be more similar to the MaxMind Country database. + +## v0.0.3 + +- Support for lowercase country codes for non-elasticsearch datasources. + +## v0.0.4 + +- Fixes snapshotting. + +## v.0.0.5 + +- Adds support for json and jsonp endpoints for location data. + +## v.0.0.6 + +- Adds decimal places option for data values in circle popovers. + +## v.0.0.7 + +- Updates tile map urls to https to avoid mixed content warnings on https sites. + +## v.0.0.8 + +- Saves location data in the dashboard json when snapshotting. This means snapshots should work even when using a custom endpoint for returning a location data json file. + +## v.0.0.9 + +- Fixes bug that meant location data did not refresh after being changed in the editor. It required the page to be refreshed to reload it. + +## v.0.0.10 + +- Performance fix for snapshotting. Sets maxdatapoints to 1 to minimize data that needs to be saved in the snapshot. + +## v.0.0.11 + +- Zoom issue fix and adds a states options for USA states location data. + +## v.0.0.12 + +- Fixes [issue with the JSON endpoint not working](https://github.com/grafana/worldmap-panel/issues/22) + +## v.0.0.13 + +- New location data option -> table data. Location data can now come from data sources other than graphite and Elasticsearch (InfluxDb for example). See table data instructions above on how to use it. + +## v.0.0.14 + +- Various [bug](https://github.com/grafana/worldmap-panel/pull/31) [fixes](https://github.com/grafana/worldmap-panel/pull/32) provided by [linkslice](https://github.com/linkslice) (Thank you!) + +## v.0.0.15 + +- Fix for change in Grafana that [breaks Worldmap panels using Geohash or Table Data](https://github.com/grafana/worldmap-panel/issues/45). + +## v.0.0.16 + +- Option for sticky labels. Fix for https://github.com/grafana/worldmap-panel/issues/27 + +- Ability to hide null or 0 values. Fix for https://github.com/grafana/worldmap-panel/issues/13 + +- Background color change. Fixes https://github.com/grafana/worldmap-panel/issues/36 + +- Dynamic thresholds implemented by [Sam Hatchett](https://github.com/samhatchett). Can now have more than 2 threshold values. Thanks! Fixes https://github.com/grafana/worldmap-panel/issues/25 + +- Validation and default values for option fields. Fixes https://github.com/grafana/worldmap-panel/issues/29 + +## v.0.0.17 + +- Adds Country data with 3-letter country codes. + diff --git a/deploy/grafana-map-plugin/CONTRIBUTING.md b/deploy/grafana-map-plugin/CONTRIBUTING.md new file mode 100755 index 0000000..b8dfe48 --- /dev/null +++ b/deploy/grafana-map-plugin/CONTRIBUTING.md @@ -0,0 +1,82 @@ +# Building Map Plugin + +## Requirements +- git +- npm / yarn + +## Install process + +- Clone "map-plugin" from repo to the grafana plugins folder. (eg. grafana_data/plugins) + +- Install plugin package dependencies + +```sh +$ npm install +``` +or +``` +$ yarn install +``` + +If you are using Docker, the two steps above can be done as follows: +``` +# First cd into this plugin's folder. +docker run -it --rm -v "$PWD":/usr/src/app -w /usr/src/app node:8 npm install +docker run -it --rm -v "$PWD":/usr/src/app -w /usr/src/app node:8 yarn install +``` + +## Test / Run + +- clone the crated data source. + + ```sh + $ sh get-crate-plugin.sh + ``` + +- Start docker-compose. + + ```sh + $ docker-compose up -d + ``` + +Once the services are up and running, set-up the data as follows: + +- Populate the database: + + ```sh + $ sh create-table.sh + ``` + +- Set-up grafana: + + ```sh + $ sh set-up-grafana.sh + ``` + +**NOTE:** Unless you remove the docker volumes, you need to run the last two +steps above only the first time) + +At this point in time login in grafana using admin/admin and you should be +able to see a dashboard called `Dashboard Map`. If there is an error regarding +the datasource metadata, just go to the `datasource` menu, open the datasource +and click `save & test`. + +## Other Tasks + +- `Compile the code` + restart grafana +```sh +$ yarn build && docker-compose restart grafana +``` + +Or using docker: +``` +docker run -it --rm -v "$PWD":/usr/src/app -w /usr/src/app node:8 yarn build +docker-compose restart grafana +``` + +## Notes + +Default start page url: http://localhost:3000 +Default user/pass is admin/admin. + +If you are trying to install packages and you get console permissions errors, it could be related with grafana changing owner from dist files. diff --git a/deploy/grafana-map-plugin/Gruntfile.js b/deploy/grafana-map-plugin/Gruntfile.js new file mode 100755 index 0000000..8befc86 --- /dev/null +++ b/deploy/grafana-map-plugin/Gruntfile.js @@ -0,0 +1,137 @@ +/* eslint import/no-extraneous-dependencies: 0 */ + +module.exports = (grunt) => { + require('load-grunt-tasks')(grunt); + + // grunt.loadNpmTasks('grunt-exec'); + grunt.loadNpmTasks('grunt-contrib-clean'); + // grunt.loadNpmTasks('grunt-postcss'); + + grunt.initConfig({ + clean: ['dist'], + copy: { + srcToDist: { + cwd: 'src', + expand: true, + src: ['plugin.json', '**/*.html', '!**/*.js', '**/*.css'], + dest: 'dist' + }, + pluginDef: { + expand: true, + src: [ 'LICENSE', 'README.md', 'CHANGELOG.md' ], + dest: 'dist', + }, + + imgToDist: { + cwd: 'src', + expand: true, + src: ['img/**/*'], + dest: 'dist/' + }, + + leaflet: { + cwd: 'node_modules/leaflet/dist/', + expand: true, + src: ['**/*'], + dest: 'dist/vendor/leaflet' + }, + + turf: { + cwd: 'node_modules/turf', + expand: true, + src: ['**/*'], + dest: 'dist/vendor/turf' + }, + + osmbuildings: { + cwd: 'node_modules/osmbuildings/dist/', + expand: true, + src: ['**/*'], + dest: 'dist/vendor/osmbuildings' + }, + + leafletAwesomeMarkers: { + cwd: 'node_modules/leaflet.awesome-markers/dist/', + expand: true, + src: ['**/*'], + dest: 'dist/vendor/leaflet.awesome-markers' + }, + + leafletMarkerCluster: { + cwd: 'node_modules/leaflet.markercluster/dist/', + expand: true, + src: ['**/*'], + dest: 'dist/vendor/leaflet.markercluster' + }, + + leafletSleep: { + cwd: 'node_modules/leaflet-sleep/', + expand: true, + src: ['Leaflet.Sleep.js'], + dest: 'dist/vendor/leaflet-sleep/' + }, + + fontawesome: { + cwd: 'node_modules/@fortawesome/fontawesome-free/', + expand: true, + src: ['css/*.css','webfonts/*'], + dest: 'dist/vendor/fontawesome-free' + }, + + }, + + babel: { + options: { + sourceMap: true, + presets: ['@babel/preset-env'] + }, + dist: { + files: [ + { + cwd: 'src', + expand: true, + src: ['**/*.js'], + dest: 'dist', + ext: '.js' + }, + ] + }, + }, + + // postcss: { + // options: { + // map: true, // inline sourcemaps + + // processors: [ + // require('pixrem')(), // add fallbacks for rem units + // require('autoprefixer')({browsers: 'last 2 versions'}), // add vendor prefixes + // //require('cssnano')() // minify the result TO-DO: just for production + // ] + // }, + // dist: { + // cwd: 'src', + // expand: true, + // src: ['*css/*.css'], + // dest: 'dist' + // } + // } + + }); + + grunt.registerTask('default', [ + 'clean', + 'copy:srcToDist', + 'copy:pluginDef', + 'copy:imgToDist', + 'copy:leaflet', + 'copy:turf', + 'copy:osmbuildings', + 'copy:leafletAwesomeMarkers', + 'copy:leafletMarkerCluster', + 'copy:leafletSleep', + 'copy:fontawesome', + + // 'postcss', + 'babel' + ]); +}; diff --git a/deploy/grafana-map-plugin/LICENSE b/deploy/grafana-map-plugin/LICENSE new file mode 100755 index 0000000..4644c8c --- /dev/null +++ b/deploy/grafana-map-plugin/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Grafana + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/deploy/grafana-map-plugin/README.md b/deploy/grafana-map-plugin/README.md new file mode 100755 index 0000000..7f32a7c --- /dev/null +++ b/deploy/grafana-map-plugin/README.md @@ -0,0 +1,8 @@ +# Grafana Map Plugin + +Map views of your Time Series datasources. + +Use this plugin if you want: + +- A representation of your geolocated data in one map panel with your points represented as markers. +- Analyse the historical timeline data using a line chart. \ No newline at end of file diff --git a/deploy/grafana-map-plugin/circle.yml b/deploy/grafana-map-plugin/circle.yml new file mode 100755 index 0000000..47283e9 --- /dev/null +++ b/deploy/grafana-map-plugin/circle.yml @@ -0,0 +1,12 @@ +machine: + node: + version: 6.4.0 + +dependencies: + override: + - npm install + - npm run build + +test: + override: + - npm run test diff --git a/deploy/grafana-map-plugin/config.sh b/deploy/grafana-map-plugin/config.sh new file mode 100755 index 0000000..43ee84d --- /dev/null +++ b/deploy/grafana-map-plugin/config.sh @@ -0,0 +1 @@ +CRATE_URL="localhost:4200" diff --git a/deploy/grafana-map-plugin/create-table.sh b/deploy/grafana-map-plugin/create-table.sh new file mode 100755 index 0000000..e5f8314 --- /dev/null +++ b/deploy/grafana-map-plugin/create-table.sh @@ -0,0 +1,211 @@ +source config.sh + +echo 'create table\n' + +curl -sS -H 'Content-Type: application/json' \ + -X POST "$CRATE_URL/_sql" \ + -H 'Default-Schema: doc' \ + -d '{"stmt":"create table example ( bool boolean, address object, availablespotnumber FLOAT, entity_id STRING, entity_type STRING, fiware_servicepath STRING, license STRING, location GEO_SHAPE, location_centroid GEO_POINT, name STRING, source STRING, status STRING, time_index TIMESTAMP, timeinstant STRING);"}' + +echo '\n\ninsert data 1\n' + +curl -sS -H 'Content-Type: application/json' \ + -X POST "$CRATE_URL/_sql" \ + -H 'Default-Schema: doc' \ + -d ' + {"stmt": "INSERT INTO example (bool, address,availablespotnumber,entity_id,entity_type,fiware_servicepath,license,location,location_centroid,name,source,status,time_index,timeinstant) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", "bulk_args": [[true, {"addressCountry":"Switzerland","streetAddress":"Armin-Bollinger-Weg","addressLocality":"Zurich"}, 73, "urn:ngsi-ld:OffStreetParking:max_bill_platz", "OffStreetParking", "/ParkingManagement", "https://creativecommons.org/publicdomain/zero/1.0/", {"coordinates":[[8.5379554,47.4143907],[8.5378758,47.4143952],[8.5365221,47.4144732],[8.5364455,47.4144776]],"type":"LineString"}, [8.537199699999999,47.414434175], "Parkhaus Max-Bill-Platz / Armin-Bollinger-Weg", "https://data.stadt-zuerich.ch", "open", 1551872353000, "2019-03-06T11:39:13Z"]]}' + +echo '\n\ninsert data 2\n' + + curl -sS -H 'Content-Type: application/json' \ + -X POST "$CRATE_URL/_sql" \ + -H 'Default-Schema: doc' \ + -d '{"stmt": "INSERT INTO example (bool, address,availablespotnumber,entity_id,entity_type,fiware_servicepath,license,location,location_centroid,name,source,status,time_index,timeinstant) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", "bulk_args": [[false, {"addressCountry": "Switzerland","streetAddress": "Dufourstrasse 142","addressLocality": "Zurich"},65,"urn:ngsi-ld:OffStreetParking:zuerichhorn","OffStreetParking","/ParkingManagement","https://creativecommons.org/publicdomain/zero/1.0/",{"coordinates":[[[8.5532871,47.3560349],[8.5533097,47.3560042],[8.5533122,47.3560009],[8.5535063,47.3560663],[8.5535399,47.3560206],[8.5535011,47.3560076],[8.5535323,47.355965],[8.5535761,47.3559798],[8.5535994,47.3559482],[8.5536647,47.3559702],[8.5535516,47.3561241],[ 8.5532871,47.3560349]]],"type": "Polygon"},[8.553472291666667,47.35601305833334],"Parkhaus Zurichhorn / Dufourstrasse 142","https://data.stadt-zuerich.ch","open",1552031070000,"2019-03-08T07:44:30Z"]]}' + +echo '\n\ninsert data 3\n' + + curl -sS -H 'Content-Type: application/json' \ + -X POST "$CRATE_URL/_sql" \ + -H 'Default-Schema: doc' \ + -d '{"stmt": "INSERT INTO example (address,availablespotnumber,entity_id,entity_type,fiware_servicepath,license,location,location_centroid,name,source,status,time_index,timeinstant) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", "bulk_args": [[{"addressCountry":"Switzerland","streetAddress":"Gloriastrasse","addressLocality":"Zurich"}, 55, "urn:ngsi-ld:OffStreetParking:unispital_sued", "OffStreetParking", "/ParkingManagement", "https://creativecommons.org/publicdomain/zero/1.0/", {"coordinates":[[8.5536227,47.3770429],[8.5539427,47.3769896],[8.5543784,47.3769189]],"type":"LineString"}, [8.553981266666666,47.3769838], "Parkplatz USZ S�d / Gloriastrasse", "https://data.stadt-zuerich.ch/", "open", 1551906232000, "2019-03-06T21:03:52Z"]]}' + +echo '\n\ninsert data 4\n' + + curl -sS -H 'Content-Type: application/json' \ + -X POST "$CRATE_URL/_sql" \ + -H 'Default-Schema: doc' \ + -d '{"stmt": "INSERT INTO example (address,availablespotnumber,entity_id,entity_type,fiware_servicepath,license,location,location_centroid,name,source,status,time_index,timeinstant) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", "bulk_args": [[{"addressCountry":"Switzerland","streetAddress":"N�schelerstrasse 31","addressLocality":"Zurich"}, 45, "urn:ngsi-ld:OffStreetParking:talgarten", "OffStreetParking", "/ParkingManagement", "https://creativecommons.org/publicdomain/zero/1.0/", {"coordinates":[[[8.5353503,47.3724602],[8.5354002,47.3724064],[8.5354454,47.3723659],[8.535915,47.3720271],[8.5360576,47.3721039],[8.5360503,47.3721084],[8.5360682,47.3721192],[8.5356209,47.3724429],[8.5355803,47.3724762],[8.5355454,47.3725128],[8.5355045,47.3724983],[8.5353503,47.3724602]]],"type":"Polygon"}, [8.535657366666667,47.37233179166666], "Parkhaus Talgarten / N�schelerstrasse 31", "https://data.stadt-zuerich.ch/", "open", 1552158093000, "2019-03-09T19:01:33Z"]]}' + +echo '\n\ninsert data 5\n' + + curl -sS -H 'Content-Type: application/json' \ + -X POST "$CRATE_URL/_sql" \ + -H 'Default-Schema: doc' \ + -d '{"stmt": "INSERT INTO example (address,availablespotnumber,entity_id,entity_type,fiware_servicepath,license,location,location_centroid,name,source,status,time_index,timeinstant) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", "bulk_args": [[{"addressCountry":"Switzerland","streetAddress":"Schillerstrasse 5","addressLocality":"Zurich"}, 35, "urn:ngsi-ld:OffStreetParking:opera", "OffStreetParking", "/ParkingManagement", "https://creativecommons.org/publicdomain/zero/1.0/", {"coordinates":[[[8.5457149,47.3656622],[8.546062,47.365176],[8.5468001,47.365415],[8.5469132,47.3654479],[8.5472176,47.3655636],[8.5471347,47.3656516],[8.5470483,47.3656188],[8.546679,47.3659876],[8.5457149,47.3656622]]],"type":"Polygon"}, [8.546587188888887,47.3655761], "Parkhaus Op�ra / Schillerstrasse 5", "https://data.stadt-zuerich.ch/", "open", 1551200630000, "2019-02-26T17:03:50Z" +]]}' + +echo '\n\ninsert data 6\n' + + curl -sS -H 'Content-Type: application/json' \ + -X POST "$CRATE_URL/_sql" \ + -H 'Default-Schema: doc' \ + -d '{"stmt": "INSERT INTO example (address,availablespotnumber,entity_id,entity_type,fiware_servicepath,license,location,location_centroid,name,source,status,time_index,timeinstant) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", "bulk_args": [[{"addressCountry":"Switzerland","streetAddress":"Schillerstrasse 5","addressLocality":"Zurich"}, 25, "urn:ngsi-ld:OffStreetParking:opera", "OffStreetParking2", "/ParkingManagement", "https://creativecommons.org/publicdomain/zero/1.0/", {"coordinates":[[[8.5457149,47.3656622],[8.546062,47.265176],[8.5468001,47.365415],[8.5469132,47.3654479],[8.5472176,47.3655636],[8.5471347,47.3656516],[8.5470483,47.3656188],[8.546679,47.3659876],[8.5457149,47.3656622]]],"type":"Polygon"}, [8.546587188888887,47.3655761], "Parkhaus Op�ra / Schillerstrasse 55", "https://data.stadt-zuerich.ch/", "open", 1551200630000, "2019-02-26T17:03:50Z" +]]}' + +echo '\n\ninsert data 6\n' + + curl -sS -H 'Content-Type: application/json' \ + -X POST 'localhost:4200/_sql' \ + -H 'Default-Schema: doc' \ + -d '{"stmt": "INSERT INTO example (address,availablespotnumber,entity_id,entity_type,fiware_servicepath,license,location,location_centroid,name,source,status,time_index,timeinstant) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", "bulk_args": [[{"addressCountry":"Switzerland","streetAddress":"Gladbachstrasse","addressLocality":"Zurich"}, 0, "urn:ngsi-ld:OffStreetParking:Siriuswiese", "OffStreetParking", "/ParkingManagement", "https://creativecommons.org/publicdomain/zero/1.0/", {"coordinates":[8.5539437,47.3797464],"type":"Point"}, [8.5539437,47.3797464], "Siriuswiese", "https://test.ch/", "open", 1551200630000, "2019-02-26T17:03:50Z" +]]}' + +echo '\n\ninsert data 7\n' + + curl -sS -H 'Content-Type: application/json' \ + -X POST 'localhost:4200/_sql' \ + -H 'Default-Schema: doc' \ + -d '{"stmt": "INSERT INTO example (address,availablespotnumber,entity_id,entity_type,fiware_servicepath,license,location,location_centroid,name,source,status,time_index,timeinstant) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", "bulk_args": [[{"addressCountry":"Switzerland","streetAddress":"Voltastrasse 40","addressLocality":"Zurich"}, 1, "urn:ngsi-ld:OffStreetParking:ultimobacio", "OffStreetParking", "/ParkingManagement", "https://creativecommons.org/publicdomain/zero/1.0/", {"coordinates":[8.5534266,47.3791918],"type":"Point"}, [8.5534266,47.3791918], "LUltimo Bacio", "https://test/", "open", 1551200630000, "2019-02-26T17:03:50Z" +]]}' + +echo '\n\ninsert data 8\n' + + curl -sS -H 'Content-Type: application/json' \ + -X POST 'localhost:4200/_sql' \ + -H 'Default-Schema: doc' \ + -d '{"stmt": "INSERT INTO example (address,availablespotnumber,entity_id,entity_type,fiware_servicepath,license,location,location_centroid,name,source,status,time_index,timeinstant) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", "bulk_args": [[{"addressCountry":"Switzerland","streetAddress":"Liedenhofstrasse 4","addressLocality":"Zurich"}, 1, "urn:ngsi-ld:EVChargingStation:EVChargingStation1", "EVChargingStation", "/ParkingManagement", "https://creativecommons.org/publicdomain/zero/1.0/", {"coordinates":[8.54098230600357, 47.37481948235262],"type":"Point"}, [8.54098230600357, 47.37481948235262], "EVChargingStation 1", "https://test/", "open", 1551200630000, "2019-02-26T17:03:50Z" +]]}' + +echo '\n\ninsert data 9\n' + + curl -sS -H 'Content-Type: application/json' \ + -X POST 'localhost:4200/_sql' \ + -H 'Default-Schema: doc' \ + -d '{"stmt": "INSERT INTO example (address,availablespotnumber,entity_id,entity_type,fiware_servicepath,license,location,location_centroid,name,source,status,time_index,timeinstant) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", "bulk_args": [[{"addressCountry":"Switzerland","streetAddress":"Liedenhofstrasse 4","addressLocality":"Zurich"}, 1, "urn:ngsi-ld:EVChargingStation:EVChargingStation2", "EVChargingStation", "/ParkingManagement", "https://creativecommons.org/publicdomain/zero/1.0/", {"coordinates":[8.54112982749939,47.37481040040007],"type":"Point"}, [8.54112982749939,47.37481040040007], "EVChargingStation 2", "https://test/", "open", 1551200630000, "2019-02-26T17:03:50Z" +]]}' + +echo '\n\ninsert data 10\n' + + curl -sS -H 'Content-Type: application/json' \ + -X POST 'localhost:4200/_sql' \ + -H 'Default-Schema: doc' \ + -d '{"stmt": "INSERT INTO example (address,availablespotnumber,entity_id,entity_type,fiware_servicepath,license,location,location_centroid,name,source,status,time_index,timeinstant) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", "bulk_args": [[{"addressCountry": "Switzerland","streetAddress": "Liedenhofstrasse 4","addressLocality": "Zurich"},1,"urn:ngsi-ld:OffStreetParking:l1","OffStreetParking","/ParkingManagement","https://creativecommons.org/publicdomain/zero/1.0/",{"coordinates":[ + [ + [ + 8.54087769985199, + 47.374832197083556 + ], + [ + 8.540968894958496, + 47.374826747913545 + ], + [ + 8.5409876704216, + 47.3749084854048 + ], + [ + 8.540893793106079, + 47.37491575095346 + ], + [ + 8.54087769985199, + 47.374832197083556 + ] + ] + ],"type": "Polygon"},[8.54087769985199,47.374832197083556],"Random Test in Zurich","https://test.ch","open",1552031070000,"2019-03-08T07:44:30Z"]]}' + +echo '\n\ninsert data 11\n' + + curl -sS -H 'Content-Type: application/json' \ + -X POST 'localhost:4200/_sql' \ + -H 'Default-Schema: doc' \ + -d '{"stmt": "INSERT INTO example (address,availablespotnumber,entity_id,entity_type,fiware_servicepath,license,location,location_centroid,name,source,status,time_index,timeinstant) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", "bulk_args": [[{"addressCountry": "Switzerland","streetAddress": "Liedenhofstrasse 4","addressLocality": "Zurich"},1,"urn:ngsi-ld:OffStreetParking:l2","OffStreetParking","/ParkingManagement","https://creativecommons.org/publicdomain/zero/1.0/",{"coordinates":[ + [ + [ + 8.541017174720764, + 47.37482493152339 + ], + [ + 8.5411137342453, + 47.37481766596224 + ], + [ + 8.54112982749939, + 47.37489758707997 + ], + [ + 8.541038632392883, + 47.3749048526301 + ], + [ + 8.541017174720764, + 47.37482493152339 + ] + ] + ],"type": "Polygon"},[8.541038632392883,47.3749048526301],"Random Test in Zurich","https://test.ch","open",1552031070000,"2019-03-08T07:44:30Z"]]}' + +echo '\n\ninsert data 12\n' + + curl -sS -H 'Content-Type: application/json' \ + -X POST 'localhost:4200/_sql' \ + -H 'Default-Schema: doc' \ + -d '{"stmt": "INSERT INTO example (address,availablespotnumber,entity_id,entity_type,fiware_servicepath,license,location,location_centroid,name,source,status,time_index,timeinstant) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", "bulk_args": [[{"addressCountry": "Switzerland","streetAddress": "Liedenhofstrasse 4","addressLocality": "Zurich"},1,"urn:ngsi-ld:OffStreetParking:l3","OffStreetParking","/ParkingManagement","https://creativecommons.org/publicdomain/zero/1.0/",{"coordinates":[ + [ + [ + 8.540861606597899, + 47.374719580788586 + ], + [ + 8.540947437286377, + 47.37471594800088 + ], + [ + 8.540960848331451, + 47.37480131844597 + ], + [ + 8.540880382061005, + 47.374808584009386 + ], + [ + 8.540861606597899, + 47.374719580788586 + ] + ] + ],"type": "Polygon"},[8.540960848331451,47.37480131844597],"Random Test in Zurich","https://test.ch","open",1552031070000,"2019-03-08T07:44:30Z"]]}' + +echo '\n\ninsert data 12\n' + + curl -sS -H 'Content-Type: application/json' \ + -X POST 'localhost:4200/_sql' \ + -H 'Default-Schema: doc' \ + -d '{"stmt": "INSERT INTO example (address,availablespotnumber,entity_id,entity_type,fiware_servicepath,license,location,location_centroid,name,source,status,time_index,timeinstant) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", "bulk_args": [[{"addressCountry": "Switzerland","streetAddress": "Liedenhofstrasse 4","addressLocality": "Zurich"},1,"urn:ngsi-ld:OffStreetParking:l4","OffStreetParking","/ParkingManagement","https://creativecommons.org/publicdomain/zero/1.0/",{"coordinates":[ + [ + [ + 8.54099839925766, + 47.37471231521293 + ], + [ + 8.541092276573181, + 47.374708682424696 + ], + [ + 8.5411137342453, + 47.374799502054955 + ], + [ + 8.541017174720764, + 47.37480131844597 + ], + [ + 8.54099839925766, + 47.37471231521293 + ] + ] + ],"type": "Polygon"},[8.541092276573181,47.374708682424696],"Random Test in Zurich","https://test.ch","open",1552031070000,"2019-03-08T07:44:30Z"]]}' + + +echo '\n\ndone\n' + + + diff --git a/deploy/grafana-map-plugin/dashboards/map.json b/deploy/grafana-map-plugin/dashboards/map.json new file mode 100755 index 0000000..2fba37d --- /dev/null +++ b/deploy/grafana-map-plugin/dashboards/map.json @@ -0,0 +1,276 @@ +{ + "dashboard": { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "circleMaxSize": 30, + "circleMinSize": 2, + "cityEnvVariable": "", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "example", + "decimals": 0, + "esMetric": "Count", + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 0 + }, + "hideEmpty": false, + "hideZero": false, + "id": 2, + "initialZoom": "11", + "layersColors": { + "OffStreetParking": "blue" + }, + "layersIcons": { + "OffStreetParking": "car" + }, + "links": [], + "mapCenter": "Custom", + "mapCenterLatitude": "47.3655761", + "mapCenterLongitude": "8.546587188888887", + "maxDataPoints": 1, + "metrics": [], + "renderChart": false, + "showLegend": true, + "stickyLabels": false, + "targets": [ + { + "format": "time_series", + "group": [], + "groupByAliases": [ + "type" + ], + "groupByColumns": [ + "entity_type" + ], + "hide": false, + "metricAggs": [ + { + "alias": "id", + "column": "entity_id", + "type": "raw" + }, + { + "alias": "value", + "column": "availablespotnumber", + "type": "raw" + }, + { + "alias": "longitude", + "column": "longitude(location_centroid)", + "type": "raw" + }, + { + "alias": "latitude", + "column": "latitude(location_centroid)", + "type": "raw" + }, + { + "alias": "created_at", + "column": "time_index", + "type": "raw" + } + ], + "metricColumn": "none", + "rawQuery": false, + "rawSql": "SELECT\n $__time(time_column),\n value1\nFROM\n metric_table\nWHERE\n $__timeFilter(time_column)\n", + "refId": "A", + "resultFormat": "table", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "timeInterval": "auto_gf", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ], + "whereClauses": [] + } + ], + "thresholds": "0,10", + "title": "Map Points", + "type": "grafana-traffic-env-panel", + "unitPlural": "", + "unitSingle": "", + "valueName": "total" + }, + { + "circleMaxSize": 30, + "circleMinSize": 2, + "cityEnvVariable": "", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "example", + "decimals": 0, + "esMetric": "Count", + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 9 + }, + "hideEmpty": false, + "hideZero": false, + "id": 3, + "initialZoom": "11", + "layersColors": { + "OffStreetParking": "blue" + }, + "layersIcons": { + "OffStreetParking": "car" + }, + "links": [], + "mapCenter": "Custom", + "mapCenterLatitude": "47.3655761", + "mapCenterLongitude": "8.546587188888887", + "maxDataPoints": 1, + "metrics": [], + "renderChart": false, + "showLegend": true, + "stickyLabels": false, + "targets": [ + { + "format": "time_series", + "group": [], + "groupByAliases": [ + "type" + ], + "groupByColumns": [ + "entity_type" + ], + "hide": false, + "metricAggs": [ + { + "alias": "id", + "column": "entity_id", + "type": "raw" + }, + { + "alias": "value", + "column": "availablespotnumber", + "type": "raw" + }, + { + "alias": "geojson", + "column": "location", + "type": "raw" + }, + { + "alias": "created_at", + "column": "time_index", + "type": "raw" + } + ], + "metricColumn": "none", + "rawQuery": false, + "rawSql": "SELECT\n $__time(time_column),\n value1\nFROM\n metric_table\nWHERE\n $__timeFilter(time_column)\n", + "refId": "A", + "resultFormat": "table", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "timeInterval": "auto_gf", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ], + "whereClauses": [] + } + ], + "thresholds": "0,10", + "title": "Map GeoJson", + "type": "grafana-traffic-env-panel", + "unitPlural": "", + "unitSingle": "", + "valueName": "total" + } + ], + "schemaVersion": 16, + "style": "dark", + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-5y", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "Map Dashboard", + "version": 3 + }, + "folderId": 0, + "overwrite": true +} \ No newline at end of file diff --git a/deploy/grafana-map-plugin/data_sources/crate.json b/deploy/grafana-map-plugin/data_sources/crate.json new file mode 100755 index 0000000..cf49ed0 --- /dev/null +++ b/deploy/grafana-map-plugin/data_sources/crate.json @@ -0,0 +1,23 @@ +{ + "id": 3, + "orgId": 1, + "name": "example", + "type": "crate-datasource", + "typeLogoUrl": "public/plugins/crate-datasource/img/crate_logo.png", + "access": "proxy", + "url": "http://crate:4200", + "password": "", + "user": "", + "database": "", + "basicAuth": false, + "isDefault": false, + "jsonData": { + "keepCookies": [], + "schema": "doc", + "table": "example", + "timeColumn": "time_index", + "timeInterval": "auto_gf", + "tlsSkipVerify": true + }, + "readOnly": false +} \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/CHANGELOG.md b/deploy/grafana-map-plugin/dist/CHANGELOG.md new file mode 100755 index 0000000..72456e8 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/CHANGELOG.md @@ -0,0 +1,118 @@ +# Changelog + +## v1.3.1 +- Map centered at location updated when changing coordinates. + +## v1.3.0 +- New option for centering map at user geolocation + +## v1.2.0 +- Suport for leaflet markercluster +- Suport for leaflet sleep to avoid auto scroll when hover big dashboards. +- Resize panel improvements for mobile. +- min zoom level set to 3. + +## v1.1.0 +- In the editor metrics tab, a query result can be 'format as' 'table' + +## v1.0.0 + +### New features / Fix +- Changed the plugin's working process. Any datasource query with a group by clause will result in layers. +- Map rendering faster. +- Removal of polylines for data point of type traffic flow observed. +- Data points of type air quality, traffic flow and other have now distinct shapes (circle, square and triangle). +- Added missing snapshot functionality (Not tested). +- New option on editor for cityenv variable support. If we choose this option the map centers on the selected city. +- Fix problem with multiple map panels in the same dashboard. +- Ability to change the icon associated to the layer (with leaflet.awesome-markers). +- When adding this panel for the first time to a dashboard, metrics are filled with predefined values. +- Dark theme improvements. + +### Development +- Improvements based on grafana development guide best practices. +- New project structure. Improved DRY. +- Updated project packages. Leaflet version updated from 0.7 to 1.3. +- Updated project packages. Highcharts updated from 5.0.15 to 6.1.0. +- Fix app bugs introduced by Leaflet update. +- Gruntfile improvements. + +## v0.1.0 + +- Project structure improvements. Leaflet and highstock went out from project src and are now a dependency. +- Support for light and dark themes. +- From now on this file contents are reverse ordered to get last features on top. + +## v0.0.2 + +- Fixes bug where time series with a country code not found in the country data crashes the panel. +- Adds some extra country codes to the country data to be more similar to the MaxMind Country database. + +## v0.0.3 + +- Support for lowercase country codes for non-elasticsearch datasources. + +## v0.0.4 + +- Fixes snapshotting. + +## v.0.0.5 + +- Adds support for json and jsonp endpoints for location data. + +## v.0.0.6 + +- Adds decimal places option for data values in circle popovers. + +## v.0.0.7 + +- Updates tile map urls to https to avoid mixed content warnings on https sites. + +## v.0.0.8 + +- Saves location data in the dashboard json when snapshotting. This means snapshots should work even when using a custom endpoint for returning a location data json file. + +## v.0.0.9 + +- Fixes bug that meant location data did not refresh after being changed in the editor. It required the page to be refreshed to reload it. + +## v.0.0.10 + +- Performance fix for snapshotting. Sets maxdatapoints to 1 to minimize data that needs to be saved in the snapshot. + +## v.0.0.11 + +- Zoom issue fix and adds a states options for USA states location data. + +## v.0.0.12 + +- Fixes [issue with the JSON endpoint not working](https://github.com/grafana/worldmap-panel/issues/22) + +## v.0.0.13 + +- New location data option -> table data. Location data can now come from data sources other than graphite and Elasticsearch (InfluxDb for example). See table data instructions above on how to use it. + +## v.0.0.14 + +- Various [bug](https://github.com/grafana/worldmap-panel/pull/31) [fixes](https://github.com/grafana/worldmap-panel/pull/32) provided by [linkslice](https://github.com/linkslice) (Thank you!) + +## v.0.0.15 + +- Fix for change in Grafana that [breaks Worldmap panels using Geohash or Table Data](https://github.com/grafana/worldmap-panel/issues/45). + +## v.0.0.16 + +- Option for sticky labels. Fix for https://github.com/grafana/worldmap-panel/issues/27 + +- Ability to hide null or 0 values. Fix for https://github.com/grafana/worldmap-panel/issues/13 + +- Background color change. Fixes https://github.com/grafana/worldmap-panel/issues/36 + +- Dynamic thresholds implemented by [Sam Hatchett](https://github.com/samhatchett). Can now have more than 2 threshold values. Thanks! Fixes https://github.com/grafana/worldmap-panel/issues/25 + +- Validation and default values for option fields. Fixes https://github.com/grafana/worldmap-panel/issues/29 + +## v.0.0.17 + +- Adds Country data with 3-letter country codes. + diff --git a/deploy/grafana-map-plugin/dist/LICENSE b/deploy/grafana-map-plugin/dist/LICENSE new file mode 100755 index 0000000..4644c8c --- /dev/null +++ b/deploy/grafana-map-plugin/dist/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Grafana + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/deploy/grafana-map-plugin/dist/README.md b/deploy/grafana-map-plugin/dist/README.md new file mode 100755 index 0000000..7f32a7c --- /dev/null +++ b/deploy/grafana-map-plugin/dist/README.md @@ -0,0 +1,8 @@ +# Grafana Map Plugin + +Map views of your Time Series datasources. + +Use this plugin if you want: + +- A representation of your geolocated data in one map panel with your points represented as markers. +- Analyse the historical timeline data using a line chart. \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/css/worldmap-panel.css b/deploy/grafana-map-plugin/dist/css/worldmap-panel.css new file mode 100755 index 0000000..030714f --- /dev/null +++ b/deploy/grafana-map-plugin/dist/css/worldmap-panel.css @@ -0,0 +1,291 @@ +/*do not show at start*/ +.map-panel .hidden { + display: none; +} + + +@font-face { + font-family:Font Awesome\ 5 Free; + font-style:normal; + font-weight:900; + src:url(../vendor/fontawesome-free/webfonts/fa-solid-900.eot?v=5.11.2); + src:url(../vendor/fontawesome-free/webfonts/fa-solid-900.eot?#iefix&v=5.11.2) format("embedded-opentype"), + url(../vendor/fontawesome-free/webfonts/fa-solid-900.woff2?v=5.11.2) format("woff2"), + url(../vendor/fontawesome-free/webfonts/fa-solid-900.woff?v=5.11.2) format("woff"), + url(../vendor/fontawesome-free/webfonts/fa-solid-900.ttf?v=5.11.2) format("truetype"), + url(../vendor/fontawesome-free/webfonts/fa-solid-900.svg?v=5.11.2#fontawesomeregular) format("svg"); +} + +.fas { + font-family:Font Awesome\ 5 Free; + font-weight:900; + font-style:normal; +} + +.map-container { + /*height: 500px;*/ +} + +.map-container .info { + padding: 6px 8px; + font: 14px/16px Arial, Helvetica, sans-serif; + /* + background: white; + background: rgba(255,255,255,0.8); + */ + box-shadow: 0 0 15px rgba(0,0,0,0.2); + border-radius: 5px; +} +.map-container .info h4 { + margin: 0 0 5px; + color: #777; +} + +.map-container .legend { + line-height: 18px; + color: #555; +} +.map-container .legend i { + width: 18px; + height: 18px; + float: left; + margin-right: 8px; + opacity: 0.7; +} + +/*Leaflet map*/ +.map-container .worldmap-popup .leaflet-popup-content-wrapper, .worldmap-popup .leaflet-popup-tip { + border-radius: 3px; +} +.map-container .leaflet-top.leaflet-left, .leaflet-bottom.leaflet-left, .leaflet-bottom.leaflet-right { + z-index: 100; +} + +.map-container .worldmap-popup .stycky-popup-info { + display: table; +} + +.map-container .worldmap-popup .stycky-popup-info .head { + font-weight: bolder; + margin-bottom: 5px; + font-size: 15px; + text-align: center; +} + +.map-container .worldmap-popup .stycky-popup-info .body div { + display: table-row; +} +.map-container .worldmap-popup .stycky-popup-info .body div span { + display: table-cell; +} + +.map-container .worldmap-popup .stycky-popup-info .body div span:nth-child(1) { + font-weight: bolder; + font-style: italic; + padding-right: 10px; +} +/*---------------------------ADDED-------------------------------------*/ + +.map-container .map-container-popups > div { + z-index: 1000; +} + +.map-container .values-ranges-legend { + right: 10px; + bottom: 10px; + position: absolute; + border-radius: 2px; +} + +.map-container .measures-table { + width: 200px; + height: auto; + max-height: 350px; + position: absolute; + bottom: 10px; + left: 10px; + overflow-y: auto; + border-radius: 2px; +} +.map-container .health-concerns-wrapper { + border-radius: 2px; + width: 400px; + max-height: 110px; + height: auto; + position: absolute; + top: 10px; + left: 10px; +} +.map-container .health-concerns-wrapper > div.body { + width: 100%; + height: 100%; + overflow-y: auto; + padding: 2px; + border-radius: 2px; + text-align: justify; + padding: 5px; +} + +.map-container .health-risk { + padding-top: 3px; + font-size: 100%; +} + +.map-container table { + font-family: arial, sans-serif; + border-collapse: collapse; + width: 100%; +} + +.map-container td, .map-container th { + text-align: left; + padding: 8px; +/* color: black;*/ +} + +.map-container .map-container-popups .info-container>.header { + text-align: center; + /*color: black;*/ + font-weight: bold; + padding: 6px; +} +.map-container .map-container-popups .info-container>.header-left { + text-align: left !important; +} +.map-container .map-container-popups .info-container>.header>span { + float: right; +} +.map-container .map-container-popups .info-container>.header>span>span.color { + padding: 3px; +} + +.map-container .map-container-popups table.intensity-scale tr > td { + padding: 6px 8px; +} +.map-container .map-container-popups table.intensity-scale tr > td > span { + padding: 8px 3px; +} +.map-container .map-container-popups table.intensity-scale tr > td > span:nth-child(1) { + margin-right: 3px; +} + +/*levels of intensity*/ +.map-marker-level-0, .map-container .map-container-popups table.intensity-scale tr.level-0 > td:nth-child(2) > span:nth-child(1) { + background-color: #00e400; +} +.map-marker-level-1, .map-container .map-container-popups table.intensity-scale tr.level-1 > td:nth-child(2) > span:nth-child(1) { + background-color: #fdca92; +} +.map-marker-level-2, .map-container .map-container-popups table.intensity-scale tr.level-2 > td:nth-child(2) > span:nth-child(1) { + background-color: #ff7e00; +} +.map-marker-level-3, .map-container .map-container-popups table.intensity-scale tr.level-3 > td:nth-child(2) > span:nth-child(1) { + background-color: #d41c32; +} +.map-marker-level-4, .map-container .map-container-popups table.intensity-scale tr.level-4 > td:nth-child(2) > span:nth-child(1) { + background-color: #7e0023; +} +.map-marker-level-5, .map-container .map-container-popups table.intensity-scale tr.level-5 > td:nth-child(2) > span:nth-child(1) { + background-color: #8f3f97; +} + +.map-marker-default { + background-color: #00e400; +} + +.stycky-popup-info .body{ + display: table; + width: 100%; +} + +.stycky-popup-info .body .popup-single-value .name { + display: none !important; +} + +.stycky-popup-info .body .popup-single-value .value { + font-size: 40px; + display: inline-block !important; +} + +.stycky-popup-info .body .popup-single-value .unit { + font-size: 15px; + display: inline-block !important; +} + +.stycky-popup-info .body .name { + margin-left: 5px; + margin-right: 5px; +} + +.stycky-popup-info .body .value { + margin-left: 5px; + margin-right: 5px; +} + +.stycky-popup-info .body .unit { + margin-left: 5px; + margin-right: 5px; +} + +.stycky-popup-info .body .popup-single-value { + text-align: center; + display: block !important; +} + +.stycky-popup-info .body .popup-multi-value { + text-align: center; +} + +.map-container .worldmap-popup .stycky-popup-info .foot { + font-weight: bolder; + text-align: right; + margin-top: 5px; +} + +.stycky-popup-info .foot .name { + display: none !important; +} + +.stycky-popup-info .foot .unit { + display: none !important; +} + +.chart-container { + width: 100%; + /*height: 360px;*/ + margin-top: 1%; + z-index: 100; + position: relative; +} +.chart-container .data-details { +/* margin-bottom: 5px;*/ +} + +.empty-space-margin { + margin-right:3px; +} + +.oc-cluster { + background-clip: padding-box; + border-radius: 20px; +} + +.oc-cluster div { + width: 40px; + height: 40px; + margin-left: 5px; + margin-top: 5px; + + text-align: center; + border-radius: 20px; + font: 12px "Helvetica Neue", Arial, Helvetica, sans-serif; + color: white; +} + +.oc-cluster span.double { + line-height: 20px; +} + +.oc-cluster span.single { + line-height: 40px; +} \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/css/worldmap.dark.css b/deploy/grafana-map-plugin/dist/css/worldmap.dark.css new file mode 100755 index 0000000..299b11b --- /dev/null +++ b/deploy/grafana-map-plugin/dist/css/worldmap.dark.css @@ -0,0 +1,79 @@ +/*Leaflet Specific*/ +.map-container .map-darken img.leaflet-tile { + -webkit-filter: brightness(1.6) grayscale(1) contrast(1); + filter: brightness(1.6) grayscale(1) contrast(1); +} + +.map-container .leaflet-container .leaflet-control-attribution, +.map-container .leaflet-control-scale-line, +/*.map-container .leaflet-div-icon,*/ +.map-container .leaflet-control-layers-expanded { + background-color: #333; +} + +.map-container .worldmap-popup .leaflet-popup-content-wrapper, +.map-container .worldmap-popup .leaflet-popup-tip, +.map-container .leaflet-control-layers, +.map-container .leaflet-control-zoom a { + background-color: #333; + color: white; +} + +.leaflet-touch .leaflet-control-layers, +.leaflet-touch .leaflet-bar { + border: 1px solid black !important; +} + +/*map popups specific*/ +.map-container table tr, +.map-container .info-container { + color: white; +} + +.map-container table.stripes tbody > tr:nth-child(odd) { + background-color: #181819; +} +.map-container table.stripes tbody > tr:nth-child(even) { + background-color: #212124; +} + +.map-container .info-container { + border: grey solid 1px; +} + +.map-container thead > tr, +.map-container .info-container { + background-color: #212124; +} + +.map-container .info-container .header { +} +.map-container .info-container .body { +} + + +/*highcharts customization*/ +.chart-container .highcharts-button-box { + color: white; + fill: #333; + stroke: #181819; +} +.chart-container .highcharts-reset-zoom > text { + /*color: white;*/ + fill: white !important; +/* stroke: white;*/ +} + +.chart-container .highcharts-menu { + box-shadow: none !important; + background-color: #181819 !important; +} + +.chart-container .highcharts-menu .highcharts-menu-item { + color: white !important; +} + +.chart-container .parameters-dropdown { + /*border: 1px solid #171819;*/ + background-color: #181819; +} diff --git a/deploy/grafana-map-plugin/dist/css/worldmap.light.css b/deploy/grafana-map-plugin/dist/css/worldmap.light.css new file mode 100755 index 0000000..e234850 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/css/worldmap.light.css @@ -0,0 +1,21 @@ +.map-container .worldmap-popup .leaflet-popup-content-wrapper, .worldmap-popup .leaflet-popup-tip { + background-color: #ECECEC; +} + +.map-container table.stripes tbody tr:nth-child(odd) { + background-color: #E6E6E6; +} +.map-container table.stripes tbody > tr:nth-child(even) { + background-color: white; +} + +.map-container .info-container { + border: grey solid 1px; +} + +.map-container table.stripes tbody > tr { + color: black; +} +.map-container thead > tr, .map-container .info-container .header, .map-container .info-container .body { + background-color: white; +} diff --git a/deploy/grafana-map-plugin/dist/definitions.js b/deploy/grafana-map-plugin/dist/definitions.js new file mode 100755 index 0000000..07caf94 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/definitions.js @@ -0,0 +1,158 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.CLUSTER_TYPES = exports.COLOR_TYPES = exports.MARKER_COLORS = exports.ICON_TYPES = exports.MAP_LOCATIONS = exports.DEFAULT_METRICS = exports.TILE_SERVERS = exports.NOMINATIM_ADDRESS = exports.PANEL_DEFAULTS = exports.PLUGIN_PATH = void 0; +var PLUGIN_PATH = 'public/plugins/grafana-traffic-env-panel/'; +exports.PLUGIN_PATH = PLUGIN_PATH; +var MARKER_COLORS = ['red', 'blue', 'green', 'purple', 'orange', 'darkred', 'lightred', 'beige', 'darkblue', 'darkgreen', 'cadetblue', 'darkpurple', 'white', 'pink', 'lightblue', 'lightgreen', 'gray', 'black', 'lightgray']; +exports.MARKER_COLORS = MARKER_COLORS; +var DEFAULT_MARKER_COLORS_RANGE = { + range: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180], + markerColor: MARKER_COLORS +}; +var TILE_SERVERS = { + 'CartoDB Positron': { + url: 'https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png', + attribution: '© OpenStreetMap © CartoDB', + subdomains: 'abcd' + }, + 'CartoDB Dark': { + url: 'https://cartodb-basemaps-{s}.global.ssl.fastly.net/dark_all/{z}/{x}/{y}.png', + attribution: '© OpenStreetMap © CartoDB', + subdomains: 'abcd' + } +}; +exports.TILE_SERVERS = TILE_SERVERS; +var COLOR_TYPES = ['fix', 'threshold']; +exports.COLOR_TYPES = COLOR_TYPES; +var CLUSTER_TYPES = ['none', 'count', 'average', 'total']; +exports.CLUSTER_TYPES = CLUSTER_TYPES; +var ICON_TYPES = ['none', 'address-book', 'address-book-o', 'address-card', 'address-card-o', 'adjust', 'adn', 'align-center', 'align-justify', 'align-left', 'align-right', 'amazon', 'ambulance', 'american-sign-language-interpreting', 'anchor', 'android', 'angellist', 'angle-double-down', 'angle-double-left', 'angle-double-right', 'angle-double-up', 'angle-down', 'angle-left', 'angle-right', 'angle-up', 'apple', 'archive', 'area-chart', 'arrow-circle-down', 'arrow-circle-left', 'arrow-circle-o-down', 'arrow-circle-o-left', 'arrow-circle-o-right', 'arrow-circle-o-up', 'arrow-circle-right', 'arrow-circle-up', 'arrow-down', 'arrow-left', 'arrow-right', 'arrow-up', 'arrows', 'arrows-alt', 'arrows-h', 'arrows-v', 'asl-interpreting', 'assistive-listening-systems', 'asterisk', 'at', 'audio-description', 'automobile', 'backward', 'balance-scale', 'ban', 'bandcamp', 'bank', 'bar-chart', 'bar-chart-o', 'barcode', 'bars', 'bath', 'bathtub', 'battery', 'battery-0', 'battery-1', 'battery-2', 'battery-3', 'battery-4', 'battery-empty', 'battery-full', 'battery-half', 'battery-quarter', 'battery-three-quarters', 'bed', 'beer', 'behance', 'behance-square', 'bell', 'bell-o', 'bell-slash', 'bell-slash-o', 'bicycle', 'binoculars', 'birthday-cake', 'bitbucket', 'bitbucket-square', 'bitcoin', 'black-tie', 'blind', 'bluetooth', 'bluetooth-b', 'bold', 'bolt', 'bomb', 'book', 'bookmark', 'bookmark-o', 'braille', 'briefcase', 'btc', 'bug', 'building', 'building-o', 'bullhorn', 'bullseye', 'bus', 'buysellads', 'cab', 'calculator', 'calendar', 'calendar-check-o', 'calendar-minus-o', 'calendar-o', 'calendar-plus-o', 'calendar-times-o', 'camera', 'camera-retro', 'car', 'caret-down', 'caret-left', 'caret-right', 'caret-square-o-down', 'caret-square-o-left', 'caret-square-o-right', 'caret-square-o-up', 'caret-up', 'cart-arrow-down', 'cart-plus', 'cc', 'cc-amex', 'cc-diners-club', 'cc-discover', 'cc-jcb', 'cc-mastercard', 'cc-paypal', 'cc-stripe', 'cc-visa', 'certificate', 'chain', 'chain-broken', 'check', 'check-circle', 'check-circle-o', 'check-square', 'check-square-o', 'chevron-circle-down', 'chevron-circle-left', 'chevron-circle-right', 'chevron-circle-up', 'chevron-down', 'chevron-left', 'chevron-right', 'chevron-up', 'child', 'chrome', 'circle', 'circle-o', 'circle-o-notch', 'circle-thin', 'clipboard', 'clock-o', 'clone', 'close', 'cloud', 'cloud-download', 'cloud-upload', 'cny', 'code', 'code-fork', 'codepen', 'codiepie', 'coffee', 'cog', 'cogs', 'columns', 'comment', 'comment-o', 'commenting', 'commenting-o', 'comments', 'comments-o', 'compass', 'compress', 'connectdevelop', 'contao', 'copy', 'copyright', 'creative-commons', 'credit-card', 'credit-card-alt', 'crop', 'crosshairs', 'css3', 'cube', 'cubes', 'cut', 'cutlery', 'dashboard', 'dashcube', 'database', 'deaf', 'deafness', 'dedent', 'delicious', 'desktop', 'deviantart', 'diamond', 'digg', 'dollar', 'dot-circle-o', 'download', 'dribbble', 'drivers-license', 'drivers-license-o', 'dropbox', 'drupal', 'edge', 'edit', 'eercast', 'eject', 'ellipsis-h', 'ellipsis-v', 'empire', 'envelope', 'envelope-o', 'envelope-open', 'envelope-open-o', 'envelope-square', 'envira', 'eraser', 'etsy', 'eur', 'euro', 'exchange', 'exclamation', 'exclamation-circle', 'exclamation-triangle', 'expand', 'expeditedssl', 'external-link', 'external-link-square', 'eye', 'eye-slash', 'eyedropper', 'fa', 'facebook', 'facebook-f', 'facebook-official', 'facebook-square', 'fast-backward', 'fast-forward', 'fax', 'feed', 'female', 'fighter-jet', 'file', 'file-archive-o', 'file-audio-o', 'file-code-o', 'file-excel-o', 'file-image-o', 'file-movie-o', 'file-o', 'file-pdf-o', 'file-photo-o', 'file-picture-o', 'file-powerpoint-o', 'file-sound-o', 'file-text', 'file-text-o', 'file-video-o', 'file-word-o', 'file-zip-o', 'files-o', 'film', 'filter', 'fire', 'fire-extinguisher', 'firefox', 'first-order', 'flag', 'flag-checkered', 'flag-o', 'flash', 'flask', 'flickr', 'floppy-o', 'folder', 'folder-o', 'folder-open', 'folder-open-o', 'font', 'font-awesome', 'fonticons', 'fort-awesome', 'forumbee', 'forward', 'foursquare', 'free-code-camp', 'frown-o', 'futbol-o', 'gamepad', 'gavel', 'gbp', 'ge', 'gear', 'gears', 'genderless', 'get-pocket', 'gg', 'gg-circle', 'gift', 'git', 'git-square', 'github', 'github-alt', 'github-square', 'gitlab', 'gittip', 'glass', 'glide', 'glide-g', 'globe', 'google', 'google-plus', 'google-plus-circle', 'google-plus-official', 'google-plus-square', 'google-wallet', 'graduation-cap', 'gratipay', 'grav', 'group', 'h-square', 'hacker-news', 'hand-grab-o', 'hand-lizard-o', 'hand-o-down', 'hand-o-left', 'hand-o-right', 'hand-o-up', 'hand-paper-o', 'hand-peace-o', 'hand-pointer-o', 'hand-rock-o', 'hand-scissors-o', 'hand-spock-o', 'hand-stop-o', 'handshake-o', 'hard-of-hearing', 'hashtag', 'hdd-o', 'header', 'headphones', 'heart', 'heart-o', 'heartbeat', 'history', 'home', 'hospital-o', 'hotel', 'hourglass', 'hourglass-1', 'hourglass-2', 'hourglass-3', 'hourglass-end', 'hourglass-half', 'hourglass-o', 'hourglass-start', 'houzz', 'html5', 'i-cursor', 'id-badge', 'id-card', 'id-card-o', 'ils', 'image', 'imdb', 'inbox', 'indent', 'industry', 'info', 'info-circle', 'inr', 'instagram', 'institution', 'internet-explorer', 'intersex', 'ioxhost', 'italic', 'joomla', 'jpy', 'jsfiddle', 'key', 'keyboard-o', 'krw', 'language', 'laptop', 'lastfm', 'lastfm-square', 'leaf', 'leanpub', 'legal', 'lemon-o', 'level-down', 'level-up', 'life-bouy', 'life-buoy', 'life-ring', 'life-saver', 'lightbulb-o', 'line-chart', 'link', 'linkedin', 'linkedin-square', 'linode', 'linux', 'list', 'list-alt', 'list-ol', 'list-ul', 'location-arrow', 'lock', 'long-arrow-down', 'long-arrow-left', 'long-arrow-right', 'long-arrow-up', 'low-vision', 'magic', 'magnet', 'mail-forward', 'mail-reply', 'mail-reply-all', 'male', 'map', 'map-marker', 'map-o', 'map-pin', 'map-signs', 'mars', 'mars-double', 'mars-stroke', 'mars-stroke-h', 'mars-stroke-v', 'maxcdn', 'meanpath', 'medium', 'medkit', 'meetup', 'meh-o', 'mercury', 'microchip', 'microphone', 'microphone-slash', 'minus', 'minus-circle', 'minus-square', 'minus-square-o', 'mixcloud', 'mobile', 'mobile-phone', 'modx', 'money', 'moon-o', 'mortar-board', 'motorcycle', 'mouse-pointer', 'music', 'navicon', 'neuter', 'number', 'newspaper-o', 'object-group', 'object-ungroup', 'odnoklassniki', 'odnoklassniki-square', 'opencart', 'openid', 'opera', 'optin-monster', 'outdent', 'pagelines', 'paint-brush', 'paper-plane', 'paper-plane-o', 'paperclip', 'paragraph', 'paste', 'pause', 'pause-circle', 'pause-circle-o', 'paw', 'paypal', 'pencil', 'pencil-square', 'pencil-square-o', 'percent', 'phone', 'phone-square', 'photo', 'picture-o', 'pie-chart', 'pied-piper', 'pied-piper-alt', 'pied-piper-pp', 'pinterest', 'pinterest-p', 'pinterest-square', 'plane', 'play', 'play-circle', 'play-circle-o', 'plug', 'plus', 'plus-circle', 'plus-square', 'plus-square-o', 'podcast', 'power-off', 'print', 'product-hunt', 'puzzle-piece', 'qq', 'qrcode', 'question', 'question-circle', 'question-circle-o', 'quora', 'quote-left', 'quote-right', 'ra', 'random', 'ravelry', 'rebel', 'recycle', 'reddit', 'reddit-alien', 'reddit-square', 'refresh', 'registered', 'remove', 'renren', 'reorder', 'repeat', 'reply', 'reply-all', 'resistance', 'retweet', 'rmb', 'road', 'rocket', 'rotate-left', 'rotate-right', 'rouble', 'rss', 'rss-square', 'rub', 'ruble', 'rupee', 's15', 'safari', 'save', 'scissors', 'scribd', 'search', 'search-minus', 'search-plus', 'sellsy', 'send', 'send-o', 'server', 'share', 'share-alt', 'share-alt-square', 'share-square', 'share-square-o', 'shekel', 'sheqel', 'shield', 'ship', 'shirtsinbulk', 'shopping-bag', 'shopping-basket', 'shopping-cart', 'shower', 'sign-in', 'sign-language', 'sign-out', 'signal', 'signing', 'simplybuilt', 'sitemap', 'skyatlas', 'skype', 'slack', 'sliders', 'slideshare', 'smile-o', 'snapchat', 'snapchat-ghost', 'snapchat-square', 'snowflake-o', 'soccer-ball-o', 'sort', 'sort-alpha-asc', 'sort-alpha-desc', 'sort-amount-asc', 'sort-amount-desc', 'sort-asc', 'sort-desc', 'sort-down', 'sort-numeric-asc', 'sort-numeric-desc', 'sort-up', 'soundcloud', 'space-shuttle', 'spinner', 'spoon', 'spotify', 'square', 'square-o', 'stack-exchange', 'stack-overflow', 'star', 'star-half', 'star-half-empty', 'star-half-full', 'star-half-o', 'star-o', 'steam', 'steam-square', 'step-backward', 'step-forward', 'stethoscope', 'sticky-note', 'sticky-note-o', 'stop', 'stop-circle', 'stop-circle-o', 'street-view', 'strikethrough', 'stumbleupon', 'stumbleupon-circle', 'subscript', 'subway', 'suitcase', 'sun-o', 'superpowers', 'superscript', 'support', 'table', 'tablet', 'tachometer', 'tag', 'tags', 'tasks', 'taxi', 'telegram', 'television', 'tencent-weibo', 'terminal', 'text-height', 'text-width', 'th', 'th-large', 'th-list', 'themeisle', 'thermometer', 'thermometer-0', 'thermometer-1', 'thermometer-2', 'thermometer-3', 'thermometer-4', 'thermometer-empty', 'thermometer-full', 'thermometer-half', 'thermometer-quarter', 'thermometer-three-quarters', 'thumb-tack', 'thumbs-down', 'thumbs-o-down', 'thumbs-o-up', 'thumbs-up', 'ticket', 'times', 'times-circle', 'times-circle-o', 'times-rectangle', 'times-rectangle-o', 'tint', 'toggle-down', 'toggle-left', 'toggle-off', 'toggle-on', 'toggle-right', 'toggle-up', 'trademark', 'train', 'transgender', 'transgender-alt', 'trash', 'trash-o', 'tree', 'trello', 'tripadvisor', 'trophy', 'truck', 'try', 'tty', 'tumblr', 'tumblr-square', 'turkish-lira', 'tv', 'twitch', 'twitter', 'twitter-square', 'umbrella', 'underline', 'undo', 'universal-access', 'university', 'unlink', 'unlock', 'unlock-alt', 'unsorted', 'upload', 'usb', 'usd', 'user', 'user-circle', 'user-circle-o', 'user-md', 'user-o', 'user-plus', 'user-secret', 'user-times', 'users', 'vcard', 'vcard-o', 'venus', 'venus-double', 'venus-mars', 'viacoin', 'viadeo', 'viadeo-square', 'video-camera', 'vimeo', 'vimeo-square', 'vine', 'vk', 'volume-control-phone', 'volume-down', 'volume-off', 'volume-up', 'warning', 'wechat', 'weibo', 'weixin', 'whatsapp', 'wheelchair', 'wheelchair-alt', 'wifi', 'wikipedia-w', 'window-close', 'window-close-o', 'window-maximize', 'window-minimize', 'window-restore', 'windows', 'won', 'wordpress', 'wpbeginner', 'wpexplorer', 'wpforms', 'wrench', 'xing', 'xing-square', 'y-combinator', 'y-combinator-square', 'yahoo', 'yc', 'yc-square', 'yelp', 'yen', 'yoast', 'youtube', 'youtube-play']; +exports.ICON_TYPES = ICON_TYPES; +var PANEL_DEFAULTS = { + maxDataPoints: 1, + mapCenter: '(0°, 0°)', + mapCenterLatitude: 0, + mapCenterLongitude: 0, + initialZoom: 1, + disableClusterLevel: 21, + valueName: 'total', + circleMinSize: 2, + circleMaxSize: 30, + thresholds: '0,10', + colors: ['rgba(245, 54, 54, 0.9)', 'rgba(237, 129, 40, 0.89)', 'rgba(50, 172, 45, 0.97)'], + unitSingle: '', + unitPlural: '', + showLegend: true, + esMetric: 'Count', + decimals: 0, + hideEmpty: false, + hideZero: false, + stickyLabels: false, + minZoomShapes: 12, + metrics: [], + targets: [{ + refId: 'A', + resultFormat: 'table', + groupByAliases: ['type'], + groupByColumns: ['entity_type'], + whereClauses: [], + metricAggs: [{ + alias: 'id', + column: 'entity_id', + type: 'raw' + }, { + alias: 'value', + column: 'availablespotnumber', + type: 'raw' + }, { + alias: 'geojson', + column: 'location', + type: 'raw' + }, { + alias: 'created_at', + column: 'time_index', + type: 'raw' + }] + }], + layersIcons: {}, + layersColors: {}, + layersColorType: {}, + layersClusterType: {}, + layersColorsHigh: {}, + layersColorsMedium: {}, + layersColorsLow: {}, + layersColorsThresholds: {}, + layersColorsBinding: {}, + layersVariables: {}, + cityEnvVariable: '', + buildings: false +}; +exports.PANEL_DEFAULTS = PANEL_DEFAULTS; +var DEFAULT_METRICS = { + 'aqi': { + 'name': 'Air Quality Index', + 'unit': '' + }, + 'h': { + 'name': 'Hydrogen', + 'unit': '' + }, + 'no2': { + 'name': 'Nitrogen Dioxide', + 'unit': 'µg/m3' + }, + 'p': { + 'name': 'Pressure', + 'unit': 'hPa' + }, + 'pm10': { + 'name': 'PM10', + 'unit': 'ug/m3' + }, + 'pm25': { + 'name': 'PM25', + 'unit': 'ug/m3' + }, + 't': { + 'name': 'Temperature', + 'unit': 'ºC' + }, + 'co': { + 'name': 'CO2', + 'unit': '' + }, + 'intensity': { + 'name': 'Intensity', + 'unit': '' + } +}; +exports.DEFAULT_METRICS = DEFAULT_METRICS; +var MAP_LOCATIONS = { + '(0°, 0°)': { + mapCenterLatitude: 0.0, + mapCenterLongitude: 0.0 + }, + 'North America': { + mapCenterLatitude: 40, + mapCenterLongitude: -100 + }, + 'Europe': { + mapCenterLatitude: 46, + mapCenterLongitude: 14 + }, + 'West Asia': { + mapCenterLatitude: 26, + mapCenterLongitude: 53 + }, + 'SE Asia': { + mapCenterLatitude: 10, + mapCenterLongitude: 106 + } +}; +exports.MAP_LOCATIONS = MAP_LOCATIONS; +var NOMINATIM_ADDRESS = 'https://nominatim.openstreetmap.org/search/?format=json&addressdetails=0&limit=1&polygon_svg=0'; +exports.NOMINATIM_ADDRESS = NOMINATIM_ADDRESS; +//# sourceMappingURL=definitions.js.map diff --git a/deploy/grafana-map-plugin/dist/definitions.js.map b/deploy/grafana-map-plugin/dist/definitions.js.map new file mode 100755 index 0000000..417db6c --- /dev/null +++ b/deploy/grafana-map-plugin/dist/definitions.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/definitions.js"],"names":["PLUGIN_PATH","MARKER_COLORS","DEFAULT_MARKER_COLORS_RANGE","range","markerColor","TILE_SERVERS","url","attribution","subdomains","COLOR_TYPES","CLUSTER_TYPES","ICON_TYPES","PANEL_DEFAULTS","maxDataPoints","mapCenter","mapCenterLatitude","mapCenterLongitude","initialZoom","disableClusterLevel","valueName","circleMinSize","circleMaxSize","thresholds","colors","unitSingle","unitPlural","showLegend","esMetric","decimals","hideEmpty","hideZero","stickyLabels","minZoomShapes","metrics","targets","refId","resultFormat","groupByAliases","groupByColumns","whereClauses","metricAggs","alias","column","type","layersIcons","layersColors","layersColorType","layersClusterType","layersColorsHigh","layersColorsMedium","layersColorsLow","layersColorsThresholds","layersColorsBinding","layersVariables","cityEnvVariable","buildings","DEFAULT_METRICS","MAP_LOCATIONS","NOMINATIM_ADDRESS"],"mappings":"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","sourcesContent":["const PLUGIN_PATH = 'public/plugins/grafana-traffic-env-panel/';\n\nconst MARKER_COLORS = ['red', 'blue', 'green', 'purple', 'orange', 'darkred', 'lightred', 'beige',\n 'darkblue', 'darkgreen', 'cadetblue', 'darkpurple', 'white', 'pink', 'lightblue', 'lightgreen', 'gray', 'black', 'lightgray'];\n\nconst DEFAULT_MARKER_COLORS_RANGE = {\n range: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180],\n markerColor: MARKER_COLORS\n};\n\nconst TILE_SERVERS = {\n 'CartoDB Positron': { url: 'https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png', attribution: '© OpenStreetMap © CartoDB', subdomains: 'abcd'},\n 'CartoDB Dark': {url: 'https://cartodb-basemaps-{s}.global.ssl.fastly.net/dark_all/{z}/{x}/{y}.png', attribution: '© OpenStreetMap © CartoDB', subdomains: 'abcd'}\n};\n\nconst COLOR_TYPES = [\n 'fix',\n 'threshold'\n];\n\nconst CLUSTER_TYPES = [\n 'none',\n 'count',\n 'average',\n 'total'\n];\n\nconst ICON_TYPES = [\n 'none',\n 'address-book',\n 'address-book-o',\n 'address-card',\n 'address-card-o',\n 'adjust',\n 'adn',\n 'align-center',\n 'align-justify',\n 'align-left',\n 'align-right',\n 'amazon',\n 'ambulance',\n 'american-sign-language-interpreting',\n 'anchor',\n 'android',\n 'angellist',\n 'angle-double-down',\n 'angle-double-left',\n 'angle-double-right',\n 'angle-double-up',\n 'angle-down',\n 'angle-left',\n 'angle-right',\n 'angle-up',\n 'apple',\n 'archive',\n 'area-chart',\n 'arrow-circle-down',\n 'arrow-circle-left',\n 'arrow-circle-o-down',\n 'arrow-circle-o-left',\n 'arrow-circle-o-right',\n 'arrow-circle-o-up',\n 'arrow-circle-right',\n 'arrow-circle-up',\n 'arrow-down',\n 'arrow-left',\n 'arrow-right',\n 'arrow-up',\n 'arrows',\n 'arrows-alt',\n 'arrows-h',\n 'arrows-v',\n 'asl-interpreting',\n 'assistive-listening-systems',\n 'asterisk',\n 'at',\n 'audio-description',\n 'automobile',\n 'backward',\n 'balance-scale',\n 'ban',\n 'bandcamp',\n 'bank',\n 'bar-chart',\n 'bar-chart-o',\n 'barcode',\n 'bars',\n 'bath',\n 'bathtub',\n 'battery',\n 'battery-0',\n 'battery-1',\n 'battery-2',\n 'battery-3',\n 'battery-4',\n 'battery-empty',\n 'battery-full',\n 'battery-half',\n 'battery-quarter',\n 'battery-three-quarters',\n 'bed',\n 'beer',\n 'behance',\n 'behance-square',\n 'bell',\n 'bell-o',\n 'bell-slash',\n 'bell-slash-o',\n 'bicycle',\n 'binoculars',\n 'birthday-cake',\n 'bitbucket',\n 'bitbucket-square',\n 'bitcoin',\n 'black-tie',\n 'blind',\n 'bluetooth',\n 'bluetooth-b',\n 'bold',\n 'bolt',\n 'bomb',\n 'book',\n 'bookmark',\n 'bookmark-o',\n 'braille',\n 'briefcase',\n 'btc',\n 'bug',\n 'building',\n 'building-o',\n 'bullhorn',\n 'bullseye',\n 'bus',\n 'buysellads',\n 'cab',\n 'calculator',\n 'calendar',\n 'calendar-check-o',\n 'calendar-minus-o',\n 'calendar-o',\n 'calendar-plus-o',\n 'calendar-times-o',\n 'camera',\n 'camera-retro',\n 'car',\n 'caret-down',\n 'caret-left',\n 'caret-right',\n 'caret-square-o-down',\n 'caret-square-o-left',\n 'caret-square-o-right',\n 'caret-square-o-up',\n 'caret-up',\n 'cart-arrow-down',\n 'cart-plus',\n 'cc',\n 'cc-amex',\n 'cc-diners-club',\n 'cc-discover',\n 'cc-jcb',\n 'cc-mastercard',\n 'cc-paypal',\n 'cc-stripe',\n 'cc-visa',\n 'certificate',\n 'chain',\n 'chain-broken',\n 'check',\n 'check-circle',\n 'check-circle-o',\n 'check-square',\n 'check-square-o',\n 'chevron-circle-down',\n 'chevron-circle-left',\n 'chevron-circle-right',\n 'chevron-circle-up',\n 'chevron-down',\n 'chevron-left',\n 'chevron-right',\n 'chevron-up',\n 'child',\n 'chrome',\n 'circle',\n 'circle-o',\n 'circle-o-notch',\n 'circle-thin',\n 'clipboard',\n 'clock-o',\n 'clone',\n 'close',\n 'cloud',\n 'cloud-download',\n 'cloud-upload',\n 'cny',\n 'code',\n 'code-fork',\n 'codepen',\n 'codiepie',\n 'coffee',\n 'cog',\n 'cogs',\n 'columns',\n 'comment',\n 'comment-o',\n 'commenting',\n 'commenting-o',\n 'comments',\n 'comments-o',\n 'compass',\n 'compress',\n 'connectdevelop',\n 'contao',\n 'copy',\n 'copyright',\n 'creative-commons',\n 'credit-card',\n 'credit-card-alt',\n 'crop',\n 'crosshairs',\n 'css3',\n 'cube',\n 'cubes',\n 'cut',\n 'cutlery',\n 'dashboard',\n 'dashcube',\n 'database',\n 'deaf',\n 'deafness',\n 'dedent',\n 'delicious',\n 'desktop',\n 'deviantart',\n 'diamond',\n 'digg',\n 'dollar',\n 'dot-circle-o',\n 'download',\n 'dribbble',\n 'drivers-license',\n 'drivers-license-o',\n 'dropbox',\n 'drupal',\n 'edge',\n 'edit',\n 'eercast',\n 'eject',\n 'ellipsis-h',\n 'ellipsis-v',\n 'empire',\n 'envelope',\n 'envelope-o',\n 'envelope-open',\n 'envelope-open-o',\n 'envelope-square',\n 'envira',\n 'eraser',\n 'etsy',\n 'eur',\n 'euro',\n 'exchange',\n 'exclamation',\n 'exclamation-circle',\n 'exclamation-triangle',\n 'expand',\n 'expeditedssl',\n 'external-link',\n 'external-link-square',\n 'eye',\n 'eye-slash',\n 'eyedropper',\n 'fa',\n 'facebook',\n 'facebook-f',\n 'facebook-official',\n 'facebook-square',\n 'fast-backward',\n 'fast-forward',\n 'fax',\n 'feed',\n 'female',\n 'fighter-jet',\n 'file',\n 'file-archive-o',\n 'file-audio-o',\n 'file-code-o',\n 'file-excel-o',\n 'file-image-o',\n 'file-movie-o',\n 'file-o',\n 'file-pdf-o',\n 'file-photo-o',\n 'file-picture-o',\n 'file-powerpoint-o',\n 'file-sound-o',\n 'file-text',\n 'file-text-o',\n 'file-video-o',\n 'file-word-o',\n 'file-zip-o',\n 'files-o',\n 'film',\n 'filter',\n 'fire',\n 'fire-extinguisher',\n 'firefox',\n 'first-order',\n 'flag',\n 'flag-checkered',\n 'flag-o',\n 'flash',\n 'flask',\n 'flickr',\n 'floppy-o',\n 'folder',\n 'folder-o',\n 'folder-open',\n 'folder-open-o',\n 'font',\n 'font-awesome',\n 'fonticons',\n 'fort-awesome',\n 'forumbee',\n 'forward',\n 'foursquare',\n 'free-code-camp',\n 'frown-o',\n 'futbol-o',\n 'gamepad',\n 'gavel',\n 'gbp',\n 'ge',\n 'gear',\n 'gears',\n 'genderless',\n 'get-pocket',\n 'gg',\n 'gg-circle',\n 'gift',\n 'git',\n 'git-square',\n 'github',\n 'github-alt',\n 'github-square',\n 'gitlab',\n 'gittip',\n 'glass',\n 'glide',\n 'glide-g',\n 'globe',\n 'google',\n 'google-plus',\n 'google-plus-circle',\n 'google-plus-official',\n 'google-plus-square',\n 'google-wallet',\n 'graduation-cap',\n 'gratipay',\n 'grav',\n 'group',\n 'h-square',\n 'hacker-news',\n 'hand-grab-o',\n 'hand-lizard-o',\n 'hand-o-down',\n 'hand-o-left',\n 'hand-o-right',\n 'hand-o-up',\n 'hand-paper-o',\n 'hand-peace-o',\n 'hand-pointer-o',\n 'hand-rock-o',\n 'hand-scissors-o',\n 'hand-spock-o',\n 'hand-stop-o',\n 'handshake-o',\n 'hard-of-hearing',\n 'hashtag',\n 'hdd-o',\n 'header',\n 'headphones',\n 'heart',\n 'heart-o',\n 'heartbeat',\n 'history',\n 'home',\n 'hospital-o',\n 'hotel',\n 'hourglass',\n 'hourglass-1',\n 'hourglass-2',\n 'hourglass-3',\n 'hourglass-end',\n 'hourglass-half',\n 'hourglass-o',\n 'hourglass-start',\n 'houzz',\n 'html5',\n 'i-cursor',\n 'id-badge',\n 'id-card',\n 'id-card-o',\n 'ils',\n 'image',\n 'imdb',\n 'inbox',\n 'indent',\n 'industry',\n 'info',\n 'info-circle',\n 'inr',\n 'instagram',\n 'institution',\n 'internet-explorer',\n 'intersex',\n 'ioxhost',\n 'italic',\n 'joomla',\n 'jpy',\n 'jsfiddle',\n 'key',\n 'keyboard-o',\n 'krw',\n 'language',\n 'laptop',\n 'lastfm',\n 'lastfm-square',\n 'leaf',\n 'leanpub',\n 'legal',\n 'lemon-o',\n 'level-down',\n 'level-up',\n 'life-bouy',\n 'life-buoy',\n 'life-ring',\n 'life-saver',\n 'lightbulb-o',\n 'line-chart',\n 'link',\n 'linkedin',\n 'linkedin-square',\n 'linode',\n 'linux',\n 'list',\n 'list-alt',\n 'list-ol',\n 'list-ul',\n 'location-arrow',\n 'lock',\n 'long-arrow-down',\n 'long-arrow-left',\n 'long-arrow-right',\n 'long-arrow-up',\n 'low-vision',\n 'magic',\n 'magnet',\n 'mail-forward',\n 'mail-reply',\n 'mail-reply-all',\n 'male',\n 'map',\n 'map-marker',\n 'map-o',\n 'map-pin',\n 'map-signs',\n 'mars',\n 'mars-double',\n 'mars-stroke',\n 'mars-stroke-h',\n 'mars-stroke-v',\n 'maxcdn',\n 'meanpath',\n 'medium',\n 'medkit',\n 'meetup',\n 'meh-o',\n 'mercury',\n 'microchip',\n 'microphone',\n 'microphone-slash',\n 'minus',\n 'minus-circle',\n 'minus-square',\n 'minus-square-o',\n 'mixcloud',\n 'mobile',\n 'mobile-phone',\n 'modx',\n 'money',\n 'moon-o',\n 'mortar-board',\n 'motorcycle',\n 'mouse-pointer',\n 'music',\n 'navicon',\n 'neuter',\n 'number',\n 'newspaper-o',\n 'object-group',\n 'object-ungroup',\n 'odnoklassniki',\n 'odnoklassniki-square',\n 'opencart',\n 'openid',\n 'opera',\n 'optin-monster',\n 'outdent',\n 'pagelines',\n 'paint-brush',\n 'paper-plane',\n 'paper-plane-o',\n 'paperclip',\n 'paragraph',\n 'paste',\n 'pause',\n 'pause-circle',\n 'pause-circle-o',\n 'paw',\n 'paypal',\n 'pencil',\n 'pencil-square',\n 'pencil-square-o',\n 'percent',\n 'phone',\n 'phone-square',\n 'photo',\n 'picture-o',\n 'pie-chart',\n 'pied-piper',\n 'pied-piper-alt',\n 'pied-piper-pp',\n 'pinterest',\n 'pinterest-p',\n 'pinterest-square',\n 'plane',\n 'play',\n 'play-circle',\n 'play-circle-o',\n 'plug',\n 'plus',\n 'plus-circle',\n 'plus-square',\n 'plus-square-o',\n 'podcast',\n 'power-off',\n 'print',\n 'product-hunt',\n 'puzzle-piece',\n 'qq',\n 'qrcode',\n 'question',\n 'question-circle',\n 'question-circle-o',\n 'quora',\n 'quote-left',\n 'quote-right',\n 'ra',\n 'random',\n 'ravelry',\n 'rebel',\n 'recycle',\n 'reddit',\n 'reddit-alien',\n 'reddit-square',\n 'refresh',\n 'registered',\n 'remove',\n 'renren',\n 'reorder',\n 'repeat',\n 'reply',\n 'reply-all',\n 'resistance',\n 'retweet',\n 'rmb',\n 'road',\n 'rocket',\n 'rotate-left',\n 'rotate-right',\n 'rouble',\n 'rss',\n 'rss-square',\n 'rub',\n 'ruble',\n 'rupee',\n 's15',\n 'safari',\n 'save',\n 'scissors',\n 'scribd',\n 'search',\n 'search-minus',\n 'search-plus',\n 'sellsy',\n 'send',\n 'send-o',\n 'server',\n 'share',\n 'share-alt',\n 'share-alt-square',\n 'share-square',\n 'share-square-o',\n 'shekel',\n 'sheqel',\n 'shield',\n 'ship',\n 'shirtsinbulk',\n 'shopping-bag',\n 'shopping-basket',\n 'shopping-cart',\n 'shower',\n 'sign-in',\n 'sign-language',\n 'sign-out',\n 'signal',\n 'signing',\n 'simplybuilt',\n 'sitemap',\n 'skyatlas',\n 'skype',\n 'slack',\n 'sliders',\n 'slideshare',\n 'smile-o',\n 'snapchat',\n 'snapchat-ghost',\n 'snapchat-square',\n 'snowflake-o',\n 'soccer-ball-o',\n 'sort',\n 'sort-alpha-asc',\n 'sort-alpha-desc',\n 'sort-amount-asc',\n 'sort-amount-desc',\n 'sort-asc',\n 'sort-desc',\n 'sort-down',\n 'sort-numeric-asc',\n 'sort-numeric-desc',\n 'sort-up',\n 'soundcloud',\n 'space-shuttle',\n 'spinner',\n 'spoon',\n 'spotify',\n 'square',\n 'square-o',\n 'stack-exchange',\n 'stack-overflow',\n 'star',\n 'star-half',\n 'star-half-empty',\n 'star-half-full',\n 'star-half-o',\n 'star-o',\n 'steam',\n 'steam-square',\n 'step-backward',\n 'step-forward',\n 'stethoscope',\n 'sticky-note',\n 'sticky-note-o',\n 'stop',\n 'stop-circle',\n 'stop-circle-o',\n 'street-view',\n 'strikethrough',\n 'stumbleupon',\n 'stumbleupon-circle',\n 'subscript',\n 'subway',\n 'suitcase',\n 'sun-o',\n 'superpowers',\n 'superscript',\n 'support',\n 'table',\n 'tablet',\n 'tachometer',\n 'tag',\n 'tags',\n 'tasks',\n 'taxi',\n 'telegram',\n 'television',\n 'tencent-weibo',\n 'terminal',\n 'text-height',\n 'text-width',\n 'th',\n 'th-large',\n 'th-list',\n 'themeisle',\n 'thermometer',\n 'thermometer-0',\n 'thermometer-1',\n 'thermometer-2',\n 'thermometer-3',\n 'thermometer-4',\n 'thermometer-empty',\n 'thermometer-full',\n 'thermometer-half',\n 'thermometer-quarter',\n 'thermometer-three-quarters',\n 'thumb-tack',\n 'thumbs-down',\n 'thumbs-o-down',\n 'thumbs-o-up',\n 'thumbs-up',\n 'ticket',\n 'times',\n 'times-circle',\n 'times-circle-o',\n 'times-rectangle',\n 'times-rectangle-o',\n 'tint',\n 'toggle-down',\n 'toggle-left',\n 'toggle-off',\n 'toggle-on',\n 'toggle-right',\n 'toggle-up',\n 'trademark',\n 'train',\n 'transgender',\n 'transgender-alt',\n 'trash',\n 'trash-o',\n 'tree',\n 'trello',\n 'tripadvisor',\n 'trophy',\n 'truck',\n 'try',\n 'tty',\n 'tumblr',\n 'tumblr-square',\n 'turkish-lira',\n 'tv',\n 'twitch',\n 'twitter',\n 'twitter-square',\n 'umbrella',\n 'underline',\n 'undo',\n 'universal-access',\n 'university',\n 'unlink',\n 'unlock',\n 'unlock-alt',\n 'unsorted',\n 'upload',\n 'usb',\n 'usd',\n 'user',\n 'user-circle',\n 'user-circle-o',\n 'user-md',\n 'user-o',\n 'user-plus',\n 'user-secret',\n 'user-times',\n 'users',\n 'vcard',\n 'vcard-o',\n 'venus',\n 'venus-double',\n 'venus-mars',\n 'viacoin',\n 'viadeo',\n 'viadeo-square',\n 'video-camera',\n 'vimeo',\n 'vimeo-square',\n 'vine',\n 'vk',\n 'volume-control-phone',\n 'volume-down',\n 'volume-off',\n 'volume-up',\n 'warning',\n 'wechat',\n 'weibo',\n 'weixin',\n 'whatsapp',\n 'wheelchair',\n 'wheelchair-alt',\n 'wifi',\n 'wikipedia-w',\n 'window-close',\n 'window-close-o',\n 'window-maximize',\n 'window-minimize',\n 'window-restore',\n 'windows',\n 'won',\n 'wordpress',\n 'wpbeginner',\n 'wpexplorer',\n 'wpforms',\n 'wrench',\n 'xing',\n 'xing-square',\n 'y-combinator',\n 'y-combinator-square',\n 'yahoo',\n 'yc',\n 'yc-square',\n 'yelp',\n 'yen',\n 'yoast',\n 'youtube',\n 'youtube-play'];\n\nconst PANEL_DEFAULTS = {\n maxDataPoints: 1,\n mapCenter: '(0°, 0°)',\n mapCenterLatitude: 0,\n mapCenterLongitude: 0,\n initialZoom: 1,\n disableClusterLevel: 21,\n valueName: 'total',\n circleMinSize: 2,\n circleMaxSize: 30,\n thresholds: '0,10',\n colors: ['rgba(245, 54, 54, 0.9)', 'rgba(237, 129, 40, 0.89)', 'rgba(50, 172, 45, 0.97)'],\n unitSingle: '',\n unitPlural: '',\n showLegend: true,\n esMetric: 'Count',\n decimals: 0,\n hideEmpty: false,\n hideZero: false,\n stickyLabels: false,\n minZoomShapes: 12,\n\n metrics: [],\n targets: [{\n refId: 'A',\n resultFormat: 'table',\n groupByAliases: ['type'],\n groupByColumns: ['entity_type'],\n whereClauses: [],\n metricAggs: [\n {alias: 'id', column: 'entity_id', type: 'raw'},\n {alias: 'value', column: 'availablespotnumber', type: 'raw'},\n {alias: 'geojson', column: 'location', type: 'raw'},\n {alias: 'created_at', column: 'time_index', type: 'raw'}\n ]\n }],\n layersIcons: {},\n layersColors: {},\n layersColorType: {},\n layersClusterType: {},\n layersColorsHigh: {},\n layersColorsMedium: {},\n layersColorsLow: {},\n layersColorsThresholds: {},\n layersColorsBinding: {},\n layersVariables: {},\n cityEnvVariable: '',\n buildings: false\n};\n\nconst DEFAULT_METRICS = {\n 'aqi': {'name': 'Air Quality Index', 'unit': ''},\n 'h': {'name': 'Hydrogen', 'unit': ''},\n 'no2': {'name': 'Nitrogen Dioxide', 'unit': 'µg/m3'},\n 'p': {'name': 'Pressure', 'unit': 'hPa'},\n 'pm10': {'name': 'PM10', 'unit': 'ug/m3'},\n 'pm25': {'name': 'PM25', 'unit': 'ug/m3'},\n 't': {'name': 'Temperature', 'unit': 'ºC'},\n 'co': {'name': 'CO2', 'unit': ''},\n 'intensity': {'name': 'Intensity', 'unit': ''}\n};\n\nconst MAP_LOCATIONS = {\n '(0°, 0°)': {mapCenterLatitude: 0.0, mapCenterLongitude: 0.0},\n 'North America': {mapCenterLatitude: 40, mapCenterLongitude: -100},\n 'Europe': {mapCenterLatitude: 46, mapCenterLongitude: 14},\n 'West Asia': {mapCenterLatitude: 26, mapCenterLongitude: 53},\n 'SE Asia': {mapCenterLatitude: 10, mapCenterLongitude: 106}\n};\n\nconst NOMINATIM_ADDRESS = 'https://nominatim.openstreetmap.org/search/?format=json&addressdetails=0&limit=1&polygon_svg=0';\n\nexport {\n PLUGIN_PATH, PANEL_DEFAULTS,\n NOMINATIM_ADDRESS, TILE_SERVERS,\n DEFAULT_METRICS, MAP_LOCATIONS, ICON_TYPES, MARKER_COLORS, COLOR_TYPES, CLUSTER_TYPES\n};\n"],"file":"definitions.js"} \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/img/fa/automobile.svg b/deploy/grafana-map-plugin/dist/img/fa/automobile.svg new file mode 100755 index 0000000..11b8b79 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/img/fa/automobile.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/img/fa/ban.svg b/deploy/grafana-map-plugin/dist/img/fa/ban.svg new file mode 100755 index 0000000..7b3c3df --- /dev/null +++ b/deploy/grafana-map-plugin/dist/img/fa/ban.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/img/fa/battery-empty.svg b/deploy/grafana-map-plugin/dist/img/fa/battery-empty.svg new file mode 100755 index 0000000..918c9d0 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/img/fa/battery-empty.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/img/fa/bell-o.svg b/deploy/grafana-map-plugin/dist/img/fa/bell-o.svg new file mode 100755 index 0000000..fd59c84 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/img/fa/bell-o.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/img/fa/bell-slash-o.svg b/deploy/grafana-map-plugin/dist/img/fa/bell-slash-o.svg new file mode 100755 index 0000000..934d828 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/img/fa/bell-slash-o.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/img/fa/bell-slash.svg b/deploy/grafana-map-plugin/dist/img/fa/bell-slash.svg new file mode 100755 index 0000000..77c1805 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/img/fa/bell-slash.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/img/fa/bell.svg b/deploy/grafana-map-plugin/dist/img/fa/bell.svg new file mode 100755 index 0000000..4858117 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/img/fa/bell.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/img/fa/bicycle.svg b/deploy/grafana-map-plugin/dist/img/fa/bicycle.svg new file mode 100755 index 0000000..aa6d494 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/img/fa/bicycle.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/img/fa/bus.svg b/deploy/grafana-map-plugin/dist/img/fa/bus.svg new file mode 100755 index 0000000..5a46db5 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/img/fa/bus.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/img/fa/car.svg b/deploy/grafana-map-plugin/dist/img/fa/car.svg new file mode 100755 index 0000000..11b8b79 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/img/fa/car.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/img/fa/clock-o.svg b/deploy/grafana-map-plugin/dist/img/fa/clock-o.svg new file mode 100755 index 0000000..2f102fa --- /dev/null +++ b/deploy/grafana-map-plugin/dist/img/fa/clock-o.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/img/fa/close.svg b/deploy/grafana-map-plugin/dist/img/fa/close.svg new file mode 100755 index 0000000..3e9c065 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/img/fa/close.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/img/fa/info-circle.svg b/deploy/grafana-map-plugin/dist/img/fa/info-circle.svg new file mode 100755 index 0000000..281f426 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/img/fa/info-circle.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/img/fa/question-circle.svg b/deploy/grafana-map-plugin/dist/img/fa/question-circle.svg new file mode 100755 index 0000000..6b7d7cf --- /dev/null +++ b/deploy/grafana-map-plugin/dist/img/fa/question-circle.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/img/fa/question.svg b/deploy/grafana-map-plugin/dist/img/fa/question.svg new file mode 100755 index 0000000..7fbcd22 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/img/fa/question.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/img/fa/trash-o.svg b/deploy/grafana-map-plugin/dist/img/fa/trash-o.svg new file mode 100755 index 0000000..3a2d079 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/img/fa/trash-o.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/img/fa/trash.svg b/deploy/grafana-map-plugin/dist/img/fa/trash.svg new file mode 100755 index 0000000..c8c3aa6 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/img/fa/trash.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/img/fa/tree.svg b/deploy/grafana-map-plugin/dist/img/fa/tree.svg new file mode 100755 index 0000000..bf935fa --- /dev/null +++ b/deploy/grafana-map-plugin/dist/img/fa/tree.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/img/fa/truck.svg b/deploy/grafana-map-plugin/dist/img/fa/truck.svg new file mode 100755 index 0000000..028cf34 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/img/fa/truck.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/img/fa/umbrella.svg b/deploy/grafana-map-plugin/dist/img/fa/umbrella.svg new file mode 100755 index 0000000..80c67b4 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/img/fa/umbrella.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/img/fa/video-camera.svg b/deploy/grafana-map-plugin/dist/img/fa/video-camera.svg new file mode 100755 index 0000000..8cb3a48 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/img/fa/video-camera.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/img/fa/volume-down.svg b/deploy/grafana-map-plugin/dist/img/fa/volume-down.svg new file mode 100755 index 0000000..0267f9a --- /dev/null +++ b/deploy/grafana-map-plugin/dist/img/fa/volume-down.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/img/fa/volume-off.svg b/deploy/grafana-map-plugin/dist/img/fa/volume-off.svg new file mode 100755 index 0000000..53ea769 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/img/fa/volume-off.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/img/fa/volume-up.svg b/deploy/grafana-map-plugin/dist/img/fa/volume-up.svg new file mode 100755 index 0000000..138fc69 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/img/fa/volume-up.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/img/fa/warning.svg b/deploy/grafana-map-plugin/dist/img/fa/warning.svg new file mode 100755 index 0000000..56e2698 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/img/fa/warning.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/img/icon.svg b/deploy/grafana-map-plugin/dist/img/icon.svg new file mode 100755 index 0000000..49d5121 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/img/icon.svg @@ -0,0 +1 @@ +ic-map \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/img/map_marker.png b/deploy/grafana-map-plugin/dist/img/map_marker.png new file mode 100755 index 0000000..6f8b216 Binary files /dev/null and b/deploy/grafana-map-plugin/dist/img/map_marker.png differ diff --git a/deploy/grafana-map-plugin/dist/map_renderer.js b/deploy/grafana-map-plugin/dist/map_renderer.js new file mode 100755 index 0000000..5aaae38 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/map_renderer.js @@ -0,0 +1,76 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports["default"] = link; + +var _lodash = _interopRequireDefault(require("lodash")); + +var _worldmap = _interopRequireDefault(require("./worldmap")); + +var _map_utils = require("./utils/map_utils"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +function link(scope, elem, attrs, ctrl) { + var mapContainer = elem.find('.map-container')[0]; + ctrl.events.on('render', function () { + return render(); + }); + + function render() { + if (!ctrl.data) return; // map is initializing + + if (!ctrl.worldMap) { + ctrl.worldMap = new _worldmap["default"](ctrl, mapContainer); + console.debug('creating worldMap'); + + if (ctrl.panel.mapCenter === 'User Geolocation') { + ctrl.setLocationByUserGeolocation(); + } + /* else + detect city change when using Location Variable + if (ctrl.panel.mapCenter === 'Location Variable') { // && this.ctrl.isADiferentCity() + console.log('centering at city'); + ctrl.setNewCoords(); + } */ + else ctrl.mapCenterMoved = true; + + ctrl.worldMap.createMap(); + } + /* else + if (ctrl.panel.mapCenter === 'Location Variable' && ctrl.isADiferentCity()) { + console.log('centering at new city'); + ctrl.setNewCoords(); + } */ + + + if (layersChanged()) { + console.log('layers had changed!'); + ctrl.worldMap.map.remove(); + ctrl.worldMap.createMap(); + } + + ctrl.worldMap.resize(); + + if (ctrl.mapCenterMoved) { + ctrl.worldMap.panToMapCenter(); + } + + ctrl.worldMap.clearLayers(); // ctrl.worldMap.filterEmptyData(); + + ctrl.worldMap.drawPoints(); + /** + * popups and graph display + */ + + ctrl.renderingCompleted(); + } // if users add new metrics we must verify if layers are the same or if we must recreate the map + + + function layersChanged() { + return !_lodash["default"].isEqual(ctrl.layerNames, Object.keys(ctrl.worldMap.overlayMaps)); + } +} +//# sourceMappingURL=map_renderer.js.map diff --git a/deploy/grafana-map-plugin/dist/map_renderer.js.map b/deploy/grafana-map-plugin/dist/map_renderer.js.map new file mode 100755 index 0000000..c17cea4 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/map_renderer.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/map_renderer.js"],"names":["link","scope","elem","attrs","ctrl","mapContainer","find","events","on","render","data","worldMap","WorldMap","console","debug","panel","mapCenter","setLocationByUserGeolocation","mapCenterMoved","createMap","layersChanged","log","map","remove","resize","panToMapCenter","clearLayers","drawPoints","renderingCompleted","_","isEqual","layerNames","Object","keys","overlayMaps"],"mappings":";;;;;;;AAAA;;AACA;;AACA;;;;AAEe,SAASA,IAAT,CAAcC,KAAd,EAAqBC,IAArB,EAA2BC,KAA3B,EAAkCC,IAAlC,EAAwC;AACrD,MAAMC,YAAY,GAAGH,IAAI,CAACI,IAAL,CAAU,gBAAV,EAA4B,CAA5B,CAArB;AAEAF,EAAAA,IAAI,CAACG,MAAL,CAAYC,EAAZ,CAAe,QAAf,EAAyB;AAAA,WAAMC,MAAM,EAAZ;AAAA,GAAzB;;AAEA,WAASA,MAAT,GAAkB;AAChB,QAAI,CAACL,IAAI,CAACM,IAAV,EAAgB,OADA,CAGhB;;AACA,QAAI,CAACN,IAAI,CAACO,QAAV,EAAoB;AAClBP,MAAAA,IAAI,CAACO,QAAL,GAAgB,IAAIC,oBAAJ,CAAaR,IAAb,EAAmBC,YAAnB,CAAhB;AACAQ,MAAAA,OAAO,CAACC,KAAR,CAAc,mBAAd;;AAEA,UAAIV,IAAI,CAACW,KAAL,CAAWC,SAAX,KAAyB,kBAA7B,EAAiD;AAC/CZ,QAAAA,IAAI,CAACa,4BAAL;AACD;AAAC;;;;;;AAFF,WAOUb,IAAI,CAACc,cAAL,GAAsB,IAAtB;;AAEVd,MAAAA,IAAI,CAACO,QAAL,CAAcQ,SAAd;AACD;AAAC;;;;;;;AAMF,QAAIC,aAAa,EAAjB,EAAqB;AACnBP,MAAAA,OAAO,CAACQ,GAAR,CAAY,qBAAZ;AACAjB,MAAAA,IAAI,CAACO,QAAL,CAAcW,GAAd,CAAkBC,MAAlB;AACAnB,MAAAA,IAAI,CAACO,QAAL,CAAcQ,SAAd;AACD;;AAEDf,IAAAA,IAAI,CAACO,QAAL,CAAca,MAAd;;AAEA,QAAIpB,IAAI,CAACc,cAAT,EAAyB;AACvBd,MAAAA,IAAI,CAACO,QAAL,CAAcc,cAAd;AACD;;AAEDrB,IAAAA,IAAI,CAACO,QAAL,CAAce,WAAd,GApCgB,CAuChB;;AACAtB,IAAAA,IAAI,CAACO,QAAL,CAAcgB,UAAd;AAEA;;;;AAIAvB,IAAAA,IAAI,CAACwB,kBAAL;AACD,GApDoD,CAsDrD;;;AACA,WAASR,aAAT,GAAyB;AACvB,WAAO,CAACS,mBAAEC,OAAF,CAAU1B,IAAI,CAAC2B,UAAf,EAA2BC,MAAM,CAACC,IAAP,CAAY7B,IAAI,CAACO,QAAL,CAAcuB,WAA1B,CAA3B,CAAR;AACD;AACF","sourcesContent":["import _ from 'lodash';\nimport WorldMap from './worldmap';\nimport { getUserLocation } from './utils/map_utils';\n\nexport default function link(scope, elem, attrs, ctrl) {\n const mapContainer = elem.find('.map-container')[0];\n\n ctrl.events.on('render', () => render());\n\n function render() {\n if (!ctrl.data) return;\n\n // map is initializing\n if (!ctrl.worldMap) {\n ctrl.worldMap = new WorldMap(ctrl, mapContainer);\n console.debug('creating worldMap');\n\n if (ctrl.panel.mapCenter === 'User Geolocation') {\n ctrl.setLocationByUserGeolocation();\n } /* else\n detect city change when using Location Variable\n if (ctrl.panel.mapCenter === 'Location Variable') { // && this.ctrl.isADiferentCity()\n console.log('centering at city');\n ctrl.setNewCoords();\n } */ else ctrl.mapCenterMoved = true;\n\n ctrl.worldMap.createMap();\n } /* else\n if (ctrl.panel.mapCenter === 'Location Variable' && ctrl.isADiferentCity()) {\n console.log('centering at new city');\n ctrl.setNewCoords();\n } */\n\n if (layersChanged()) {\n console.log('layers had changed!');\n ctrl.worldMap.map.remove();\n ctrl.worldMap.createMap();\n }\n\n ctrl.worldMap.resize();\n\n if (ctrl.mapCenterMoved) {\n ctrl.worldMap.panToMapCenter();\n }\n\n ctrl.worldMap.clearLayers();\n\n\n // ctrl.worldMap.filterEmptyData();\n ctrl.worldMap.drawPoints();\n\n /**\n * popups and graph display\n */\n\n ctrl.renderingCompleted();\n }\n\n // if users add new metrics we must verify if layers are the same or if we must recreate the map\n function layersChanged() {\n return !_.isEqual(ctrl.layerNames, Object.keys(ctrl.worldMap.overlayMaps));\n }\n}\n"],"file":"map_renderer.js"} \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/module.js b/deploy/grafana-map-plugin/dist/module.js new file mode 100755 index 0000000..c28bd15 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/module.js @@ -0,0 +1,25 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "PanelCtrl", { + enumerable: true, + get: function get() { + return _worldmap_ctrl["default"]; + } +}); + +var _sdk = require("app/plugins/sdk"); + +var _worldmap_ctrl = _interopRequireDefault(require("./worldmap_ctrl")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +/* eslint import/no-extraneous-dependencies: 0 */ +(0, _sdk.loadPluginCss)({ + dark: 'plugins/grafana-traffic-env-panel/css/worldmap.dark.css', + light: 'plugins/grafana-traffic-env-panel/css/worldmap.light.css' +}); +/* eslint import/prefer-default-export: 0 */ +//# sourceMappingURL=module.js.map diff --git a/deploy/grafana-map-plugin/dist/module.js.map b/deploy/grafana-map-plugin/dist/module.js.map new file mode 100755 index 0000000..fb6c6ad --- /dev/null +++ b/deploy/grafana-map-plugin/dist/module.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/module.js"],"names":["dark","light"],"mappings":";;;;;;;;;;;;AACA;;AACA;;;;AAFA;AAIA,wBAAc;AACZA,EAAAA,IAAI,EAAE,yDADM;AAEZC,EAAAA,KAAK,EAAE;AAFK,CAAd;AAKA","sourcesContent":["/* eslint import/no-extraneous-dependencies: 0 */\nimport { loadPluginCss } from 'app/plugins/sdk';\nimport WorldmapCtrl from './worldmap_ctrl';\n\nloadPluginCss({\n dark: 'plugins/grafana-traffic-env-panel/css/worldmap.dark.css',\n light: 'plugins/grafana-traffic-env-panel/css/worldmap.light.css'\n});\n\n/* eslint import/prefer-default-export: 0 */\nexport {\n WorldmapCtrl as PanelCtrl\n};\n"],"file":"module.js"} \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/partials/editor.html b/deploy/grafana-map-plugin/dist/partials/editor.html new file mode 100755 index 0000000..50774ec --- /dev/null +++ b/deploy/grafana-map-plugin/dist/partials/editor.html @@ -0,0 +1,259 @@ +
+
Map Layout
+ +
+ +
+ +
+
+ +
+
+ + + +
+
+ + + +
+
+ + + + +
+ + +
+ +
+ + +
+ +
+ + +
+ + + +
+ +
+
+ Map Metrics Details +
+ +
+
Parameter
+
Alias
+
Units
+
+ +
+
+ + + + + + + + + + +
+
+
+ +
+
+ +
+
Map Layers
+
+
{{layerName}}
+
+
+ Icon + +
+ - {{iconType}} +
+
+
+ + +
+ +
+ Cluster Type + +
+
+ Color Type + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ +
+
Help
+

- Adding this panel for the first time to your dashboard will pre-fill Metrics fields.
+ Replace empty fieldname with the field you want to use as the default for map render

+

- You have to select a default datasource or select one from the availables in metrics tab.

+

- You can replace your query fieldnames by something more intuitive. (Section Field Mappings/Units)

+
diff --git a/deploy/grafana-map-plugin/dist/partials/module.html b/deploy/grafana-map-plugin/dist/partials/module.html new file mode 100755 index 0000000..e7e37bd --- /dev/null +++ b/deploy/grafana-map-plugin/dist/partials/module.html @@ -0,0 +1,16 @@ +
+
+
+ + +
+
+ +
\ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/plugin.json b/deploy/grafana-map-plugin/dist/plugin.json new file mode 100755 index 0000000..abf1a49 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/plugin.json @@ -0,0 +1,28 @@ +{ + "type": "panel", + "name": "Map Panel", + "id": "grafana-traffic-env-panel", + + "info": { + "description": "Grafana Map panel for analysing timeseries geolocated data (eg.traffic and environment data)", + "author": { + "name": "Ubiwhere", + "url": "" + }, + "keywords": ["map", "panel", "geoJSON"], + "logos": { + "small": "img/icon.svg", + "large": "img/icon.svg" + }, + "links": [ + {"name": "Project site", "url": ""}, + {"name": "MIT License", "url": ""} + ], + "version": "1.3.4" + }, + + "dependencies": { + "grafanaVersion": "5.x.x", + "plugins": [ ] + } +} diff --git a/deploy/grafana-map-plugin/dist/utils/data_utils.js b/deploy/grafana-map-plugin/dist/utils/data_utils.js new file mode 100755 index 0000000..1c9195b --- /dev/null +++ b/deploy/grafana-map-plugin/dist/utils/data_utils.js @@ -0,0 +1,178 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.DataFormatter = void 0; + +function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } + +function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); } + +function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); } + +function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } } + +function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } + +function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } + +function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } + +function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } + +function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +// import { isEqual, reduce, filter, transform, isObject } from 'lodash'; +var DataFormatter = +/*#__PURE__*/ +function () { + function DataFormatter() { + _classCallCheck(this, DataFormatter); + } + + _createClass(DataFormatter, [{ + key: "getValues", + value: function getValues(series) { + if (!series || series.length === 0) return {}; + + var seriesType = this._getSeriesType(series); + + return seriesType === 'table' ? this._getSeries(series) : this._getSeriesTimeSeries(series); + } + }, { + key: "isJsonString", + value: function isJsonString(item) { + if (typeof item !== "string") { + return false; + } + + try { + item = JSON.parse(item); + } catch (e) { + return false; + } + + if (_typeof(item) === "object" && item !== null) { + return true; + } + + return false; + } + }, { + key: "fixType", + value: function fixType(item) { + if (this.isJsonString(item)) { + return JSON.parse(item); + } else { + return item; + } + } + }, { + key: "_getSeries", + value: function _getSeries(series) { + var _this = this; + + var hashSeriesByLayerByKey = {}; + var seriesLayer = null; + var id = null; + series.forEach(function (series_elem) { + var columns = series_elem.columns.map(function (elem) { + return elem.text; + }); + var type_index = columns.length - 1; + var id_index = 1; + + if (columns.indexOf("type") < 0) { + console.warn("Missing type alias in the query (required to define layers)"); + } else { + type_index = columns.indexOf("type"); + } + + if (columns.indexOf("id") < 0) { + console.warn("Missing id alias in the query"); + } else { + id_index = columns.indexOf("id"); + } + + series_elem.rows.forEach(function (series_elem_row) { + seriesLayer = series_elem_row[type_index]; + + if (!hashSeriesByLayerByKey[seriesLayer]) { + hashSeriesByLayerByKey[seriesLayer] = {}; + } + + id = series_elem_row[id_index]; + + if (!hashSeriesByLayerByKey[seriesLayer][id]) { + hashSeriesByLayerByKey[seriesLayer][id] = []; + } + + var hashWithValues = {}; + columns.forEach(function (elem, i) { + if (i !== columns.indexOf("time") && i !== columns.length - 1) // do not insert grafana field 'time' and the group by field + { + hashWithValues[elem] = _this.fixType(series_elem_row[i]); + } + }); + hashSeriesByLayerByKey[seriesLayer][id].push(hashWithValues); + }); + }); + return hashSeriesByLayerByKey; + } + }, { + key: "_getSeriesTimeSeries", + value: function _getSeriesTimeSeries(series) { + var setSeries = {}; + var setSeriesByLayer = {}; + series.forEach(function (series_elem) { + var _series_elem$target$s = series_elem.target.split(': '), + _series_elem$target$s2 = _slicedToArray(_series_elem$target$s, 2), + seriesLayer = _series_elem$target$s2[0], + seriesFieldName = _series_elem$target$s2[1]; + + if (!setSeriesByLayer[seriesLayer]) { + setSeriesByLayer[seriesLayer] = []; + } + + setSeriesByLayer[seriesLayer].push([seriesFieldName].concat(_toConsumableArray(series_elem.datapoints.map(function (elem) { + return elem[0]; + })))); + }); // get one array and transform into a hash + + var hashSeriesByLayerByKey = {}; + Object.keys(setSeriesByLayer).forEach(function (layerName) { + if (!hashSeriesByLayerByKey[layerName]) hashSeriesByLayerByKey[layerName] = {}; + var superArray = setSeriesByLayer[layerName]; + + for (var column = 1; column < superArray[0].length; column++) { + var result = {}; + + for (var line = 0; line < superArray.length; line++) { + result[superArray[line][0]] = superArray[line][column]; + } + + if (!hashSeriesByLayerByKey[layerName][result.id]) hashSeriesByLayerByKey[layerName][result.id] = []; + hashSeriesByLayerByKey[layerName][result.id].push(result); + } + }); + return hashSeriesByLayerByKey; + } + }, { + key: "_getSeriesType", + value: function _getSeriesType(series) { + return series[0].type; + } + }]); + + return DataFormatter; +}(); + +exports.DataFormatter = DataFormatter; +//# sourceMappingURL=data_utils.js.map diff --git a/deploy/grafana-map-plugin/dist/utils/data_utils.js.map b/deploy/grafana-map-plugin/dist/utils/data_utils.js.map new file mode 100755 index 0000000..f6a24fc --- /dev/null +++ b/deploy/grafana-map-plugin/dist/utils/data_utils.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/utils/data_utils.js"],"names":["DataFormatter","series","length","seriesType","_getSeriesType","_getSeries","_getSeriesTimeSeries","item","JSON","parse","e","isJsonString","hashSeriesByLayerByKey","seriesLayer","id","forEach","series_elem","columns","map","elem","text","type_index","id_index","indexOf","console","warn","rows","series_elem_row","hashWithValues","i","fixType","push","setSeries","setSeriesByLayer","target","split","seriesFieldName","datapoints","Object","keys","layerName","superArray","column","result","line","type"],"mappings":"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","sourcesContent":["// import { isEqual, reduce, filter, transform, isObject } from 'lodash';\n\nclass DataFormatter {\n getValues(series) {\n if (!series || series.length === 0) return {};\n\n const seriesType = this._getSeriesType(series);\n\n return (seriesType === 'table') ? this._getSeries(series) : this._getSeriesTimeSeries(series);\n }\n\n\n isJsonString(item) {\n if (typeof item !== \"string\") {\n return false;\n }\n\n try {\n item = JSON.parse(item);\n } catch (e) {\n return false;\n }\n\n if (typeof item === \"object\" && item !== null) {\n return true;\n }\n\n return false;\n }\n\n fixType(item) {\n if (this.isJsonString(item)) {\n return JSON.parse(item);\n } else {\n return item;\n }\n }\n\n _getSeries(series) {\n const hashSeriesByLayerByKey = {};\n let seriesLayer = null;\n let id = null;\n\n series.forEach((series_elem) => {\n const columns = series_elem.columns.map((elem) => elem.text);\n var type_index = columns.length - 1;\n var id_index = 1;\n\n if(columns.indexOf(\"type\") < 0){\n console.warn(\"Missing type alias in the query (required to define layers)\");\n } else {\n type_index = columns.indexOf(\"type\");\n }\n\n if(columns.indexOf(\"id\") < 0 ){\n console.warn(\"Missing id alias in the query\");\n } else {\n id_index = columns.indexOf(\"id\");\n }\n\n series_elem.rows.forEach((series_elem_row) => {\n seriesLayer = series_elem_row[type_index];\n\n if (!(hashSeriesByLayerByKey[seriesLayer])) {\n hashSeriesByLayerByKey[seriesLayer] = {};\n }\n\n id = series_elem_row[id_index];\n if (!(hashSeriesByLayerByKey[seriesLayer][id])) {\n hashSeriesByLayerByKey[seriesLayer][id] = [];\n }\n\n const hashWithValues = {};\n columns.forEach((elem, i) => {\n if (i !== columns.indexOf(\"time\") && i !== columns.length - 1) // do not insert grafana field 'time' and the group by field\n { hashWithValues[elem] = this.fixType(series_elem_row[i]); }\n });\n hashSeriesByLayerByKey[seriesLayer][id].push(hashWithValues);\n });\n });\n\n return hashSeriesByLayerByKey;\n }\n\n _getSeriesTimeSeries(series) {\n const setSeries = {};\n const setSeriesByLayer = {};\n\n series.forEach((series_elem) => {\n const [seriesLayer, seriesFieldName] = series_elem.target.split(': ');\n\n if (!(setSeriesByLayer[seriesLayer])) {\n setSeriesByLayer[seriesLayer] = [];\n }\n\n setSeriesByLayer[seriesLayer].push([seriesFieldName, ...series_elem.datapoints.map((elem) => elem[0])]);\n });\n\n\n // get one array and transform into a hash\n const hashSeriesByLayerByKey = {};\n\n Object.keys(setSeriesByLayer).forEach((layerName) => {\n if (!hashSeriesByLayerByKey[layerName]) hashSeriesByLayerByKey[layerName] = {};\n\n const superArray = setSeriesByLayer[layerName];\n\n for (let column = 1; column < superArray[0].length; column++) {\n const result = {};\n for (let line = 0; line < superArray.length; line++) {\n result[superArray[line][0]] = superArray[line][column];\n }\n\n if (!hashSeriesByLayerByKey[layerName][result.id]) hashSeriesByLayerByKey[layerName][result.id] = [];\n\n hashSeriesByLayerByKey[layerName][result.id].push(result);\n }\n });\n\n return hashSeriesByLayerByKey;\n }\n\n _getSeriesType(series) {\n return series[0].type;\n }\n}\n\nexport { DataFormatter };\n"],"file":"data_utils.js"} \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/utils/datasource.js b/deploy/grafana-map-plugin/dist/utils/datasource.js new file mode 100755 index 0000000..f22ab66 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/utils/datasource.js @@ -0,0 +1,26 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getDatasources = getDatasources; +exports.getValidDatasources = getValidDatasources; + +function getDatasources(targets) { + return targets.map(function (elem) { + return { + 'name': elem.datasource + }; + }); +} + +function getValidDatasources(targets) { + return targets.filter(function (elem) { + return elem.metricAggs.filter(function (elem) { + return elem.alias === 'latitude' || elem.alias === 'longitude'; + }); + }).map(function (elem) { + return elem.datasource; + }); +} +//# sourceMappingURL=datasource.js.map diff --git a/deploy/grafana-map-plugin/dist/utils/datasource.js.map b/deploy/grafana-map-plugin/dist/utils/datasource.js.map new file mode 100755 index 0000000..669baf2 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/utils/datasource.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/utils/datasource.js"],"names":["getDatasources","targets","map","elem","datasource","getValidDatasources","filter","metricAggs","alias"],"mappings":";;;;;;;;AAAA,SAASA,cAAT,CAAwBC,OAAxB,EAAiC;AAC/B,SAAOA,OAAO,CAACC,GAAR,CAAY,UAACC,IAAD,EAAU;AAAE,WAAO;AAAE,cAAQA,IAAI,CAACC;AAAf,KAAP;AAAqC,GAA7D,CAAP;AACD;;AAED,SAASC,mBAAT,CAA6BJ,OAA7B,EAAsC;AACpC,SAAOA,OAAO,CAACK,MAAR,CAAe,UAACH,IAAD;AAAA,WAAUA,IAAI,CAACI,UAAL,CAAgBD,MAAhB,CAAuB,UAACH,IAAD;AAAA,aAAUA,IAAI,CAACK,KAAL,KAAe,UAAf,IAA6BL,IAAI,CAACK,KAAL,KAAe,WAAtD;AAAA,KAAvB,CAAV;AAAA,GAAf,EAAoHN,GAApH,CAAwH,UAACC,IAAD;AAAA,WAAUA,IAAI,CAACC,UAAf;AAAA,GAAxH,CAAP;AACD","sourcesContent":["function getDatasources(targets) {\n return targets.map((elem) => { return { 'name': elem.datasource }; });\n}\n\nfunction getValidDatasources(targets) {\n return targets.filter((elem) => elem.metricAggs.filter((elem) => elem.alias === 'latitude' || elem.alias === 'longitude')).map((elem) => elem.datasource);\n}\n\nexport {\n getDatasources, getValidDatasources\n};\n"],"file":"datasource.js"} \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/utils/map_utils.js b/deploy/grafana-map-plugin/dist/utils/map_utils.js new file mode 100755 index 0000000..6b94a7f --- /dev/null +++ b/deploy/grafana-map-plugin/dist/utils/map_utils.js @@ -0,0 +1,159 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.getCityCoordinates = getCityCoordinates; +exports.getDataPointStickyInfo = getDataPointStickyInfo; +exports.getSelectedCity = getSelectedCity; +exports.geolocationOptions = void 0; + +var _lodash = require("lodash"); + +var _config = _interopRequireDefault(require("app/core/config")); + +var _string = require("./string"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +/** +* private functions +*/ +function getDataPointStickyInfo(dataPoint, metricsTranslations) { + var stickyInfo = '
+ +
+
+ +
+
+ +
+ +
+ +
+
+ + +
+ +
+
+
+
+ +
+ + + +
+ + + + +
+ +
+ + + +
+ + + +
+ + +
+
+ +
+
+ +
+
+ + +
+
+ + + +
+
+
+
+
+ +
+
+ Group By time Interval + +
+
+ +
+ +
+
+
+
+
+
+
'; + var bodyData = getDataPointDetails(dataPoint, ['geojson', 'id', 'type', 'created_at', 'longitude', 'latitude', 'name'], false); + + if (dataPoint.name && Object.keys(bodyData).length > 1) { + stickyInfo += '
' + dataPoint.name + '
'; + } else if (dataPoint.id && Object.keys(bodyData).length > 1) { + stickyInfo += '
' + dataPoint.id + '
'; + } else if (Object.keys(bodyData).length === 1) { + stickyInfo += '
' + Object.keys(bodyData)[0] + '
'; + } + + var bodyClass = 'popup-single-value'; + + if (Object.keys(bodyData).length > 1) { + bodyClass = 'popup-multiple-value'; + } // body + + + stickyInfo += '
'; + stickyInfo += translate(bodyData, metricsTranslations, bodyClass).join(''); + stickyInfo += '
'; // foot + + var footData; + + if (Object.keys(bodyData).length === 1 && dataPoint.name) { + footData = getDataPointDetails(dataPoint, ['created_at', 'name'], true); + } else { + footData = getDataPointDetails(dataPoint, ['created_at'], true); + } + + var footClass = ''; + stickyInfo += '
'; + stickyInfo += translate(footData, metricsTranslations, footClass).join(''); + stickyInfo += '
'; + return stickyInfo; +} + +function getDataPointDetails(dataPoint, skipkey, include) { + return include ? Object.keys(dataPoint).filter(function (key) { + return skipkey.includes(key); + }).reduce(function (obj, key) { + obj[key] = dataPoint[key]; + return obj; + }, {}) : Object.keys(dataPoint).filter(function (key) { + return !skipkey.includes(key); + }).reduce(function (obj, key) { + obj[key] = dataPoint[key]; + return obj; + }, {}); +} + +function objToString(obj) { + var str = '
'; + + for (var p in obj) { + if (obj.hasOwnProperty(p)) { + if (_typeof(obj[p]) === 'object') { + str += p + ': ' + objToString(obj[p]) + '
'; + } else { + str += p + ': ' + obj[p] + '
'; + } + } + } + + str += '
'; + return str; +} + +function translate(filteredData, metricsTranslations, cssClass) { + var keys = Object.keys(filteredData); + var translatedValues = keys.map(function (dpKey) { + var dP = dpKey === 'created_at' ? new Date(filteredData[dpKey]).toLocaleString() : _typeof(filteredData[dpKey]) === 'object' ? objToString(filteredData[dpKey]) : typeof filteredData[dpKey] === 'boolean' ? filteredData[dpKey] : isNaN(filteredData[dpKey]) ? filteredData[dpKey] : Number.isInteger(filteredData[dpKey]) ? filteredData[dpKey] : parseFloat(filteredData[dpKey].toFixed(2)); + var trans = metricsTranslations.filter(function (elem) { + return elem[0] === dpKey; + }); + return { + 'name': trans.length > 0 && trans[0][1] ? trans[0][1] : (0, _string.titleize)(dpKey), + 'value': dP || '-', + 'unit': trans.length > 0 ? trans[0][2] : '' + }; + }); + return translatedValues.map(function (translatedValue) { + return "
").concat(translatedValue.name, "").concat(translatedValue.value, "").concat(translatedValue.unit || '', "
"); + }); +} // Given vars passed as param, retrieves the selected city + + +function getSelectedCity(vars, selectedVarName) { + var cityEnv = vars.filter(function (elem) { + return elem.name === selectedVarName; + }); + var city = null; + if (cityEnv && cityEnv.length === 1) city = cityEnv[0].current.value; + return city; +} // Access remote api and gives the coordinates from a city center based on NOMINATIM url server + + +function getCityCoordinates(city_name) { + var url = NOMINATIM_ADDRESS.replace('', city_name); + return fetch(url).then(function (response) { + return response.json(); + }).then(function (data) { + return { + latitude: data[0].lat, + longitude: data[0].lon + }; + })["catch"](function (error) { + return console.error(error); + }); +} +/* +* Auxiliar functions +*/ +// just for improve DRY + + +function convertDate(time_) { + var time = new Date(time_); + var day = time.getDate(); + var month = time.getMonth(); + var year = time.getFullYear(); + var hour = time.getHours() - 1; + var minutes = time.getMinutes(); + var seconds = time.getSeconds(); + var milliseconds = time.getMilliseconds(); + return Date.UTC(year, month, day, hour + 1, minutes, seconds, milliseconds); +} + +var geolocationOptions = { + enableHighAccuracy: true, + timeout: 5000, + maximumAge: 110 +}; +exports.geolocationOptions = geolocationOptions; +//# sourceMappingURL=map_utils.js.map diff --git a/deploy/grafana-map-plugin/dist/utils/map_utils.js.map b/deploy/grafana-map-plugin/dist/utils/map_utils.js.map new file mode 100755 index 0000000..ff77b42 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/utils/map_utils.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/utils/map_utils.js"],"names":["getDataPointStickyInfo","dataPoint","metricsTranslations","stickyInfo","bodyData","getDataPointDetails","name","Object","keys","length","id","bodyClass","translate","join","footData","footClass","skipkey","include","filter","key","includes","reduce","obj","objToString","str","p","hasOwnProperty","filteredData","cssClass","translatedValues","map","dpKey","dP","Date","toLocaleString","isNaN","Number","isInteger","parseFloat","toFixed","trans","elem","translatedValue","value","unit","getSelectedCity","vars","selectedVarName","cityEnv","city","current","getCityCoordinates","city_name","url","NOMINATIM_ADDRESS","replace","fetch","then","response","json","data","latitude","lat","longitude","lon","error","console","convertDate","time_","time","day","getDate","month","getMonth","year","getFullYear","hour","getHours","minutes","getMinutes","seconds","getSeconds","milliseconds","getMilliseconds","UTC","geolocationOptions","enableHighAccuracy","timeout","maximumAge"],"mappings":"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","sourcesContent":["// draw components in the map\n/* Vendor specific */\nimport { defaults, isEqual } from 'lodash';\n\nimport config from 'app/core/config';\n\n/* Grafana Specific */\n\nimport { titleize } from './string';\n\n\n/**\n* private functions\n*/\n\nfunction getDataPointStickyInfo(dataPoint, metricsTranslations) {\n let stickyInfo = '
';\n\n var bodyData = getDataPointDetails(dataPoint, ['geojson', 'id', 'type', 'created_at', 'longitude', 'latitude' , 'name'], false);\n\n if (dataPoint.name && Object.keys(bodyData).length > 1){\n stickyInfo += '
' + dataPoint.name + '
';\n } else if (dataPoint.id && Object.keys(bodyData).length > 1) {\n stickyInfo += '
' + dataPoint.id + '
';\n } else if (Object.keys(bodyData).length === 1){\n stickyInfo += '
' + Object.keys(bodyData)[0] + '
';\n }\n\n var bodyClass = 'popup-single-value';\n if (Object.keys(bodyData).length > 1){\n bodyClass = 'popup-multiple-value';\n }\n\n // body\n stickyInfo += '
';\n stickyInfo += translate(bodyData, metricsTranslations, bodyClass).join('');\n stickyInfo += '
';\n\n // foot\n var footData;\n if (Object.keys(bodyData).length === 1 && dataPoint.name){\n footData = getDataPointDetails(dataPoint, ['created_at', 'name'], true);\n } else {\n footData = getDataPointDetails(dataPoint, ['created_at'], true);\n }\n\n\n var footClass = '';\n\n stickyInfo += '
';\n stickyInfo+= translate(footData, metricsTranslations, footClass).join('');\n stickyInfo += '
';\n return stickyInfo;\n}\n\nfunction getDataPointDetails(dataPoint, skipkey, include) {\n return include? Object.keys(dataPoint).filter(key => skipkey.includes(key)).reduce((obj, key) => { obj[key] = dataPoint[key]; return obj; }, {}) : Object.keys(dataPoint).filter(key => !skipkey.includes(key)).reduce((obj, key) => { obj[key] = dataPoint[key]; return obj; }, {});\n}\n\n\nfunction objToString (obj) {\n var str = '
';\n for (var p in obj) {\n if (obj.hasOwnProperty(p)) {\n if(typeof obj[p] === 'object'){\n str += p + ': ' + objToString(obj[p]) + '
';\n } else {\n str += p + ': ' + obj[p] + '
';\n }\n }\n }\n str += '
';\n return str;\n}\n\nfunction translate(filteredData, metricsTranslations, cssClass){\n const keys = Object.keys(filteredData);\n const translatedValues = keys.map((dpKey) => {\n const dP = (dpKey === 'created_at' ? new Date(filteredData[dpKey]).toLocaleString() : typeof filteredData[dpKey] === 'object' ? objToString(filteredData[dpKey]) : typeof filteredData[dpKey] === 'boolean' ? filteredData[dpKey] : isNaN(filteredData[dpKey]) ? filteredData[dpKey] : Number.isInteger(filteredData[dpKey]) ? filteredData[dpKey] : parseFloat(filteredData[dpKey].toFixed(2)) );\n const trans = metricsTranslations.filter((elem) => elem[0] === dpKey);\n return { 'name': (trans.length > 0 && trans[0][1] ? trans[0][1] : titleize(dpKey)), 'value': dP || '-', 'unit': (trans.length > 0 ? trans[0][2] : '') };\n });\n return translatedValues.map((translatedValue) => `
${translatedValue.name}${translatedValue.value}${translatedValue.unit || ''}
`);\n}\n\n// Given vars passed as param, retrieves the selected city\nfunction getSelectedCity(vars, selectedVarName) {\n const cityEnv = vars.filter((elem) => elem.name === selectedVarName);\n\n let city = null;\n if (cityEnv && cityEnv.length === 1) city = cityEnv[0].current.value;\n\n return city;\n}\n\n// Access remote api and gives the coordinates from a city center based on NOMINATIM url server\nfunction getCityCoordinates(city_name) {\n const url = NOMINATIM_ADDRESS.replace('', city_name);\n return fetch(url)\n .then((response) => response.json())\n .then((data) => { return { latitude: data[0].lat, longitude: data[0].lon }; })\n .catch((error) => console.error(error));\n}\n/*\n* Auxiliar functions\n*/\n// just for improve DRY\nfunction convertDate(time_) {\n const time = new Date(time_);\n const day = time.getDate();\n const month = time.getMonth();\n const year = time.getFullYear();\n const hour = time.getHours() - 1;\n const minutes = time.getMinutes();\n const seconds = time.getSeconds();\n const milliseconds = time.getMilliseconds();\n return Date.UTC(year, month, day, hour + 1, minutes, seconds, milliseconds);\n}\n\nconst geolocationOptions = {\n enableHighAccuracy: true,\n timeout: 5000,\n maximumAge: 110\n};\n\nexport {\n\n getCityCoordinates,\n\n getDataPointStickyInfo,\n\n getSelectedCity,\n\n geolocationOptions\n};\n"],"file":"map_utils.js"} \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/utils/string.js b/deploy/grafana-map-plugin/dist/utils/string.js new file mode 100755 index 0000000..366d396 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/utils/string.js @@ -0,0 +1,30 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.capitalize = capitalize; +exports.titleize = titleize; + +function capitalize(str) { + return str.charAt(0).toUpperCase() + str.slice(1); +} + +function titleize(str) { + return str.split('_').map(function (elem) { + return capitalize(elem); + }).join(' '); +} + +String.prototype.capitalize = function () { + this.charAt(0).toUpperCase() + this.slice(1); +}; + +String.prototype.titleize = function () { + var _this = this; + + this.split('_').map(function (elem) { + return _this.capitalize(elem); + }).join(' '); +}; +//# sourceMappingURL=string.js.map diff --git a/deploy/grafana-map-plugin/dist/utils/string.js.map b/deploy/grafana-map-plugin/dist/utils/string.js.map new file mode 100755 index 0000000..296ce38 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/utils/string.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/utils/string.js"],"names":["capitalize","str","charAt","toUpperCase","slice","titleize","split","map","elem","join","String","prototype"],"mappings":";;;;;;;;AAAO,SAASA,UAAT,CAAoBC,GAApB,EAAyB;AAC9B,SAAOA,GAAG,CAACC,MAAJ,CAAW,CAAX,EAAcC,WAAd,KAA8BF,GAAG,CAACG,KAAJ,CAAU,CAAV,CAArC;AACD;;AAEM,SAASC,QAAT,CAAkBJ,GAAlB,EAAuB;AAC5B,SAAOA,GAAG,CAACK,KAAJ,CAAU,GAAV,EAAeC,GAAf,CAAmB,UAACC,IAAD;AAAA,WAAUR,UAAU,CAACQ,IAAD,CAApB;AAAA,GAAnB,EAA+CC,IAA/C,CAAoD,GAApD,CAAP;AACD;;AAGDC,MAAM,CAACC,SAAP,CAAiBX,UAAjB,GAA8B,YAAY;AACxC,OAAKE,MAAL,CAAY,CAAZ,EAAeC,WAAf,KAA+B,KAAKC,KAAL,CAAW,CAAX,CAA/B;AACD,CAFD;;AAGAM,MAAM,CAACC,SAAP,CAAiBN,QAAjB,GAA4B,YAAY;AAAA;;AACtC,OAAKC,KAAL,CAAW,GAAX,EAAgBC,GAAhB,CAAoB,UAACC,IAAD;AAAA,WAAU,KAAI,CAACR,UAAL,CAAgBQ,IAAhB,CAAV;AAAA,GAApB,EAAqDC,IAArD,CAA0D,GAA1D;AACD,CAFD","sourcesContent":["export function capitalize(str) {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\nexport function titleize(str) {\n return str.split('_').map((elem) => capitalize(elem)).join(' ');\n}\n\n\nString.prototype.capitalize = function () {\n this.charAt(0).toUpperCase() + this.slice(1);\n};\nString.prototype.titleize = function () {\n this.split('_').map((elem) => this.capitalize(elem)).join(' ');\n};\n"],"file":"string.js"} \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/all.css b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/all.css new file mode 100755 index 0000000..ba15e19 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/all.css @@ -0,0 +1,4463 @@ +/*! + * Font Awesome Free 5.12.1 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +.fa, +.fas, +.far, +.fal, +.fad, +.fab { + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + display: inline-block; + font-style: normal; + font-variant: normal; + text-rendering: auto; + line-height: 1; } + +.fa-lg { + font-size: 1.33333em; + line-height: 0.75em; + vertical-align: -.0667em; } + +.fa-xs { + font-size: .75em; } + +.fa-sm { + font-size: .875em; } + +.fa-1x { + font-size: 1em; } + +.fa-2x { + font-size: 2em; } + +.fa-3x { + font-size: 3em; } + +.fa-4x { + font-size: 4em; } + +.fa-5x { + font-size: 5em; } + +.fa-6x { + font-size: 6em; } + +.fa-7x { + font-size: 7em; } + +.fa-8x { + font-size: 8em; } + +.fa-9x { + font-size: 9em; } + +.fa-10x { + font-size: 10em; } + +.fa-fw { + text-align: center; + width: 1.25em; } + +.fa-ul { + list-style-type: none; + margin-left: 2.5em; + padding-left: 0; } + .fa-ul > li { + position: relative; } + +.fa-li { + left: -2em; + position: absolute; + text-align: center; + width: 2em; + line-height: inherit; } + +.fa-border { + border: solid 0.08em #eee; + border-radius: .1em; + padding: .2em .25em .15em; } + +.fa-pull-left { + float: left; } + +.fa-pull-right { + float: right; } + +.fa.fa-pull-left, +.fas.fa-pull-left, +.far.fa-pull-left, +.fal.fa-pull-left, +.fab.fa-pull-left { + margin-right: .3em; } + +.fa.fa-pull-right, +.fas.fa-pull-right, +.far.fa-pull-right, +.fal.fa-pull-right, +.fab.fa-pull-right { + margin-left: .3em; } + +.fa-spin { + -webkit-animation: fa-spin 2s infinite linear; + animation: fa-spin 2s infinite linear; } + +.fa-pulse { + -webkit-animation: fa-spin 1s infinite steps(8); + animation: fa-spin 1s infinite steps(8); } + +@-webkit-keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); } } + +@keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); } } + +.fa-rotate-90 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)"; + -webkit-transform: rotate(90deg); + transform: rotate(90deg); } + +.fa-rotate-180 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)"; + -webkit-transform: rotate(180deg); + transform: rotate(180deg); } + +.fa-rotate-270 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)"; + -webkit-transform: rotate(270deg); + transform: rotate(270deg); } + +.fa-flip-horizontal { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)"; + -webkit-transform: scale(-1, 1); + transform: scale(-1, 1); } + +.fa-flip-vertical { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; + -webkit-transform: scale(1, -1); + transform: scale(1, -1); } + +.fa-flip-both, .fa-flip-horizontal.fa-flip-vertical { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; + -webkit-transform: scale(-1, -1); + transform: scale(-1, -1); } + +:root .fa-rotate-90, +:root .fa-rotate-180, +:root .fa-rotate-270, +:root .fa-flip-horizontal, +:root .fa-flip-vertical, +:root .fa-flip-both { + -webkit-filter: none; + filter: none; } + +.fa-stack { + display: inline-block; + height: 2em; + line-height: 2em; + position: relative; + vertical-align: middle; + width: 2.5em; } + +.fa-stack-1x, +.fa-stack-2x { + left: 0; + position: absolute; + text-align: center; + width: 100%; } + +.fa-stack-1x { + line-height: inherit; } + +.fa-stack-2x { + font-size: 2em; } + +.fa-inverse { + color: #fff; } + +/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen +readers do not read off random characters that represent icons */ +.fa-500px:before { + content: "\f26e"; } + +.fa-accessible-icon:before { + content: "\f368"; } + +.fa-accusoft:before { + content: "\f369"; } + +.fa-acquisitions-incorporated:before { + content: "\f6af"; } + +.fa-ad:before { + content: "\f641"; } + +.fa-address-book:before { + content: "\f2b9"; } + +.fa-address-card:before { + content: "\f2bb"; } + +.fa-adjust:before { + content: "\f042"; } + +.fa-adn:before { + content: "\f170"; } + +.fa-adobe:before { + content: "\f778"; } + +.fa-adversal:before { + content: "\f36a"; } + +.fa-affiliatetheme:before { + content: "\f36b"; } + +.fa-air-freshener:before { + content: "\f5d0"; } + +.fa-airbnb:before { + content: "\f834"; } + +.fa-algolia:before { + content: "\f36c"; } + +.fa-align-center:before { + content: "\f037"; } + +.fa-align-justify:before { + content: "\f039"; } + +.fa-align-left:before { + content: "\f036"; } + +.fa-align-right:before { + content: "\f038"; } + +.fa-alipay:before { + content: "\f642"; } + +.fa-allergies:before { + content: "\f461"; } + +.fa-amazon:before { + content: "\f270"; } + +.fa-amazon-pay:before { + content: "\f42c"; } + +.fa-ambulance:before { + content: "\f0f9"; } + +.fa-american-sign-language-interpreting:before { + content: "\f2a3"; } + +.fa-amilia:before { + content: "\f36d"; } + +.fa-anchor:before { + content: "\f13d"; } + +.fa-android:before { + content: "\f17b"; } + +.fa-angellist:before { + content: "\f209"; } + +.fa-angle-double-down:before { + content: "\f103"; } + +.fa-angle-double-left:before { + content: "\f100"; } + +.fa-angle-double-right:before { + content: "\f101"; } + +.fa-angle-double-up:before { + content: "\f102"; } + +.fa-angle-down:before { + content: "\f107"; } + +.fa-angle-left:before { + content: "\f104"; } + +.fa-angle-right:before { + content: "\f105"; } + +.fa-angle-up:before { + content: "\f106"; } + +.fa-angry:before { + content: "\f556"; } + +.fa-angrycreative:before { + content: "\f36e"; } + +.fa-angular:before { + content: "\f420"; } + +.fa-ankh:before { + content: "\f644"; } + +.fa-app-store:before { + content: "\f36f"; } + +.fa-app-store-ios:before { + content: "\f370"; } + +.fa-apper:before { + content: "\f371"; } + +.fa-apple:before { + content: "\f179"; } + +.fa-apple-alt:before { + content: "\f5d1"; } + +.fa-apple-pay:before { + content: "\f415"; } + +.fa-archive:before { + content: "\f187"; } + +.fa-archway:before { + content: "\f557"; } + +.fa-arrow-alt-circle-down:before { + content: "\f358"; } + +.fa-arrow-alt-circle-left:before { + content: "\f359"; } + +.fa-arrow-alt-circle-right:before { + content: "\f35a"; } + +.fa-arrow-alt-circle-up:before { + content: "\f35b"; } + +.fa-arrow-circle-down:before { + content: "\f0ab"; } + +.fa-arrow-circle-left:before { + content: "\f0a8"; } + +.fa-arrow-circle-right:before { + content: "\f0a9"; } + +.fa-arrow-circle-up:before { + content: "\f0aa"; } + +.fa-arrow-down:before { + content: "\f063"; } + +.fa-arrow-left:before { + content: "\f060"; } + +.fa-arrow-right:before { + content: "\f061"; } + +.fa-arrow-up:before { + content: "\f062"; } + +.fa-arrows-alt:before { + content: "\f0b2"; } + +.fa-arrows-alt-h:before { + content: "\f337"; } + +.fa-arrows-alt-v:before { + content: "\f338"; } + +.fa-artstation:before { + content: "\f77a"; } + +.fa-assistive-listening-systems:before { + content: "\f2a2"; } + +.fa-asterisk:before { + content: "\f069"; } + +.fa-asymmetrik:before { + content: "\f372"; } + +.fa-at:before { + content: "\f1fa"; } + +.fa-atlas:before { + content: "\f558"; } + +.fa-atlassian:before { + content: "\f77b"; } + +.fa-atom:before { + content: "\f5d2"; } + +.fa-audible:before { + content: "\f373"; } + +.fa-audio-description:before { + content: "\f29e"; } + +.fa-autoprefixer:before { + content: "\f41c"; } + +.fa-avianex:before { + content: "\f374"; } + +.fa-aviato:before { + content: "\f421"; } + +.fa-award:before { + content: "\f559"; } + +.fa-aws:before { + content: "\f375"; } + +.fa-baby:before { + content: "\f77c"; } + +.fa-baby-carriage:before { + content: "\f77d"; } + +.fa-backspace:before { + content: "\f55a"; } + +.fa-backward:before { + content: "\f04a"; } + +.fa-bacon:before { + content: "\f7e5"; } + +.fa-bahai:before { + content: "\f666"; } + +.fa-balance-scale:before { + content: "\f24e"; } + +.fa-balance-scale-left:before { + content: "\f515"; } + +.fa-balance-scale-right:before { + content: "\f516"; } + +.fa-ban:before { + content: "\f05e"; } + +.fa-band-aid:before { + content: "\f462"; } + +.fa-bandcamp:before { + content: "\f2d5"; } + +.fa-barcode:before { + content: "\f02a"; } + +.fa-bars:before { + content: "\f0c9"; } + +.fa-baseball-ball:before { + content: "\f433"; } + +.fa-basketball-ball:before { + content: "\f434"; } + +.fa-bath:before { + content: "\f2cd"; } + +.fa-battery-empty:before { + content: "\f244"; } + +.fa-battery-full:before { + content: "\f240"; } + +.fa-battery-half:before { + content: "\f242"; } + +.fa-battery-quarter:before { + content: "\f243"; } + +.fa-battery-three-quarters:before { + content: "\f241"; } + +.fa-battle-net:before { + content: "\f835"; } + +.fa-bed:before { + content: "\f236"; } + +.fa-beer:before { + content: "\f0fc"; } + +.fa-behance:before { + content: "\f1b4"; } + +.fa-behance-square:before { + content: "\f1b5"; } + +.fa-bell:before { + content: "\f0f3"; } + +.fa-bell-slash:before { + content: "\f1f6"; } + +.fa-bezier-curve:before { + content: "\f55b"; } + +.fa-bible:before { + content: "\f647"; } + +.fa-bicycle:before { + content: "\f206"; } + +.fa-biking:before { + content: "\f84a"; } + +.fa-bimobject:before { + content: "\f378"; } + +.fa-binoculars:before { + content: "\f1e5"; } + +.fa-biohazard:before { + content: "\f780"; } + +.fa-birthday-cake:before { + content: "\f1fd"; } + +.fa-bitbucket:before { + content: "\f171"; } + +.fa-bitcoin:before { + content: "\f379"; } + +.fa-bity:before { + content: "\f37a"; } + +.fa-black-tie:before { + content: "\f27e"; } + +.fa-blackberry:before { + content: "\f37b"; } + +.fa-blender:before { + content: "\f517"; } + +.fa-blender-phone:before { + content: "\f6b6"; } + +.fa-blind:before { + content: "\f29d"; } + +.fa-blog:before { + content: "\f781"; } + +.fa-blogger:before { + content: "\f37c"; } + +.fa-blogger-b:before { + content: "\f37d"; } + +.fa-bluetooth:before { + content: "\f293"; } + +.fa-bluetooth-b:before { + content: "\f294"; } + +.fa-bold:before { + content: "\f032"; } + +.fa-bolt:before { + content: "\f0e7"; } + +.fa-bomb:before { + content: "\f1e2"; } + +.fa-bone:before { + content: "\f5d7"; } + +.fa-bong:before { + content: "\f55c"; } + +.fa-book:before { + content: "\f02d"; } + +.fa-book-dead:before { + content: "\f6b7"; } + +.fa-book-medical:before { + content: "\f7e6"; } + +.fa-book-open:before { + content: "\f518"; } + +.fa-book-reader:before { + content: "\f5da"; } + +.fa-bookmark:before { + content: "\f02e"; } + +.fa-bootstrap:before { + content: "\f836"; } + +.fa-border-all:before { + content: "\f84c"; } + +.fa-border-none:before { + content: "\f850"; } + +.fa-border-style:before { + content: "\f853"; } + +.fa-bowling-ball:before { + content: "\f436"; } + +.fa-box:before { + content: "\f466"; } + +.fa-box-open:before { + content: "\f49e"; } + +.fa-boxes:before { + content: "\f468"; } + +.fa-braille:before { + content: "\f2a1"; } + +.fa-brain:before { + content: "\f5dc"; } + +.fa-bread-slice:before { + content: "\f7ec"; } + +.fa-briefcase:before { + content: "\f0b1"; } + +.fa-briefcase-medical:before { + content: "\f469"; } + +.fa-broadcast-tower:before { + content: "\f519"; } + +.fa-broom:before { + content: "\f51a"; } + +.fa-brush:before { + content: "\f55d"; } + +.fa-btc:before { + content: "\f15a"; } + +.fa-buffer:before { + content: "\f837"; } + +.fa-bug:before { + content: "\f188"; } + +.fa-building:before { + content: "\f1ad"; } + +.fa-bullhorn:before { + content: "\f0a1"; } + +.fa-bullseye:before { + content: "\f140"; } + +.fa-burn:before { + content: "\f46a"; } + +.fa-buromobelexperte:before { + content: "\f37f"; } + +.fa-bus:before { + content: "\f207"; } + +.fa-bus-alt:before { + content: "\f55e"; } + +.fa-business-time:before { + content: "\f64a"; } + +.fa-buy-n-large:before { + content: "\f8a6"; } + +.fa-buysellads:before { + content: "\f20d"; } + +.fa-calculator:before { + content: "\f1ec"; } + +.fa-calendar:before { + content: "\f133"; } + +.fa-calendar-alt:before { + content: "\f073"; } + +.fa-calendar-check:before { + content: "\f274"; } + +.fa-calendar-day:before { + content: "\f783"; } + +.fa-calendar-minus:before { + content: "\f272"; } + +.fa-calendar-plus:before { + content: "\f271"; } + +.fa-calendar-times:before { + content: "\f273"; } + +.fa-calendar-week:before { + content: "\f784"; } + +.fa-camera:before { + content: "\f030"; } + +.fa-camera-retro:before { + content: "\f083"; } + +.fa-campground:before { + content: "\f6bb"; } + +.fa-canadian-maple-leaf:before { + content: "\f785"; } + +.fa-candy-cane:before { + content: "\f786"; } + +.fa-cannabis:before { + content: "\f55f"; } + +.fa-capsules:before { + content: "\f46b"; } + +.fa-car:before { + content: "\f1b9"; } + +.fa-car-alt:before { + content: "\f5de"; } + +.fa-car-battery:before { + content: "\f5df"; } + +.fa-car-crash:before { + content: "\f5e1"; } + +.fa-car-side:before { + content: "\f5e4"; } + +.fa-caravan:before { + content: "\f8ff"; } + +.fa-caret-down:before { + content: "\f0d7"; } + +.fa-caret-left:before { + content: "\f0d9"; } + +.fa-caret-right:before { + content: "\f0da"; } + +.fa-caret-square-down:before { + content: "\f150"; } + +.fa-caret-square-left:before { + content: "\f191"; } + +.fa-caret-square-right:before { + content: "\f152"; } + +.fa-caret-square-up:before { + content: "\f151"; } + +.fa-caret-up:before { + content: "\f0d8"; } + +.fa-carrot:before { + content: "\f787"; } + +.fa-cart-arrow-down:before { + content: "\f218"; } + +.fa-cart-plus:before { + content: "\f217"; } + +.fa-cash-register:before { + content: "\f788"; } + +.fa-cat:before { + content: "\f6be"; } + +.fa-cc-amazon-pay:before { + content: "\f42d"; } + +.fa-cc-amex:before { + content: "\f1f3"; } + +.fa-cc-apple-pay:before { + content: "\f416"; } + +.fa-cc-diners-club:before { + content: "\f24c"; } + +.fa-cc-discover:before { + content: "\f1f2"; } + +.fa-cc-jcb:before { + content: "\f24b"; } + +.fa-cc-mastercard:before { + content: "\f1f1"; } + +.fa-cc-paypal:before { + content: "\f1f4"; } + +.fa-cc-stripe:before { + content: "\f1f5"; } + +.fa-cc-visa:before { + content: "\f1f0"; } + +.fa-centercode:before { + content: "\f380"; } + +.fa-centos:before { + content: "\f789"; } + +.fa-certificate:before { + content: "\f0a3"; } + +.fa-chair:before { + content: "\f6c0"; } + +.fa-chalkboard:before { + content: "\f51b"; } + +.fa-chalkboard-teacher:before { + content: "\f51c"; } + +.fa-charging-station:before { + content: "\f5e7"; } + +.fa-chart-area:before { + content: "\f1fe"; } + +.fa-chart-bar:before { + content: "\f080"; } + +.fa-chart-line:before { + content: "\f201"; } + +.fa-chart-pie:before { + content: "\f200"; } + +.fa-check:before { + content: "\f00c"; } + +.fa-check-circle:before { + content: "\f058"; } + +.fa-check-double:before { + content: "\f560"; } + +.fa-check-square:before { + content: "\f14a"; } + +.fa-cheese:before { + content: "\f7ef"; } + +.fa-chess:before { + content: "\f439"; } + +.fa-chess-bishop:before { + content: "\f43a"; } + +.fa-chess-board:before { + content: "\f43c"; } + +.fa-chess-king:before { + content: "\f43f"; } + +.fa-chess-knight:before { + content: "\f441"; } + +.fa-chess-pawn:before { + content: "\f443"; } + +.fa-chess-queen:before { + content: "\f445"; } + +.fa-chess-rook:before { + content: "\f447"; } + +.fa-chevron-circle-down:before { + content: "\f13a"; } + +.fa-chevron-circle-left:before { + content: "\f137"; } + +.fa-chevron-circle-right:before { + content: "\f138"; } + +.fa-chevron-circle-up:before { + content: "\f139"; } + +.fa-chevron-down:before { + content: "\f078"; } + +.fa-chevron-left:before { + content: "\f053"; } + +.fa-chevron-right:before { + content: "\f054"; } + +.fa-chevron-up:before { + content: "\f077"; } + +.fa-child:before { + content: "\f1ae"; } + +.fa-chrome:before { + content: "\f268"; } + +.fa-chromecast:before { + content: "\f838"; } + +.fa-church:before { + content: "\f51d"; } + +.fa-circle:before { + content: "\f111"; } + +.fa-circle-notch:before { + content: "\f1ce"; } + +.fa-city:before { + content: "\f64f"; } + +.fa-clinic-medical:before { + content: "\f7f2"; } + +.fa-clipboard:before { + content: "\f328"; } + +.fa-clipboard-check:before { + content: "\f46c"; } + +.fa-clipboard-list:before { + content: "\f46d"; } + +.fa-clock:before { + content: "\f017"; } + +.fa-clone:before { + content: "\f24d"; } + +.fa-closed-captioning:before { + content: "\f20a"; } + +.fa-cloud:before { + content: "\f0c2"; } + +.fa-cloud-download-alt:before { + content: "\f381"; } + +.fa-cloud-meatball:before { + content: "\f73b"; } + +.fa-cloud-moon:before { + content: "\f6c3"; } + +.fa-cloud-moon-rain:before { + content: "\f73c"; } + +.fa-cloud-rain:before { + content: "\f73d"; } + +.fa-cloud-showers-heavy:before { + content: "\f740"; } + +.fa-cloud-sun:before { + content: "\f6c4"; } + +.fa-cloud-sun-rain:before { + content: "\f743"; } + +.fa-cloud-upload-alt:before { + content: "\f382"; } + +.fa-cloudscale:before { + content: "\f383"; } + +.fa-cloudsmith:before { + content: "\f384"; } + +.fa-cloudversify:before { + content: "\f385"; } + +.fa-cocktail:before { + content: "\f561"; } + +.fa-code:before { + content: "\f121"; } + +.fa-code-branch:before { + content: "\f126"; } + +.fa-codepen:before { + content: "\f1cb"; } + +.fa-codiepie:before { + content: "\f284"; } + +.fa-coffee:before { + content: "\f0f4"; } + +.fa-cog:before { + content: "\f013"; } + +.fa-cogs:before { + content: "\f085"; } + +.fa-coins:before { + content: "\f51e"; } + +.fa-columns:before { + content: "\f0db"; } + +.fa-comment:before { + content: "\f075"; } + +.fa-comment-alt:before { + content: "\f27a"; } + +.fa-comment-dollar:before { + content: "\f651"; } + +.fa-comment-dots:before { + content: "\f4ad"; } + +.fa-comment-medical:before { + content: "\f7f5"; } + +.fa-comment-slash:before { + content: "\f4b3"; } + +.fa-comments:before { + content: "\f086"; } + +.fa-comments-dollar:before { + content: "\f653"; } + +.fa-compact-disc:before { + content: "\f51f"; } + +.fa-compass:before { + content: "\f14e"; } + +.fa-compress:before { + content: "\f066"; } + +.fa-compress-alt:before { + content: "\f422"; } + +.fa-compress-arrows-alt:before { + content: "\f78c"; } + +.fa-concierge-bell:before { + content: "\f562"; } + +.fa-confluence:before { + content: "\f78d"; } + +.fa-connectdevelop:before { + content: "\f20e"; } + +.fa-contao:before { + content: "\f26d"; } + +.fa-cookie:before { + content: "\f563"; } + +.fa-cookie-bite:before { + content: "\f564"; } + +.fa-copy:before { + content: "\f0c5"; } + +.fa-copyright:before { + content: "\f1f9"; } + +.fa-cotton-bureau:before { + content: "\f89e"; } + +.fa-couch:before { + content: "\f4b8"; } + +.fa-cpanel:before { + content: "\f388"; } + +.fa-creative-commons:before { + content: "\f25e"; } + +.fa-creative-commons-by:before { + content: "\f4e7"; } + +.fa-creative-commons-nc:before { + content: "\f4e8"; } + +.fa-creative-commons-nc-eu:before { + content: "\f4e9"; } + +.fa-creative-commons-nc-jp:before { + content: "\f4ea"; } + +.fa-creative-commons-nd:before { + content: "\f4eb"; } + +.fa-creative-commons-pd:before { + content: "\f4ec"; } + +.fa-creative-commons-pd-alt:before { + content: "\f4ed"; } + +.fa-creative-commons-remix:before { + content: "\f4ee"; } + +.fa-creative-commons-sa:before { + content: "\f4ef"; } + +.fa-creative-commons-sampling:before { + content: "\f4f0"; } + +.fa-creative-commons-sampling-plus:before { + content: "\f4f1"; } + +.fa-creative-commons-share:before { + content: "\f4f2"; } + +.fa-creative-commons-zero:before { + content: "\f4f3"; } + +.fa-credit-card:before { + content: "\f09d"; } + +.fa-critical-role:before { + content: "\f6c9"; } + +.fa-crop:before { + content: "\f125"; } + +.fa-crop-alt:before { + content: "\f565"; } + +.fa-cross:before { + content: "\f654"; } + +.fa-crosshairs:before { + content: "\f05b"; } + +.fa-crow:before { + content: "\f520"; } + +.fa-crown:before { + content: "\f521"; } + +.fa-crutch:before { + content: "\f7f7"; } + +.fa-css3:before { + content: "\f13c"; } + +.fa-css3-alt:before { + content: "\f38b"; } + +.fa-cube:before { + content: "\f1b2"; } + +.fa-cubes:before { + content: "\f1b3"; } + +.fa-cut:before { + content: "\f0c4"; } + +.fa-cuttlefish:before { + content: "\f38c"; } + +.fa-d-and-d:before { + content: "\f38d"; } + +.fa-d-and-d-beyond:before { + content: "\f6ca"; } + +.fa-dailymotion:before { + content: "\f952"; } + +.fa-dashcube:before { + content: "\f210"; } + +.fa-database:before { + content: "\f1c0"; } + +.fa-deaf:before { + content: "\f2a4"; } + +.fa-delicious:before { + content: "\f1a5"; } + +.fa-democrat:before { + content: "\f747"; } + +.fa-deploydog:before { + content: "\f38e"; } + +.fa-deskpro:before { + content: "\f38f"; } + +.fa-desktop:before { + content: "\f108"; } + +.fa-dev:before { + content: "\f6cc"; } + +.fa-deviantart:before { + content: "\f1bd"; } + +.fa-dharmachakra:before { + content: "\f655"; } + +.fa-dhl:before { + content: "\f790"; } + +.fa-diagnoses:before { + content: "\f470"; } + +.fa-diaspora:before { + content: "\f791"; } + +.fa-dice:before { + content: "\f522"; } + +.fa-dice-d20:before { + content: "\f6cf"; } + +.fa-dice-d6:before { + content: "\f6d1"; } + +.fa-dice-five:before { + content: "\f523"; } + +.fa-dice-four:before { + content: "\f524"; } + +.fa-dice-one:before { + content: "\f525"; } + +.fa-dice-six:before { + content: "\f526"; } + +.fa-dice-three:before { + content: "\f527"; } + +.fa-dice-two:before { + content: "\f528"; } + +.fa-digg:before { + content: "\f1a6"; } + +.fa-digital-ocean:before { + content: "\f391"; } + +.fa-digital-tachograph:before { + content: "\f566"; } + +.fa-directions:before { + content: "\f5eb"; } + +.fa-discord:before { + content: "\f392"; } + +.fa-discourse:before { + content: "\f393"; } + +.fa-divide:before { + content: "\f529"; } + +.fa-dizzy:before { + content: "\f567"; } + +.fa-dna:before { + content: "\f471"; } + +.fa-dochub:before { + content: "\f394"; } + +.fa-docker:before { + content: "\f395"; } + +.fa-dog:before { + content: "\f6d3"; } + +.fa-dollar-sign:before { + content: "\f155"; } + +.fa-dolly:before { + content: "\f472"; } + +.fa-dolly-flatbed:before { + content: "\f474"; } + +.fa-donate:before { + content: "\f4b9"; } + +.fa-door-closed:before { + content: "\f52a"; } + +.fa-door-open:before { + content: "\f52b"; } + +.fa-dot-circle:before { + content: "\f192"; } + +.fa-dove:before { + content: "\f4ba"; } + +.fa-download:before { + content: "\f019"; } + +.fa-draft2digital:before { + content: "\f396"; } + +.fa-drafting-compass:before { + content: "\f568"; } + +.fa-dragon:before { + content: "\f6d5"; } + +.fa-draw-polygon:before { + content: "\f5ee"; } + +.fa-dribbble:before { + content: "\f17d"; } + +.fa-dribbble-square:before { + content: "\f397"; } + +.fa-dropbox:before { + content: "\f16b"; } + +.fa-drum:before { + content: "\f569"; } + +.fa-drum-steelpan:before { + content: "\f56a"; } + +.fa-drumstick-bite:before { + content: "\f6d7"; } + +.fa-drupal:before { + content: "\f1a9"; } + +.fa-dumbbell:before { + content: "\f44b"; } + +.fa-dumpster:before { + content: "\f793"; } + +.fa-dumpster-fire:before { + content: "\f794"; } + +.fa-dungeon:before { + content: "\f6d9"; } + +.fa-dyalog:before { + content: "\f399"; } + +.fa-earlybirds:before { + content: "\f39a"; } + +.fa-ebay:before { + content: "\f4f4"; } + +.fa-edge:before { + content: "\f282"; } + +.fa-edit:before { + content: "\f044"; } + +.fa-egg:before { + content: "\f7fb"; } + +.fa-eject:before { + content: "\f052"; } + +.fa-elementor:before { + content: "\f430"; } + +.fa-ellipsis-h:before { + content: "\f141"; } + +.fa-ellipsis-v:before { + content: "\f142"; } + +.fa-ello:before { + content: "\f5f1"; } + +.fa-ember:before { + content: "\f423"; } + +.fa-empire:before { + content: "\f1d1"; } + +.fa-envelope:before { + content: "\f0e0"; } + +.fa-envelope-open:before { + content: "\f2b6"; } + +.fa-envelope-open-text:before { + content: "\f658"; } + +.fa-envelope-square:before { + content: "\f199"; } + +.fa-envira:before { + content: "\f299"; } + +.fa-equals:before { + content: "\f52c"; } + +.fa-eraser:before { + content: "\f12d"; } + +.fa-erlang:before { + content: "\f39d"; } + +.fa-ethereum:before { + content: "\f42e"; } + +.fa-ethernet:before { + content: "\f796"; } + +.fa-etsy:before { + content: "\f2d7"; } + +.fa-euro-sign:before { + content: "\f153"; } + +.fa-evernote:before { + content: "\f839"; } + +.fa-exchange-alt:before { + content: "\f362"; } + +.fa-exclamation:before { + content: "\f12a"; } + +.fa-exclamation-circle:before { + content: "\f06a"; } + +.fa-exclamation-triangle:before { + content: "\f071"; } + +.fa-expand:before { + content: "\f065"; } + +.fa-expand-alt:before { + content: "\f424"; } + +.fa-expand-arrows-alt:before { + content: "\f31e"; } + +.fa-expeditedssl:before { + content: "\f23e"; } + +.fa-external-link-alt:before { + content: "\f35d"; } + +.fa-external-link-square-alt:before { + content: "\f360"; } + +.fa-eye:before { + content: "\f06e"; } + +.fa-eye-dropper:before { + content: "\f1fb"; } + +.fa-eye-slash:before { + content: "\f070"; } + +.fa-facebook:before { + content: "\f09a"; } + +.fa-facebook-f:before { + content: "\f39e"; } + +.fa-facebook-messenger:before { + content: "\f39f"; } + +.fa-facebook-square:before { + content: "\f082"; } + +.fa-fan:before { + content: "\f863"; } + +.fa-fantasy-flight-games:before { + content: "\f6dc"; } + +.fa-fast-backward:before { + content: "\f049"; } + +.fa-fast-forward:before { + content: "\f050"; } + +.fa-fax:before { + content: "\f1ac"; } + +.fa-feather:before { + content: "\f52d"; } + +.fa-feather-alt:before { + content: "\f56b"; } + +.fa-fedex:before { + content: "\f797"; } + +.fa-fedora:before { + content: "\f798"; } + +.fa-female:before { + content: "\f182"; } + +.fa-fighter-jet:before { + content: "\f0fb"; } + +.fa-figma:before { + content: "\f799"; } + +.fa-file:before { + content: "\f15b"; } + +.fa-file-alt:before { + content: "\f15c"; } + +.fa-file-archive:before { + content: "\f1c6"; } + +.fa-file-audio:before { + content: "\f1c7"; } + +.fa-file-code:before { + content: "\f1c9"; } + +.fa-file-contract:before { + content: "\f56c"; } + +.fa-file-csv:before { + content: "\f6dd"; } + +.fa-file-download:before { + content: "\f56d"; } + +.fa-file-excel:before { + content: "\f1c3"; } + +.fa-file-export:before { + content: "\f56e"; } + +.fa-file-image:before { + content: "\f1c5"; } + +.fa-file-import:before { + content: "\f56f"; } + +.fa-file-invoice:before { + content: "\f570"; } + +.fa-file-invoice-dollar:before { + content: "\f571"; } + +.fa-file-medical:before { + content: "\f477"; } + +.fa-file-medical-alt:before { + content: "\f478"; } + +.fa-file-pdf:before { + content: "\f1c1"; } + +.fa-file-powerpoint:before { + content: "\f1c4"; } + +.fa-file-prescription:before { + content: "\f572"; } + +.fa-file-signature:before { + content: "\f573"; } + +.fa-file-upload:before { + content: "\f574"; } + +.fa-file-video:before { + content: "\f1c8"; } + +.fa-file-word:before { + content: "\f1c2"; } + +.fa-fill:before { + content: "\f575"; } + +.fa-fill-drip:before { + content: "\f576"; } + +.fa-film:before { + content: "\f008"; } + +.fa-filter:before { + content: "\f0b0"; } + +.fa-fingerprint:before { + content: "\f577"; } + +.fa-fire:before { + content: "\f06d"; } + +.fa-fire-alt:before { + content: "\f7e4"; } + +.fa-fire-extinguisher:before { + content: "\f134"; } + +.fa-firefox:before { + content: "\f269"; } + +.fa-firefox-browser:before { + content: "\f907"; } + +.fa-first-aid:before { + content: "\f479"; } + +.fa-first-order:before { + content: "\f2b0"; } + +.fa-first-order-alt:before { + content: "\f50a"; } + +.fa-firstdraft:before { + content: "\f3a1"; } + +.fa-fish:before { + content: "\f578"; } + +.fa-fist-raised:before { + content: "\f6de"; } + +.fa-flag:before { + content: "\f024"; } + +.fa-flag-checkered:before { + content: "\f11e"; } + +.fa-flag-usa:before { + content: "\f74d"; } + +.fa-flask:before { + content: "\f0c3"; } + +.fa-flickr:before { + content: "\f16e"; } + +.fa-flipboard:before { + content: "\f44d"; } + +.fa-flushed:before { + content: "\f579"; } + +.fa-fly:before { + content: "\f417"; } + +.fa-folder:before { + content: "\f07b"; } + +.fa-folder-minus:before { + content: "\f65d"; } + +.fa-folder-open:before { + content: "\f07c"; } + +.fa-folder-plus:before { + content: "\f65e"; } + +.fa-font:before { + content: "\f031"; } + +.fa-font-awesome:before { + content: "\f2b4"; } + +.fa-font-awesome-alt:before { + content: "\f35c"; } + +.fa-font-awesome-flag:before { + content: "\f425"; } + +.fa-font-awesome-logo-full:before { + content: "\f4e6"; } + +.fa-fonticons:before { + content: "\f280"; } + +.fa-fonticons-fi:before { + content: "\f3a2"; } + +.fa-football-ball:before { + content: "\f44e"; } + +.fa-fort-awesome:before { + content: "\f286"; } + +.fa-fort-awesome-alt:before { + content: "\f3a3"; } + +.fa-forumbee:before { + content: "\f211"; } + +.fa-forward:before { + content: "\f04e"; } + +.fa-foursquare:before { + content: "\f180"; } + +.fa-free-code-camp:before { + content: "\f2c5"; } + +.fa-freebsd:before { + content: "\f3a4"; } + +.fa-frog:before { + content: "\f52e"; } + +.fa-frown:before { + content: "\f119"; } + +.fa-frown-open:before { + content: "\f57a"; } + +.fa-fulcrum:before { + content: "\f50b"; } + +.fa-funnel-dollar:before { + content: "\f662"; } + +.fa-futbol:before { + content: "\f1e3"; } + +.fa-galactic-republic:before { + content: "\f50c"; } + +.fa-galactic-senate:before { + content: "\f50d"; } + +.fa-gamepad:before { + content: "\f11b"; } + +.fa-gas-pump:before { + content: "\f52f"; } + +.fa-gavel:before { + content: "\f0e3"; } + +.fa-gem:before { + content: "\f3a5"; } + +.fa-genderless:before { + content: "\f22d"; } + +.fa-get-pocket:before { + content: "\f265"; } + +.fa-gg:before { + content: "\f260"; } + +.fa-gg-circle:before { + content: "\f261"; } + +.fa-ghost:before { + content: "\f6e2"; } + +.fa-gift:before { + content: "\f06b"; } + +.fa-gifts:before { + content: "\f79c"; } + +.fa-git:before { + content: "\f1d3"; } + +.fa-git-alt:before { + content: "\f841"; } + +.fa-git-square:before { + content: "\f1d2"; } + +.fa-github:before { + content: "\f09b"; } + +.fa-github-alt:before { + content: "\f113"; } + +.fa-github-square:before { + content: "\f092"; } + +.fa-gitkraken:before { + content: "\f3a6"; } + +.fa-gitlab:before { + content: "\f296"; } + +.fa-gitter:before { + content: "\f426"; } + +.fa-glass-cheers:before { + content: "\f79f"; } + +.fa-glass-martini:before { + content: "\f000"; } + +.fa-glass-martini-alt:before { + content: "\f57b"; } + +.fa-glass-whiskey:before { + content: "\f7a0"; } + +.fa-glasses:before { + content: "\f530"; } + +.fa-glide:before { + content: "\f2a5"; } + +.fa-glide-g:before { + content: "\f2a6"; } + +.fa-globe:before { + content: "\f0ac"; } + +.fa-globe-africa:before { + content: "\f57c"; } + +.fa-globe-americas:before { + content: "\f57d"; } + +.fa-globe-asia:before { + content: "\f57e"; } + +.fa-globe-europe:before { + content: "\f7a2"; } + +.fa-gofore:before { + content: "\f3a7"; } + +.fa-golf-ball:before { + content: "\f450"; } + +.fa-goodreads:before { + content: "\f3a8"; } + +.fa-goodreads-g:before { + content: "\f3a9"; } + +.fa-google:before { + content: "\f1a0"; } + +.fa-google-drive:before { + content: "\f3aa"; } + +.fa-google-play:before { + content: "\f3ab"; } + +.fa-google-plus:before { + content: "\f2b3"; } + +.fa-google-plus-g:before { + content: "\f0d5"; } + +.fa-google-plus-square:before { + content: "\f0d4"; } + +.fa-google-wallet:before { + content: "\f1ee"; } + +.fa-gopuram:before { + content: "\f664"; } + +.fa-graduation-cap:before { + content: "\f19d"; } + +.fa-gratipay:before { + content: "\f184"; } + +.fa-grav:before { + content: "\f2d6"; } + +.fa-greater-than:before { + content: "\f531"; } + +.fa-greater-than-equal:before { + content: "\f532"; } + +.fa-grimace:before { + content: "\f57f"; } + +.fa-grin:before { + content: "\f580"; } + +.fa-grin-alt:before { + content: "\f581"; } + +.fa-grin-beam:before { + content: "\f582"; } + +.fa-grin-beam-sweat:before { + content: "\f583"; } + +.fa-grin-hearts:before { + content: "\f584"; } + +.fa-grin-squint:before { + content: "\f585"; } + +.fa-grin-squint-tears:before { + content: "\f586"; } + +.fa-grin-stars:before { + content: "\f587"; } + +.fa-grin-tears:before { + content: "\f588"; } + +.fa-grin-tongue:before { + content: "\f589"; } + +.fa-grin-tongue-squint:before { + content: "\f58a"; } + +.fa-grin-tongue-wink:before { + content: "\f58b"; } + +.fa-grin-wink:before { + content: "\f58c"; } + +.fa-grip-horizontal:before { + content: "\f58d"; } + +.fa-grip-lines:before { + content: "\f7a4"; } + +.fa-grip-lines-vertical:before { + content: "\f7a5"; } + +.fa-grip-vertical:before { + content: "\f58e"; } + +.fa-gripfire:before { + content: "\f3ac"; } + +.fa-grunt:before { + content: "\f3ad"; } + +.fa-guitar:before { + content: "\f7a6"; } + +.fa-gulp:before { + content: "\f3ae"; } + +.fa-h-square:before { + content: "\f0fd"; } + +.fa-hacker-news:before { + content: "\f1d4"; } + +.fa-hacker-news-square:before { + content: "\f3af"; } + +.fa-hackerrank:before { + content: "\f5f7"; } + +.fa-hamburger:before { + content: "\f805"; } + +.fa-hammer:before { + content: "\f6e3"; } + +.fa-hamsa:before { + content: "\f665"; } + +.fa-hand-holding:before { + content: "\f4bd"; } + +.fa-hand-holding-heart:before { + content: "\f4be"; } + +.fa-hand-holding-usd:before { + content: "\f4c0"; } + +.fa-hand-lizard:before { + content: "\f258"; } + +.fa-hand-middle-finger:before { + content: "\f806"; } + +.fa-hand-paper:before { + content: "\f256"; } + +.fa-hand-peace:before { + content: "\f25b"; } + +.fa-hand-point-down:before { + content: "\f0a7"; } + +.fa-hand-point-left:before { + content: "\f0a5"; } + +.fa-hand-point-right:before { + content: "\f0a4"; } + +.fa-hand-point-up:before { + content: "\f0a6"; } + +.fa-hand-pointer:before { + content: "\f25a"; } + +.fa-hand-rock:before { + content: "\f255"; } + +.fa-hand-scissors:before { + content: "\f257"; } + +.fa-hand-spock:before { + content: "\f259"; } + +.fa-hands:before { + content: "\f4c2"; } + +.fa-hands-helping:before { + content: "\f4c4"; } + +.fa-handshake:before { + content: "\f2b5"; } + +.fa-hanukiah:before { + content: "\f6e6"; } + +.fa-hard-hat:before { + content: "\f807"; } + +.fa-hashtag:before { + content: "\f292"; } + +.fa-hat-cowboy:before { + content: "\f8c0"; } + +.fa-hat-cowboy-side:before { + content: "\f8c1"; } + +.fa-hat-wizard:before { + content: "\f6e8"; } + +.fa-hdd:before { + content: "\f0a0"; } + +.fa-heading:before { + content: "\f1dc"; } + +.fa-headphones:before { + content: "\f025"; } + +.fa-headphones-alt:before { + content: "\f58f"; } + +.fa-headset:before { + content: "\f590"; } + +.fa-heart:before { + content: "\f004"; } + +.fa-heart-broken:before { + content: "\f7a9"; } + +.fa-heartbeat:before { + content: "\f21e"; } + +.fa-helicopter:before { + content: "\f533"; } + +.fa-highlighter:before { + content: "\f591"; } + +.fa-hiking:before { + content: "\f6ec"; } + +.fa-hippo:before { + content: "\f6ed"; } + +.fa-hips:before { + content: "\f452"; } + +.fa-hire-a-helper:before { + content: "\f3b0"; } + +.fa-history:before { + content: "\f1da"; } + +.fa-hockey-puck:before { + content: "\f453"; } + +.fa-holly-berry:before { + content: "\f7aa"; } + +.fa-home:before { + content: "\f015"; } + +.fa-hooli:before { + content: "\f427"; } + +.fa-hornbill:before { + content: "\f592"; } + +.fa-horse:before { + content: "\f6f0"; } + +.fa-horse-head:before { + content: "\f7ab"; } + +.fa-hospital:before { + content: "\f0f8"; } + +.fa-hospital-alt:before { + content: "\f47d"; } + +.fa-hospital-symbol:before { + content: "\f47e"; } + +.fa-hot-tub:before { + content: "\f593"; } + +.fa-hotdog:before { + content: "\f80f"; } + +.fa-hotel:before { + content: "\f594"; } + +.fa-hotjar:before { + content: "\f3b1"; } + +.fa-hourglass:before { + content: "\f254"; } + +.fa-hourglass-end:before { + content: "\f253"; } + +.fa-hourglass-half:before { + content: "\f252"; } + +.fa-hourglass-start:before { + content: "\f251"; } + +.fa-house-damage:before { + content: "\f6f1"; } + +.fa-houzz:before { + content: "\f27c"; } + +.fa-hryvnia:before { + content: "\f6f2"; } + +.fa-html5:before { + content: "\f13b"; } + +.fa-hubspot:before { + content: "\f3b2"; } + +.fa-i-cursor:before { + content: "\f246"; } + +.fa-ice-cream:before { + content: "\f810"; } + +.fa-icicles:before { + content: "\f7ad"; } + +.fa-icons:before { + content: "\f86d"; } + +.fa-id-badge:before { + content: "\f2c1"; } + +.fa-id-card:before { + content: "\f2c2"; } + +.fa-id-card-alt:before { + content: "\f47f"; } + +.fa-ideal:before { + content: "\f913"; } + +.fa-igloo:before { + content: "\f7ae"; } + +.fa-image:before { + content: "\f03e"; } + +.fa-images:before { + content: "\f302"; } + +.fa-imdb:before { + content: "\f2d8"; } + +.fa-inbox:before { + content: "\f01c"; } + +.fa-indent:before { + content: "\f03c"; } + +.fa-industry:before { + content: "\f275"; } + +.fa-infinity:before { + content: "\f534"; } + +.fa-info:before { + content: "\f129"; } + +.fa-info-circle:before { + content: "\f05a"; } + +.fa-instagram:before { + content: "\f16d"; } + +.fa-instagram-square:before { + content: "\f955"; } + +.fa-intercom:before { + content: "\f7af"; } + +.fa-internet-explorer:before { + content: "\f26b"; } + +.fa-invision:before { + content: "\f7b0"; } + +.fa-ioxhost:before { + content: "\f208"; } + +.fa-italic:before { + content: "\f033"; } + +.fa-itch-io:before { + content: "\f83a"; } + +.fa-itunes:before { + content: "\f3b4"; } + +.fa-itunes-note:before { + content: "\f3b5"; } + +.fa-java:before { + content: "\f4e4"; } + +.fa-jedi:before { + content: "\f669"; } + +.fa-jedi-order:before { + content: "\f50e"; } + +.fa-jenkins:before { + content: "\f3b6"; } + +.fa-jira:before { + content: "\f7b1"; } + +.fa-joget:before { + content: "\f3b7"; } + +.fa-joint:before { + content: "\f595"; } + +.fa-joomla:before { + content: "\f1aa"; } + +.fa-journal-whills:before { + content: "\f66a"; } + +.fa-js:before { + content: "\f3b8"; } + +.fa-js-square:before { + content: "\f3b9"; } + +.fa-jsfiddle:before { + content: "\f1cc"; } + +.fa-kaaba:before { + content: "\f66b"; } + +.fa-kaggle:before { + content: "\f5fa"; } + +.fa-key:before { + content: "\f084"; } + +.fa-keybase:before { + content: "\f4f5"; } + +.fa-keyboard:before { + content: "\f11c"; } + +.fa-keycdn:before { + content: "\f3ba"; } + +.fa-khanda:before { + content: "\f66d"; } + +.fa-kickstarter:before { + content: "\f3bb"; } + +.fa-kickstarter-k:before { + content: "\f3bc"; } + +.fa-kiss:before { + content: "\f596"; } + +.fa-kiss-beam:before { + content: "\f597"; } + +.fa-kiss-wink-heart:before { + content: "\f598"; } + +.fa-kiwi-bird:before { + content: "\f535"; } + +.fa-korvue:before { + content: "\f42f"; } + +.fa-landmark:before { + content: "\f66f"; } + +.fa-language:before { + content: "\f1ab"; } + +.fa-laptop:before { + content: "\f109"; } + +.fa-laptop-code:before { + content: "\f5fc"; } + +.fa-laptop-medical:before { + content: "\f812"; } + +.fa-laravel:before { + content: "\f3bd"; } + +.fa-lastfm:before { + content: "\f202"; } + +.fa-lastfm-square:before { + content: "\f203"; } + +.fa-laugh:before { + content: "\f599"; } + +.fa-laugh-beam:before { + content: "\f59a"; } + +.fa-laugh-squint:before { + content: "\f59b"; } + +.fa-laugh-wink:before { + content: "\f59c"; } + +.fa-layer-group:before { + content: "\f5fd"; } + +.fa-leaf:before { + content: "\f06c"; } + +.fa-leanpub:before { + content: "\f212"; } + +.fa-lemon:before { + content: "\f094"; } + +.fa-less:before { + content: "\f41d"; } + +.fa-less-than:before { + content: "\f536"; } + +.fa-less-than-equal:before { + content: "\f537"; } + +.fa-level-down-alt:before { + content: "\f3be"; } + +.fa-level-up-alt:before { + content: "\f3bf"; } + +.fa-life-ring:before { + content: "\f1cd"; } + +.fa-lightbulb:before { + content: "\f0eb"; } + +.fa-line:before { + content: "\f3c0"; } + +.fa-link:before { + content: "\f0c1"; } + +.fa-linkedin:before { + content: "\f08c"; } + +.fa-linkedin-in:before { + content: "\f0e1"; } + +.fa-linode:before { + content: "\f2b8"; } + +.fa-linux:before { + content: "\f17c"; } + +.fa-lira-sign:before { + content: "\f195"; } + +.fa-list:before { + content: "\f03a"; } + +.fa-list-alt:before { + content: "\f022"; } + +.fa-list-ol:before { + content: "\f0cb"; } + +.fa-list-ul:before { + content: "\f0ca"; } + +.fa-location-arrow:before { + content: "\f124"; } + +.fa-lock:before { + content: "\f023"; } + +.fa-lock-open:before { + content: "\f3c1"; } + +.fa-long-arrow-alt-down:before { + content: "\f309"; } + +.fa-long-arrow-alt-left:before { + content: "\f30a"; } + +.fa-long-arrow-alt-right:before { + content: "\f30b"; } + +.fa-long-arrow-alt-up:before { + content: "\f30c"; } + +.fa-low-vision:before { + content: "\f2a8"; } + +.fa-luggage-cart:before { + content: "\f59d"; } + +.fa-lyft:before { + content: "\f3c3"; } + +.fa-magento:before { + content: "\f3c4"; } + +.fa-magic:before { + content: "\f0d0"; } + +.fa-magnet:before { + content: "\f076"; } + +.fa-mail-bulk:before { + content: "\f674"; } + +.fa-mailchimp:before { + content: "\f59e"; } + +.fa-male:before { + content: "\f183"; } + +.fa-mandalorian:before { + content: "\f50f"; } + +.fa-map:before { + content: "\f279"; } + +.fa-map-marked:before { + content: "\f59f"; } + +.fa-map-marked-alt:before { + content: "\f5a0"; } + +.fa-map-marker:before { + content: "\f041"; } + +.fa-map-marker-alt:before { + content: "\f3c5"; } + +.fa-map-pin:before { + content: "\f276"; } + +.fa-map-signs:before { + content: "\f277"; } + +.fa-markdown:before { + content: "\f60f"; } + +.fa-marker:before { + content: "\f5a1"; } + +.fa-mars:before { + content: "\f222"; } + +.fa-mars-double:before { + content: "\f227"; } + +.fa-mars-stroke:before { + content: "\f229"; } + +.fa-mars-stroke-h:before { + content: "\f22b"; } + +.fa-mars-stroke-v:before { + content: "\f22a"; } + +.fa-mask:before { + content: "\f6fa"; } + +.fa-mastodon:before { + content: "\f4f6"; } + +.fa-maxcdn:before { + content: "\f136"; } + +.fa-mdb:before { + content: "\f8ca"; } + +.fa-medal:before { + content: "\f5a2"; } + +.fa-medapps:before { + content: "\f3c6"; } + +.fa-medium:before { + content: "\f23a"; } + +.fa-medium-m:before { + content: "\f3c7"; } + +.fa-medkit:before { + content: "\f0fa"; } + +.fa-medrt:before { + content: "\f3c8"; } + +.fa-meetup:before { + content: "\f2e0"; } + +.fa-megaport:before { + content: "\f5a3"; } + +.fa-meh:before { + content: "\f11a"; } + +.fa-meh-blank:before { + content: "\f5a4"; } + +.fa-meh-rolling-eyes:before { + content: "\f5a5"; } + +.fa-memory:before { + content: "\f538"; } + +.fa-mendeley:before { + content: "\f7b3"; } + +.fa-menorah:before { + content: "\f676"; } + +.fa-mercury:before { + content: "\f223"; } + +.fa-meteor:before { + content: "\f753"; } + +.fa-microblog:before { + content: "\f91a"; } + +.fa-microchip:before { + content: "\f2db"; } + +.fa-microphone:before { + content: "\f130"; } + +.fa-microphone-alt:before { + content: "\f3c9"; } + +.fa-microphone-alt-slash:before { + content: "\f539"; } + +.fa-microphone-slash:before { + content: "\f131"; } + +.fa-microscope:before { + content: "\f610"; } + +.fa-microsoft:before { + content: "\f3ca"; } + +.fa-minus:before { + content: "\f068"; } + +.fa-minus-circle:before { + content: "\f056"; } + +.fa-minus-square:before { + content: "\f146"; } + +.fa-mitten:before { + content: "\f7b5"; } + +.fa-mix:before { + content: "\f3cb"; } + +.fa-mixcloud:before { + content: "\f289"; } + +.fa-mixer:before { + content: "\f956"; } + +.fa-mizuni:before { + content: "\f3cc"; } + +.fa-mobile:before { + content: "\f10b"; } + +.fa-mobile-alt:before { + content: "\f3cd"; } + +.fa-modx:before { + content: "\f285"; } + +.fa-monero:before { + content: "\f3d0"; } + +.fa-money-bill:before { + content: "\f0d6"; } + +.fa-money-bill-alt:before { + content: "\f3d1"; } + +.fa-money-bill-wave:before { + content: "\f53a"; } + +.fa-money-bill-wave-alt:before { + content: "\f53b"; } + +.fa-money-check:before { + content: "\f53c"; } + +.fa-money-check-alt:before { + content: "\f53d"; } + +.fa-monument:before { + content: "\f5a6"; } + +.fa-moon:before { + content: "\f186"; } + +.fa-mortar-pestle:before { + content: "\f5a7"; } + +.fa-mosque:before { + content: "\f678"; } + +.fa-motorcycle:before { + content: "\f21c"; } + +.fa-mountain:before { + content: "\f6fc"; } + +.fa-mouse:before { + content: "\f8cc"; } + +.fa-mouse-pointer:before { + content: "\f245"; } + +.fa-mug-hot:before { + content: "\f7b6"; } + +.fa-music:before { + content: "\f001"; } + +.fa-napster:before { + content: "\f3d2"; } + +.fa-neos:before { + content: "\f612"; } + +.fa-network-wired:before { + content: "\f6ff"; } + +.fa-neuter:before { + content: "\f22c"; } + +.fa-newspaper:before { + content: "\f1ea"; } + +.fa-nimblr:before { + content: "\f5a8"; } + +.fa-node:before { + content: "\f419"; } + +.fa-node-js:before { + content: "\f3d3"; } + +.fa-not-equal:before { + content: "\f53e"; } + +.fa-notes-medical:before { + content: "\f481"; } + +.fa-npm:before { + content: "\f3d4"; } + +.fa-ns8:before { + content: "\f3d5"; } + +.fa-nutritionix:before { + content: "\f3d6"; } + +.fa-object-group:before { + content: "\f247"; } + +.fa-object-ungroup:before { + content: "\f248"; } + +.fa-odnoklassniki:before { + content: "\f263"; } + +.fa-odnoklassniki-square:before { + content: "\f264"; } + +.fa-oil-can:before { + content: "\f613"; } + +.fa-old-republic:before { + content: "\f510"; } + +.fa-om:before { + content: "\f679"; } + +.fa-opencart:before { + content: "\f23d"; } + +.fa-openid:before { + content: "\f19b"; } + +.fa-opera:before { + content: "\f26a"; } + +.fa-optin-monster:before { + content: "\f23c"; } + +.fa-orcid:before { + content: "\f8d2"; } + +.fa-osi:before { + content: "\f41a"; } + +.fa-otter:before { + content: "\f700"; } + +.fa-outdent:before { + content: "\f03b"; } + +.fa-page4:before { + content: "\f3d7"; } + +.fa-pagelines:before { + content: "\f18c"; } + +.fa-pager:before { + content: "\f815"; } + +.fa-paint-brush:before { + content: "\f1fc"; } + +.fa-paint-roller:before { + content: "\f5aa"; } + +.fa-palette:before { + content: "\f53f"; } + +.fa-palfed:before { + content: "\f3d8"; } + +.fa-pallet:before { + content: "\f482"; } + +.fa-paper-plane:before { + content: "\f1d8"; } + +.fa-paperclip:before { + content: "\f0c6"; } + +.fa-parachute-box:before { + content: "\f4cd"; } + +.fa-paragraph:before { + content: "\f1dd"; } + +.fa-parking:before { + content: "\f540"; } + +.fa-passport:before { + content: "\f5ab"; } + +.fa-pastafarianism:before { + content: "\f67b"; } + +.fa-paste:before { + content: "\f0ea"; } + +.fa-patreon:before { + content: "\f3d9"; } + +.fa-pause:before { + content: "\f04c"; } + +.fa-pause-circle:before { + content: "\f28b"; } + +.fa-paw:before { + content: "\f1b0"; } + +.fa-paypal:before { + content: "\f1ed"; } + +.fa-peace:before { + content: "\f67c"; } + +.fa-pen:before { + content: "\f304"; } + +.fa-pen-alt:before { + content: "\f305"; } + +.fa-pen-fancy:before { + content: "\f5ac"; } + +.fa-pen-nib:before { + content: "\f5ad"; } + +.fa-pen-square:before { + content: "\f14b"; } + +.fa-pencil-alt:before { + content: "\f303"; } + +.fa-pencil-ruler:before { + content: "\f5ae"; } + +.fa-penny-arcade:before { + content: "\f704"; } + +.fa-people-carry:before { + content: "\f4ce"; } + +.fa-pepper-hot:before { + content: "\f816"; } + +.fa-percent:before { + content: "\f295"; } + +.fa-percentage:before { + content: "\f541"; } + +.fa-periscope:before { + content: "\f3da"; } + +.fa-person-booth:before { + content: "\f756"; } + +.fa-phabricator:before { + content: "\f3db"; } + +.fa-phoenix-framework:before { + content: "\f3dc"; } + +.fa-phoenix-squadron:before { + content: "\f511"; } + +.fa-phone:before { + content: "\f095"; } + +.fa-phone-alt:before { + content: "\f879"; } + +.fa-phone-slash:before { + content: "\f3dd"; } + +.fa-phone-square:before { + content: "\f098"; } + +.fa-phone-square-alt:before { + content: "\f87b"; } + +.fa-phone-volume:before { + content: "\f2a0"; } + +.fa-photo-video:before { + content: "\f87c"; } + +.fa-php:before { + content: "\f457"; } + +.fa-pied-piper:before { + content: "\f2ae"; } + +.fa-pied-piper-alt:before { + content: "\f1a8"; } + +.fa-pied-piper-hat:before { + content: "\f4e5"; } + +.fa-pied-piper-pp:before { + content: "\f1a7"; } + +.fa-pied-piper-square:before { + content: "\f91e"; } + +.fa-piggy-bank:before { + content: "\f4d3"; } + +.fa-pills:before { + content: "\f484"; } + +.fa-pinterest:before { + content: "\f0d2"; } + +.fa-pinterest-p:before { + content: "\f231"; } + +.fa-pinterest-square:before { + content: "\f0d3"; } + +.fa-pizza-slice:before { + content: "\f818"; } + +.fa-place-of-worship:before { + content: "\f67f"; } + +.fa-plane:before { + content: "\f072"; } + +.fa-plane-arrival:before { + content: "\f5af"; } + +.fa-plane-departure:before { + content: "\f5b0"; } + +.fa-play:before { + content: "\f04b"; } + +.fa-play-circle:before { + content: "\f144"; } + +.fa-playstation:before { + content: "\f3df"; } + +.fa-plug:before { + content: "\f1e6"; } + +.fa-plus:before { + content: "\f067"; } + +.fa-plus-circle:before { + content: "\f055"; } + +.fa-plus-square:before { + content: "\f0fe"; } + +.fa-podcast:before { + content: "\f2ce"; } + +.fa-poll:before { + content: "\f681"; } + +.fa-poll-h:before { + content: "\f682"; } + +.fa-poo:before { + content: "\f2fe"; } + +.fa-poo-storm:before { + content: "\f75a"; } + +.fa-poop:before { + content: "\f619"; } + +.fa-portrait:before { + content: "\f3e0"; } + +.fa-pound-sign:before { + content: "\f154"; } + +.fa-power-off:before { + content: "\f011"; } + +.fa-pray:before { + content: "\f683"; } + +.fa-praying-hands:before { + content: "\f684"; } + +.fa-prescription:before { + content: "\f5b1"; } + +.fa-prescription-bottle:before { + content: "\f485"; } + +.fa-prescription-bottle-alt:before { + content: "\f486"; } + +.fa-print:before { + content: "\f02f"; } + +.fa-procedures:before { + content: "\f487"; } + +.fa-product-hunt:before { + content: "\f288"; } + +.fa-project-diagram:before { + content: "\f542"; } + +.fa-pushed:before { + content: "\f3e1"; } + +.fa-puzzle-piece:before { + content: "\f12e"; } + +.fa-python:before { + content: "\f3e2"; } + +.fa-qq:before { + content: "\f1d6"; } + +.fa-qrcode:before { + content: "\f029"; } + +.fa-question:before { + content: "\f128"; } + +.fa-question-circle:before { + content: "\f059"; } + +.fa-quidditch:before { + content: "\f458"; } + +.fa-quinscape:before { + content: "\f459"; } + +.fa-quora:before { + content: "\f2c4"; } + +.fa-quote-left:before { + content: "\f10d"; } + +.fa-quote-right:before { + content: "\f10e"; } + +.fa-quran:before { + content: "\f687"; } + +.fa-r-project:before { + content: "\f4f7"; } + +.fa-radiation:before { + content: "\f7b9"; } + +.fa-radiation-alt:before { + content: "\f7ba"; } + +.fa-rainbow:before { + content: "\f75b"; } + +.fa-random:before { + content: "\f074"; } + +.fa-raspberry-pi:before { + content: "\f7bb"; } + +.fa-ravelry:before { + content: "\f2d9"; } + +.fa-react:before { + content: "\f41b"; } + +.fa-reacteurope:before { + content: "\f75d"; } + +.fa-readme:before { + content: "\f4d5"; } + +.fa-rebel:before { + content: "\f1d0"; } + +.fa-receipt:before { + content: "\f543"; } + +.fa-record-vinyl:before { + content: "\f8d9"; } + +.fa-recycle:before { + content: "\f1b8"; } + +.fa-red-river:before { + content: "\f3e3"; } + +.fa-reddit:before { + content: "\f1a1"; } + +.fa-reddit-alien:before { + content: "\f281"; } + +.fa-reddit-square:before { + content: "\f1a2"; } + +.fa-redhat:before { + content: "\f7bc"; } + +.fa-redo:before { + content: "\f01e"; } + +.fa-redo-alt:before { + content: "\f2f9"; } + +.fa-registered:before { + content: "\f25d"; } + +.fa-remove-format:before { + content: "\f87d"; } + +.fa-renren:before { + content: "\f18b"; } + +.fa-reply:before { + content: "\f3e5"; } + +.fa-reply-all:before { + content: "\f122"; } + +.fa-replyd:before { + content: "\f3e6"; } + +.fa-republican:before { + content: "\f75e"; } + +.fa-researchgate:before { + content: "\f4f8"; } + +.fa-resolving:before { + content: "\f3e7"; } + +.fa-restroom:before { + content: "\f7bd"; } + +.fa-retweet:before { + content: "\f079"; } + +.fa-rev:before { + content: "\f5b2"; } + +.fa-ribbon:before { + content: "\f4d6"; } + +.fa-ring:before { + content: "\f70b"; } + +.fa-road:before { + content: "\f018"; } + +.fa-robot:before { + content: "\f544"; } + +.fa-rocket:before { + content: "\f135"; } + +.fa-rocketchat:before { + content: "\f3e8"; } + +.fa-rockrms:before { + content: "\f3e9"; } + +.fa-route:before { + content: "\f4d7"; } + +.fa-rss:before { + content: "\f09e"; } + +.fa-rss-square:before { + content: "\f143"; } + +.fa-ruble-sign:before { + content: "\f158"; } + +.fa-ruler:before { + content: "\f545"; } + +.fa-ruler-combined:before { + content: "\f546"; } + +.fa-ruler-horizontal:before { + content: "\f547"; } + +.fa-ruler-vertical:before { + content: "\f548"; } + +.fa-running:before { + content: "\f70c"; } + +.fa-rupee-sign:before { + content: "\f156"; } + +.fa-sad-cry:before { + content: "\f5b3"; } + +.fa-sad-tear:before { + content: "\f5b4"; } + +.fa-safari:before { + content: "\f267"; } + +.fa-salesforce:before { + content: "\f83b"; } + +.fa-sass:before { + content: "\f41e"; } + +.fa-satellite:before { + content: "\f7bf"; } + +.fa-satellite-dish:before { + content: "\f7c0"; } + +.fa-save:before { + content: "\f0c7"; } + +.fa-schlix:before { + content: "\f3ea"; } + +.fa-school:before { + content: "\f549"; } + +.fa-screwdriver:before { + content: "\f54a"; } + +.fa-scribd:before { + content: "\f28a"; } + +.fa-scroll:before { + content: "\f70e"; } + +.fa-sd-card:before { + content: "\f7c2"; } + +.fa-search:before { + content: "\f002"; } + +.fa-search-dollar:before { + content: "\f688"; } + +.fa-search-location:before { + content: "\f689"; } + +.fa-search-minus:before { + content: "\f010"; } + +.fa-search-plus:before { + content: "\f00e"; } + +.fa-searchengin:before { + content: "\f3eb"; } + +.fa-seedling:before { + content: "\f4d8"; } + +.fa-sellcast:before { + content: "\f2da"; } + +.fa-sellsy:before { + content: "\f213"; } + +.fa-server:before { + content: "\f233"; } + +.fa-servicestack:before { + content: "\f3ec"; } + +.fa-shapes:before { + content: "\f61f"; } + +.fa-share:before { + content: "\f064"; } + +.fa-share-alt:before { + content: "\f1e0"; } + +.fa-share-alt-square:before { + content: "\f1e1"; } + +.fa-share-square:before { + content: "\f14d"; } + +.fa-shekel-sign:before { + content: "\f20b"; } + +.fa-shield-alt:before { + content: "\f3ed"; } + +.fa-ship:before { + content: "\f21a"; } + +.fa-shipping-fast:before { + content: "\f48b"; } + +.fa-shirtsinbulk:before { + content: "\f214"; } + +.fa-shoe-prints:before { + content: "\f54b"; } + +.fa-shopify:before { + content: "\f957"; } + +.fa-shopping-bag:before { + content: "\f290"; } + +.fa-shopping-basket:before { + content: "\f291"; } + +.fa-shopping-cart:before { + content: "\f07a"; } + +.fa-shopware:before { + content: "\f5b5"; } + +.fa-shower:before { + content: "\f2cc"; } + +.fa-shuttle-van:before { + content: "\f5b6"; } + +.fa-sign:before { + content: "\f4d9"; } + +.fa-sign-in-alt:before { + content: "\f2f6"; } + +.fa-sign-language:before { + content: "\f2a7"; } + +.fa-sign-out-alt:before { + content: "\f2f5"; } + +.fa-signal:before { + content: "\f012"; } + +.fa-signature:before { + content: "\f5b7"; } + +.fa-sim-card:before { + content: "\f7c4"; } + +.fa-simplybuilt:before { + content: "\f215"; } + +.fa-sistrix:before { + content: "\f3ee"; } + +.fa-sitemap:before { + content: "\f0e8"; } + +.fa-sith:before { + content: "\f512"; } + +.fa-skating:before { + content: "\f7c5"; } + +.fa-sketch:before { + content: "\f7c6"; } + +.fa-skiing:before { + content: "\f7c9"; } + +.fa-skiing-nordic:before { + content: "\f7ca"; } + +.fa-skull:before { + content: "\f54c"; } + +.fa-skull-crossbones:before { + content: "\f714"; } + +.fa-skyatlas:before { + content: "\f216"; } + +.fa-skype:before { + content: "\f17e"; } + +.fa-slack:before { + content: "\f198"; } + +.fa-slack-hash:before { + content: "\f3ef"; } + +.fa-slash:before { + content: "\f715"; } + +.fa-sleigh:before { + content: "\f7cc"; } + +.fa-sliders-h:before { + content: "\f1de"; } + +.fa-slideshare:before { + content: "\f1e7"; } + +.fa-smile:before { + content: "\f118"; } + +.fa-smile-beam:before { + content: "\f5b8"; } + +.fa-smile-wink:before { + content: "\f4da"; } + +.fa-smog:before { + content: "\f75f"; } + +.fa-smoking:before { + content: "\f48d"; } + +.fa-smoking-ban:before { + content: "\f54d"; } + +.fa-sms:before { + content: "\f7cd"; } + +.fa-snapchat:before { + content: "\f2ab"; } + +.fa-snapchat-ghost:before { + content: "\f2ac"; } + +.fa-snapchat-square:before { + content: "\f2ad"; } + +.fa-snowboarding:before { + content: "\f7ce"; } + +.fa-snowflake:before { + content: "\f2dc"; } + +.fa-snowman:before { + content: "\f7d0"; } + +.fa-snowplow:before { + content: "\f7d2"; } + +.fa-socks:before { + content: "\f696"; } + +.fa-solar-panel:before { + content: "\f5ba"; } + +.fa-sort:before { + content: "\f0dc"; } + +.fa-sort-alpha-down:before { + content: "\f15d"; } + +.fa-sort-alpha-down-alt:before { + content: "\f881"; } + +.fa-sort-alpha-up:before { + content: "\f15e"; } + +.fa-sort-alpha-up-alt:before { + content: "\f882"; } + +.fa-sort-amount-down:before { + content: "\f160"; } + +.fa-sort-amount-down-alt:before { + content: "\f884"; } + +.fa-sort-amount-up:before { + content: "\f161"; } + +.fa-sort-amount-up-alt:before { + content: "\f885"; } + +.fa-sort-down:before { + content: "\f0dd"; } + +.fa-sort-numeric-down:before { + content: "\f162"; } + +.fa-sort-numeric-down-alt:before { + content: "\f886"; } + +.fa-sort-numeric-up:before { + content: "\f163"; } + +.fa-sort-numeric-up-alt:before { + content: "\f887"; } + +.fa-sort-up:before { + content: "\f0de"; } + +.fa-soundcloud:before { + content: "\f1be"; } + +.fa-sourcetree:before { + content: "\f7d3"; } + +.fa-spa:before { + content: "\f5bb"; } + +.fa-space-shuttle:before { + content: "\f197"; } + +.fa-speakap:before { + content: "\f3f3"; } + +.fa-speaker-deck:before { + content: "\f83c"; } + +.fa-spell-check:before { + content: "\f891"; } + +.fa-spider:before { + content: "\f717"; } + +.fa-spinner:before { + content: "\f110"; } + +.fa-splotch:before { + content: "\f5bc"; } + +.fa-spotify:before { + content: "\f1bc"; } + +.fa-spray-can:before { + content: "\f5bd"; } + +.fa-square:before { + content: "\f0c8"; } + +.fa-square-full:before { + content: "\f45c"; } + +.fa-square-root-alt:before { + content: "\f698"; } + +.fa-squarespace:before { + content: "\f5be"; } + +.fa-stack-exchange:before { + content: "\f18d"; } + +.fa-stack-overflow:before { + content: "\f16c"; } + +.fa-stackpath:before { + content: "\f842"; } + +.fa-stamp:before { + content: "\f5bf"; } + +.fa-star:before { + content: "\f005"; } + +.fa-star-and-crescent:before { + content: "\f699"; } + +.fa-star-half:before { + content: "\f089"; } + +.fa-star-half-alt:before { + content: "\f5c0"; } + +.fa-star-of-david:before { + content: "\f69a"; } + +.fa-star-of-life:before { + content: "\f621"; } + +.fa-staylinked:before { + content: "\f3f5"; } + +.fa-steam:before { + content: "\f1b6"; } + +.fa-steam-square:before { + content: "\f1b7"; } + +.fa-steam-symbol:before { + content: "\f3f6"; } + +.fa-step-backward:before { + content: "\f048"; } + +.fa-step-forward:before { + content: "\f051"; } + +.fa-stethoscope:before { + content: "\f0f1"; } + +.fa-sticker-mule:before { + content: "\f3f7"; } + +.fa-sticky-note:before { + content: "\f249"; } + +.fa-stop:before { + content: "\f04d"; } + +.fa-stop-circle:before { + content: "\f28d"; } + +.fa-stopwatch:before { + content: "\f2f2"; } + +.fa-store:before { + content: "\f54e"; } + +.fa-store-alt:before { + content: "\f54f"; } + +.fa-strava:before { + content: "\f428"; } + +.fa-stream:before { + content: "\f550"; } + +.fa-street-view:before { + content: "\f21d"; } + +.fa-strikethrough:before { + content: "\f0cc"; } + +.fa-stripe:before { + content: "\f429"; } + +.fa-stripe-s:before { + content: "\f42a"; } + +.fa-stroopwafel:before { + content: "\f551"; } + +.fa-studiovinari:before { + content: "\f3f8"; } + +.fa-stumbleupon:before { + content: "\f1a4"; } + +.fa-stumbleupon-circle:before { + content: "\f1a3"; } + +.fa-subscript:before { + content: "\f12c"; } + +.fa-subway:before { + content: "\f239"; } + +.fa-suitcase:before { + content: "\f0f2"; } + +.fa-suitcase-rolling:before { + content: "\f5c1"; } + +.fa-sun:before { + content: "\f185"; } + +.fa-superpowers:before { + content: "\f2dd"; } + +.fa-superscript:before { + content: "\f12b"; } + +.fa-supple:before { + content: "\f3f9"; } + +.fa-surprise:before { + content: "\f5c2"; } + +.fa-suse:before { + content: "\f7d6"; } + +.fa-swatchbook:before { + content: "\f5c3"; } + +.fa-swift:before { + content: "\f8e1"; } + +.fa-swimmer:before { + content: "\f5c4"; } + +.fa-swimming-pool:before { + content: "\f5c5"; } + +.fa-symfony:before { + content: "\f83d"; } + +.fa-synagogue:before { + content: "\f69b"; } + +.fa-sync:before { + content: "\f021"; } + +.fa-sync-alt:before { + content: "\f2f1"; } + +.fa-syringe:before { + content: "\f48e"; } + +.fa-table:before { + content: "\f0ce"; } + +.fa-table-tennis:before { + content: "\f45d"; } + +.fa-tablet:before { + content: "\f10a"; } + +.fa-tablet-alt:before { + content: "\f3fa"; } + +.fa-tablets:before { + content: "\f490"; } + +.fa-tachometer-alt:before { + content: "\f3fd"; } + +.fa-tag:before { + content: "\f02b"; } + +.fa-tags:before { + content: "\f02c"; } + +.fa-tape:before { + content: "\f4db"; } + +.fa-tasks:before { + content: "\f0ae"; } + +.fa-taxi:before { + content: "\f1ba"; } + +.fa-teamspeak:before { + content: "\f4f9"; } + +.fa-teeth:before { + content: "\f62e"; } + +.fa-teeth-open:before { + content: "\f62f"; } + +.fa-telegram:before { + content: "\f2c6"; } + +.fa-telegram-plane:before { + content: "\f3fe"; } + +.fa-temperature-high:before { + content: "\f769"; } + +.fa-temperature-low:before { + content: "\f76b"; } + +.fa-tencent-weibo:before { + content: "\f1d5"; } + +.fa-tenge:before { + content: "\f7d7"; } + +.fa-terminal:before { + content: "\f120"; } + +.fa-text-height:before { + content: "\f034"; } + +.fa-text-width:before { + content: "\f035"; } + +.fa-th:before { + content: "\f00a"; } + +.fa-th-large:before { + content: "\f009"; } + +.fa-th-list:before { + content: "\f00b"; } + +.fa-the-red-yeti:before { + content: "\f69d"; } + +.fa-theater-masks:before { + content: "\f630"; } + +.fa-themeco:before { + content: "\f5c6"; } + +.fa-themeisle:before { + content: "\f2b2"; } + +.fa-thermometer:before { + content: "\f491"; } + +.fa-thermometer-empty:before { + content: "\f2cb"; } + +.fa-thermometer-full:before { + content: "\f2c7"; } + +.fa-thermometer-half:before { + content: "\f2c9"; } + +.fa-thermometer-quarter:before { + content: "\f2ca"; } + +.fa-thermometer-three-quarters:before { + content: "\f2c8"; } + +.fa-think-peaks:before { + content: "\f731"; } + +.fa-thumbs-down:before { + content: "\f165"; } + +.fa-thumbs-up:before { + content: "\f164"; } + +.fa-thumbtack:before { + content: "\f08d"; } + +.fa-ticket-alt:before { + content: "\f3ff"; } + +.fa-times:before { + content: "\f00d"; } + +.fa-times-circle:before { + content: "\f057"; } + +.fa-tint:before { + content: "\f043"; } + +.fa-tint-slash:before { + content: "\f5c7"; } + +.fa-tired:before { + content: "\f5c8"; } + +.fa-toggle-off:before { + content: "\f204"; } + +.fa-toggle-on:before { + content: "\f205"; } + +.fa-toilet:before { + content: "\f7d8"; } + +.fa-toilet-paper:before { + content: "\f71e"; } + +.fa-toolbox:before { + content: "\f552"; } + +.fa-tools:before { + content: "\f7d9"; } + +.fa-tooth:before { + content: "\f5c9"; } + +.fa-torah:before { + content: "\f6a0"; } + +.fa-torii-gate:before { + content: "\f6a1"; } + +.fa-tractor:before { + content: "\f722"; } + +.fa-trade-federation:before { + content: "\f513"; } + +.fa-trademark:before { + content: "\f25c"; } + +.fa-traffic-light:before { + content: "\f637"; } + +.fa-trailer:before { + content: "\f941"; } + +.fa-train:before { + content: "\f238"; } + +.fa-tram:before { + content: "\f7da"; } + +.fa-transgender:before { + content: "\f224"; } + +.fa-transgender-alt:before { + content: "\f225"; } + +.fa-trash:before { + content: "\f1f8"; } + +.fa-trash-alt:before { + content: "\f2ed"; } + +.fa-trash-restore:before { + content: "\f829"; } + +.fa-trash-restore-alt:before { + content: "\f82a"; } + +.fa-tree:before { + content: "\f1bb"; } + +.fa-trello:before { + content: "\f181"; } + +.fa-tripadvisor:before { + content: "\f262"; } + +.fa-trophy:before { + content: "\f091"; } + +.fa-truck:before { + content: "\f0d1"; } + +.fa-truck-loading:before { + content: "\f4de"; } + +.fa-truck-monster:before { + content: "\f63b"; } + +.fa-truck-moving:before { + content: "\f4df"; } + +.fa-truck-pickup:before { + content: "\f63c"; } + +.fa-tshirt:before { + content: "\f553"; } + +.fa-tty:before { + content: "\f1e4"; } + +.fa-tumblr:before { + content: "\f173"; } + +.fa-tumblr-square:before { + content: "\f174"; } + +.fa-tv:before { + content: "\f26c"; } + +.fa-twitch:before { + content: "\f1e8"; } + +.fa-twitter:before { + content: "\f099"; } + +.fa-twitter-square:before { + content: "\f081"; } + +.fa-typo3:before { + content: "\f42b"; } + +.fa-uber:before { + content: "\f402"; } + +.fa-ubuntu:before { + content: "\f7df"; } + +.fa-uikit:before { + content: "\f403"; } + +.fa-umbraco:before { + content: "\f8e8"; } + +.fa-umbrella:before { + content: "\f0e9"; } + +.fa-umbrella-beach:before { + content: "\f5ca"; } + +.fa-underline:before { + content: "\f0cd"; } + +.fa-undo:before { + content: "\f0e2"; } + +.fa-undo-alt:before { + content: "\f2ea"; } + +.fa-uniregistry:before { + content: "\f404"; } + +.fa-unity:before { + content: "\f949"; } + +.fa-universal-access:before { + content: "\f29a"; } + +.fa-university:before { + content: "\f19c"; } + +.fa-unlink:before { + content: "\f127"; } + +.fa-unlock:before { + content: "\f09c"; } + +.fa-unlock-alt:before { + content: "\f13e"; } + +.fa-untappd:before { + content: "\f405"; } + +.fa-upload:before { + content: "\f093"; } + +.fa-ups:before { + content: "\f7e0"; } + +.fa-usb:before { + content: "\f287"; } + +.fa-user:before { + content: "\f007"; } + +.fa-user-alt:before { + content: "\f406"; } + +.fa-user-alt-slash:before { + content: "\f4fa"; } + +.fa-user-astronaut:before { + content: "\f4fb"; } + +.fa-user-check:before { + content: "\f4fc"; } + +.fa-user-circle:before { + content: "\f2bd"; } + +.fa-user-clock:before { + content: "\f4fd"; } + +.fa-user-cog:before { + content: "\f4fe"; } + +.fa-user-edit:before { + content: "\f4ff"; } + +.fa-user-friends:before { + content: "\f500"; } + +.fa-user-graduate:before { + content: "\f501"; } + +.fa-user-injured:before { + content: "\f728"; } + +.fa-user-lock:before { + content: "\f502"; } + +.fa-user-md:before { + content: "\f0f0"; } + +.fa-user-minus:before { + content: "\f503"; } + +.fa-user-ninja:before { + content: "\f504"; } + +.fa-user-nurse:before { + content: "\f82f"; } + +.fa-user-plus:before { + content: "\f234"; } + +.fa-user-secret:before { + content: "\f21b"; } + +.fa-user-shield:before { + content: "\f505"; } + +.fa-user-slash:before { + content: "\f506"; } + +.fa-user-tag:before { + content: "\f507"; } + +.fa-user-tie:before { + content: "\f508"; } + +.fa-user-times:before { + content: "\f235"; } + +.fa-users:before { + content: "\f0c0"; } + +.fa-users-cog:before { + content: "\f509"; } + +.fa-usps:before { + content: "\f7e1"; } + +.fa-ussunnah:before { + content: "\f407"; } + +.fa-utensil-spoon:before { + content: "\f2e5"; } + +.fa-utensils:before { + content: "\f2e7"; } + +.fa-vaadin:before { + content: "\f408"; } + +.fa-vector-square:before { + content: "\f5cb"; } + +.fa-venus:before { + content: "\f221"; } + +.fa-venus-double:before { + content: "\f226"; } + +.fa-venus-mars:before { + content: "\f228"; } + +.fa-viacoin:before { + content: "\f237"; } + +.fa-viadeo:before { + content: "\f2a9"; } + +.fa-viadeo-square:before { + content: "\f2aa"; } + +.fa-vial:before { + content: "\f492"; } + +.fa-vials:before { + content: "\f493"; } + +.fa-viber:before { + content: "\f409"; } + +.fa-video:before { + content: "\f03d"; } + +.fa-video-slash:before { + content: "\f4e2"; } + +.fa-vihara:before { + content: "\f6a7"; } + +.fa-vimeo:before { + content: "\f40a"; } + +.fa-vimeo-square:before { + content: "\f194"; } + +.fa-vimeo-v:before { + content: "\f27d"; } + +.fa-vine:before { + content: "\f1ca"; } + +.fa-vk:before { + content: "\f189"; } + +.fa-vnv:before { + content: "\f40b"; } + +.fa-voicemail:before { + content: "\f897"; } + +.fa-volleyball-ball:before { + content: "\f45f"; } + +.fa-volume-down:before { + content: "\f027"; } + +.fa-volume-mute:before { + content: "\f6a9"; } + +.fa-volume-off:before { + content: "\f026"; } + +.fa-volume-up:before { + content: "\f028"; } + +.fa-vote-yea:before { + content: "\f772"; } + +.fa-vr-cardboard:before { + content: "\f729"; } + +.fa-vuejs:before { + content: "\f41f"; } + +.fa-walking:before { + content: "\f554"; } + +.fa-wallet:before { + content: "\f555"; } + +.fa-warehouse:before { + content: "\f494"; } + +.fa-water:before { + content: "\f773"; } + +.fa-wave-square:before { + content: "\f83e"; } + +.fa-waze:before { + content: "\f83f"; } + +.fa-weebly:before { + content: "\f5cc"; } + +.fa-weibo:before { + content: "\f18a"; } + +.fa-weight:before { + content: "\f496"; } + +.fa-weight-hanging:before { + content: "\f5cd"; } + +.fa-weixin:before { + content: "\f1d7"; } + +.fa-whatsapp:before { + content: "\f232"; } + +.fa-whatsapp-square:before { + content: "\f40c"; } + +.fa-wheelchair:before { + content: "\f193"; } + +.fa-whmcs:before { + content: "\f40d"; } + +.fa-wifi:before { + content: "\f1eb"; } + +.fa-wikipedia-w:before { + content: "\f266"; } + +.fa-wind:before { + content: "\f72e"; } + +.fa-window-close:before { + content: "\f410"; } + +.fa-window-maximize:before { + content: "\f2d0"; } + +.fa-window-minimize:before { + content: "\f2d1"; } + +.fa-window-restore:before { + content: "\f2d2"; } + +.fa-windows:before { + content: "\f17a"; } + +.fa-wine-bottle:before { + content: "\f72f"; } + +.fa-wine-glass:before { + content: "\f4e3"; } + +.fa-wine-glass-alt:before { + content: "\f5ce"; } + +.fa-wix:before { + content: "\f5cf"; } + +.fa-wizards-of-the-coast:before { + content: "\f730"; } + +.fa-wolf-pack-battalion:before { + content: "\f514"; } + +.fa-won-sign:before { + content: "\f159"; } + +.fa-wordpress:before { + content: "\f19a"; } + +.fa-wordpress-simple:before { + content: "\f411"; } + +.fa-wpbeginner:before { + content: "\f297"; } + +.fa-wpexplorer:before { + content: "\f2de"; } + +.fa-wpforms:before { + content: "\f298"; } + +.fa-wpressr:before { + content: "\f3e4"; } + +.fa-wrench:before { + content: "\f0ad"; } + +.fa-x-ray:before { + content: "\f497"; } + +.fa-xbox:before { + content: "\f412"; } + +.fa-xing:before { + content: "\f168"; } + +.fa-xing-square:before { + content: "\f169"; } + +.fa-y-combinator:before { + content: "\f23b"; } + +.fa-yahoo:before { + content: "\f19e"; } + +.fa-yammer:before { + content: "\f840"; } + +.fa-yandex:before { + content: "\f413"; } + +.fa-yandex-international:before { + content: "\f414"; } + +.fa-yarn:before { + content: "\f7e3"; } + +.fa-yelp:before { + content: "\f1e9"; } + +.fa-yen-sign:before { + content: "\f157"; } + +.fa-yin-yang:before { + content: "\f6ad"; } + +.fa-yoast:before { + content: "\f2b1"; } + +.fa-youtube:before { + content: "\f167"; } + +.fa-youtube-square:before { + content: "\f431"; } + +.fa-zhihu:before { + content: "\f63f"; } + +.sr-only { + border: 0; + clip: rect(0, 0, 0, 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; } + +.sr-only-focusable:active, .sr-only-focusable:focus { + clip: auto; + height: auto; + margin: 0; + overflow: visible; + position: static; + width: auto; } +@font-face { + font-family: 'Font Awesome 5 Brands'; + font-style: normal; + font-weight: 400; + font-display: auto; + src: url("../webfonts/fa-brands-400.eot"); + src: url("../webfonts/fa-brands-400.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.woff") format("woff"), url("../webfonts/fa-brands-400.ttf") format("truetype"), url("../webfonts/fa-brands-400.svg#fontawesome") format("svg"); } + +.fab { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } +@font-face { + font-family: 'Font Awesome 5 Free'; + font-style: normal; + font-weight: 400; + font-display: auto; + src: url("../webfonts/fa-regular-400.eot"); + src: url("../webfonts/fa-regular-400.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.woff") format("woff"), url("../webfonts/fa-regular-400.ttf") format("truetype"), url("../webfonts/fa-regular-400.svg#fontawesome") format("svg"); } + +.far { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } +@font-face { + font-family: 'Font Awesome 5 Free'; + font-style: normal; + font-weight: 900; + font-display: auto; + src: url("../webfonts/fa-solid-900.eot"); + src: url("../webfonts/fa-solid-900.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.woff") format("woff"), url("../webfonts/fa-solid-900.ttf") format("truetype"), url("../webfonts/fa-solid-900.svg#fontawesome") format("svg"); } + +.fa, +.fas { + font-family: 'Font Awesome 5 Free'; + font-weight: 900; } diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/all.min.css b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/all.min.css new file mode 100755 index 0000000..d16a4d5 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/all.min.css @@ -0,0 +1,5 @@ +/*! + * Font Awesome Free 5.12.1 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +.fa,.fab,.fad,.fal,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:.08em solid #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fab.fa-pull-left,.fal.fa-pull-left,.far.fa-pull-left,.fas.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fab.fa-pull-right,.fal.fa-pull-right,.far.fa-pull-right,.fas.fa-pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-webkit-transform:scaleY(-1);transform:scaleY(-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical,.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-webkit-transform:scale(-1);transform:scale(-1)}:root .fa-flip-both,:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{-webkit-filter:none;filter:none}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-500px:before{content:"\f26e"}.fa-accessible-icon:before{content:"\f368"}.fa-accusoft:before{content:"\f369"}.fa-acquisitions-incorporated:before{content:"\f6af"}.fa-ad:before{content:"\f641"}.fa-address-book:before{content:"\f2b9"}.fa-address-card:before{content:"\f2bb"}.fa-adjust:before{content:"\f042"}.fa-adn:before{content:"\f170"}.fa-adobe:before{content:"\f778"}.fa-adversal:before{content:"\f36a"}.fa-affiliatetheme:before{content:"\f36b"}.fa-air-freshener:before{content:"\f5d0"}.fa-airbnb:before{content:"\f834"}.fa-algolia:before{content:"\f36c"}.fa-align-center:before{content:"\f037"}.fa-align-justify:before{content:"\f039"}.fa-align-left:before{content:"\f036"}.fa-align-right:before{content:"\f038"}.fa-alipay:before{content:"\f642"}.fa-allergies:before{content:"\f461"}.fa-amazon:before{content:"\f270"}.fa-amazon-pay:before{content:"\f42c"}.fa-ambulance:before{content:"\f0f9"}.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-amilia:before{content:"\f36d"}.fa-anchor:before{content:"\f13d"}.fa-android:before{content:"\f17b"}.fa-angellist:before{content:"\f209"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-down:before{content:"\f107"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angry:before{content:"\f556"}.fa-angrycreative:before{content:"\f36e"}.fa-angular:before{content:"\f420"}.fa-ankh:before{content:"\f644"}.fa-app-store:before{content:"\f36f"}.fa-app-store-ios:before{content:"\f370"}.fa-apper:before{content:"\f371"}.fa-apple:before{content:"\f179"}.fa-apple-alt:before{content:"\f5d1"}.fa-apple-pay:before{content:"\f415"}.fa-archive:before{content:"\f187"}.fa-archway:before{content:"\f557"}.fa-arrow-alt-circle-down:before{content:"\f358"}.fa-arrow-alt-circle-left:before{content:"\f359"}.fa-arrow-alt-circle-right:before{content:"\f35a"}.fa-arrow-alt-circle-up:before{content:"\f35b"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-down:before{content:"\f063"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrows-alt:before{content:"\f0b2"}.fa-arrows-alt-h:before{content:"\f337"}.fa-arrows-alt-v:before{content:"\f338"}.fa-artstation:before{content:"\f77a"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asterisk:before{content:"\f069"}.fa-asymmetrik:before{content:"\f372"}.fa-at:before{content:"\f1fa"}.fa-atlas:before{content:"\f558"}.fa-atlassian:before{content:"\f77b"}.fa-atom:before{content:"\f5d2"}.fa-audible:before{content:"\f373"}.fa-audio-description:before{content:"\f29e"}.fa-autoprefixer:before{content:"\f41c"}.fa-avianex:before{content:"\f374"}.fa-aviato:before{content:"\f421"}.fa-award:before{content:"\f559"}.fa-aws:before{content:"\f375"}.fa-baby:before{content:"\f77c"}.fa-baby-carriage:before{content:"\f77d"}.fa-backspace:before{content:"\f55a"}.fa-backward:before{content:"\f04a"}.fa-bacon:before{content:"\f7e5"}.fa-bahai:before{content:"\f666"}.fa-balance-scale:before{content:"\f24e"}.fa-balance-scale-left:before{content:"\f515"}.fa-balance-scale-right:before{content:"\f516"}.fa-ban:before{content:"\f05e"}.fa-band-aid:before{content:"\f462"}.fa-bandcamp:before{content:"\f2d5"}.fa-barcode:before{content:"\f02a"}.fa-bars:before{content:"\f0c9"}.fa-baseball-ball:before{content:"\f433"}.fa-basketball-ball:before{content:"\f434"}.fa-bath:before{content:"\f2cd"}.fa-battery-empty:before{content:"\f244"}.fa-battery-full:before{content:"\f240"}.fa-battery-half:before{content:"\f242"}.fa-battery-quarter:before{content:"\f243"}.fa-battery-three-quarters:before{content:"\f241"}.fa-battle-net:before{content:"\f835"}.fa-bed:before{content:"\f236"}.fa-beer:before{content:"\f0fc"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-bell:before{content:"\f0f3"}.fa-bell-slash:before{content:"\f1f6"}.fa-bezier-curve:before{content:"\f55b"}.fa-bible:before{content:"\f647"}.fa-bicycle:before{content:"\f206"}.fa-biking:before{content:"\f84a"}.fa-bimobject:before{content:"\f378"}.fa-binoculars:before{content:"\f1e5"}.fa-biohazard:before{content:"\f780"}.fa-birthday-cake:before{content:"\f1fd"}.fa-bitbucket:before{content:"\f171"}.fa-bitcoin:before{content:"\f379"}.fa-bity:before{content:"\f37a"}.fa-black-tie:before{content:"\f27e"}.fa-blackberry:before{content:"\f37b"}.fa-blender:before{content:"\f517"}.fa-blender-phone:before{content:"\f6b6"}.fa-blind:before{content:"\f29d"}.fa-blog:before{content:"\f781"}.fa-blogger:before{content:"\f37c"}.fa-blogger-b:before{content:"\f37d"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-bold:before{content:"\f032"}.fa-bolt:before{content:"\f0e7"}.fa-bomb:before{content:"\f1e2"}.fa-bone:before{content:"\f5d7"}.fa-bong:before{content:"\f55c"}.fa-book:before{content:"\f02d"}.fa-book-dead:before{content:"\f6b7"}.fa-book-medical:before{content:"\f7e6"}.fa-book-open:before{content:"\f518"}.fa-book-reader:before{content:"\f5da"}.fa-bookmark:before{content:"\f02e"}.fa-bootstrap:before{content:"\f836"}.fa-border-all:before{content:"\f84c"}.fa-border-none:before{content:"\f850"}.fa-border-style:before{content:"\f853"}.fa-bowling-ball:before{content:"\f436"}.fa-box:before{content:"\f466"}.fa-box-open:before{content:"\f49e"}.fa-boxes:before{content:"\f468"}.fa-braille:before{content:"\f2a1"}.fa-brain:before{content:"\f5dc"}.fa-bread-slice:before{content:"\f7ec"}.fa-briefcase:before{content:"\f0b1"}.fa-briefcase-medical:before{content:"\f469"}.fa-broadcast-tower:before{content:"\f519"}.fa-broom:before{content:"\f51a"}.fa-brush:before{content:"\f55d"}.fa-btc:before{content:"\f15a"}.fa-buffer:before{content:"\f837"}.fa-bug:before{content:"\f188"}.fa-building:before{content:"\f1ad"}.fa-bullhorn:before{content:"\f0a1"}.fa-bullseye:before{content:"\f140"}.fa-burn:before{content:"\f46a"}.fa-buromobelexperte:before{content:"\f37f"}.fa-bus:before{content:"\f207"}.fa-bus-alt:before{content:"\f55e"}.fa-business-time:before{content:"\f64a"}.fa-buy-n-large:before{content:"\f8a6"}.fa-buysellads:before{content:"\f20d"}.fa-calculator:before{content:"\f1ec"}.fa-calendar:before{content:"\f133"}.fa-calendar-alt:before{content:"\f073"}.fa-calendar-check:before{content:"\f274"}.fa-calendar-day:before{content:"\f783"}.fa-calendar-minus:before{content:"\f272"}.fa-calendar-plus:before{content:"\f271"}.fa-calendar-times:before{content:"\f273"}.fa-calendar-week:before{content:"\f784"}.fa-camera:before{content:"\f030"}.fa-camera-retro:before{content:"\f083"}.fa-campground:before{content:"\f6bb"}.fa-canadian-maple-leaf:before{content:"\f785"}.fa-candy-cane:before{content:"\f786"}.fa-cannabis:before{content:"\f55f"}.fa-capsules:before{content:"\f46b"}.fa-car:before{content:"\f1b9"}.fa-car-alt:before{content:"\f5de"}.fa-car-battery:before{content:"\f5df"}.fa-car-crash:before{content:"\f5e1"}.fa-car-side:before{content:"\f5e4"}.fa-caravan:before{content:"\f8ff"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-caret-square-down:before{content:"\f150"}.fa-caret-square-left:before{content:"\f191"}.fa-caret-square-right:before{content:"\f152"}.fa-caret-square-up:before{content:"\f151"}.fa-caret-up:before{content:"\f0d8"}.fa-carrot:before{content:"\f787"}.fa-cart-arrow-down:before{content:"\f218"}.fa-cart-plus:before{content:"\f217"}.fa-cash-register:before{content:"\f788"}.fa-cat:before{content:"\f6be"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-apple-pay:before{content:"\f416"}.fa-cc-diners-club:before{content:"\f24c"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-cc-visa:before{content:"\f1f0"}.fa-centercode:before{content:"\f380"}.fa-centos:before{content:"\f789"}.fa-certificate:before{content:"\f0a3"}.fa-chair:before{content:"\f6c0"}.fa-chalkboard:before{content:"\f51b"}.fa-chalkboard-teacher:before{content:"\f51c"}.fa-charging-station:before{content:"\f5e7"}.fa-chart-area:before{content:"\f1fe"}.fa-chart-bar:before{content:"\f080"}.fa-chart-line:before{content:"\f201"}.fa-chart-pie:before{content:"\f200"}.fa-check:before{content:"\f00c"}.fa-check-circle:before{content:"\f058"}.fa-check-double:before{content:"\f560"}.fa-check-square:before{content:"\f14a"}.fa-cheese:before{content:"\f7ef"}.fa-chess:before{content:"\f439"}.fa-chess-bishop:before{content:"\f43a"}.fa-chess-board:before{content:"\f43c"}.fa-chess-king:before{content:"\f43f"}.fa-chess-knight:before{content:"\f441"}.fa-chess-pawn:before{content:"\f443"}.fa-chess-queen:before{content:"\f445"}.fa-chess-rook:before{content:"\f447"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-down:before{content:"\f078"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-chevron-up:before{content:"\f077"}.fa-child:before{content:"\f1ae"}.fa-chrome:before{content:"\f268"}.fa-chromecast:before{content:"\f838"}.fa-church:before{content:"\f51d"}.fa-circle:before{content:"\f111"}.fa-circle-notch:before{content:"\f1ce"}.fa-city:before{content:"\f64f"}.fa-clinic-medical:before{content:"\f7f2"}.fa-clipboard:before{content:"\f328"}.fa-clipboard-check:before{content:"\f46c"}.fa-clipboard-list:before{content:"\f46d"}.fa-clock:before{content:"\f017"}.fa-clone:before{content:"\f24d"}.fa-closed-captioning:before{content:"\f20a"}.fa-cloud:before{content:"\f0c2"}.fa-cloud-download-alt:before{content:"\f381"}.fa-cloud-meatball:before{content:"\f73b"}.fa-cloud-moon:before{content:"\f6c3"}.fa-cloud-moon-rain:before{content:"\f73c"}.fa-cloud-rain:before{content:"\f73d"}.fa-cloud-showers-heavy:before{content:"\f740"}.fa-cloud-sun:before{content:"\f6c4"}.fa-cloud-sun-rain:before{content:"\f743"}.fa-cloud-upload-alt:before{content:"\f382"}.fa-cloudscale:before{content:"\f383"}.fa-cloudsmith:before{content:"\f384"}.fa-cloudversify:before{content:"\f385"}.fa-cocktail:before{content:"\f561"}.fa-code:before{content:"\f121"}.fa-code-branch:before{content:"\f126"}.fa-codepen:before{content:"\f1cb"}.fa-codiepie:before{content:"\f284"}.fa-coffee:before{content:"\f0f4"}.fa-cog:before{content:"\f013"}.fa-cogs:before{content:"\f085"}.fa-coins:before{content:"\f51e"}.fa-columns:before{content:"\f0db"}.fa-comment:before{content:"\f075"}.fa-comment-alt:before{content:"\f27a"}.fa-comment-dollar:before{content:"\f651"}.fa-comment-dots:before{content:"\f4ad"}.fa-comment-medical:before{content:"\f7f5"}.fa-comment-slash:before{content:"\f4b3"}.fa-comments:before{content:"\f086"}.fa-comments-dollar:before{content:"\f653"}.fa-compact-disc:before{content:"\f51f"}.fa-compass:before{content:"\f14e"}.fa-compress:before{content:"\f066"}.fa-compress-alt:before{content:"\f422"}.fa-compress-arrows-alt:before{content:"\f78c"}.fa-concierge-bell:before{content:"\f562"}.fa-confluence:before{content:"\f78d"}.fa-connectdevelop:before{content:"\f20e"}.fa-contao:before{content:"\f26d"}.fa-cookie:before{content:"\f563"}.fa-cookie-bite:before{content:"\f564"}.fa-copy:before{content:"\f0c5"}.fa-copyright:before{content:"\f1f9"}.fa-cotton-bureau:before{content:"\f89e"}.fa-couch:before{content:"\f4b8"}.fa-cpanel:before{content:"\f388"}.fa-creative-commons:before{content:"\f25e"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-creative-commons-nc-eu:before{content:"\f4e9"}.fa-creative-commons-nc-jp:before{content:"\f4ea"}.fa-creative-commons-nd:before{content:"\f4eb"}.fa-creative-commons-pd:before{content:"\f4ec"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-creative-commons-remix:before{content:"\f4ee"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-creative-commons-sampling-plus:before{content:"\f4f1"}.fa-creative-commons-share:before{content:"\f4f2"}.fa-creative-commons-zero:before{content:"\f4f3"}.fa-credit-card:before{content:"\f09d"}.fa-critical-role:before{content:"\f6c9"}.fa-crop:before{content:"\f125"}.fa-crop-alt:before{content:"\f565"}.fa-cross:before{content:"\f654"}.fa-crosshairs:before{content:"\f05b"}.fa-crow:before{content:"\f520"}.fa-crown:before{content:"\f521"}.fa-crutch:before{content:"\f7f7"}.fa-css3:before{content:"\f13c"}.fa-css3-alt:before{content:"\f38b"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-cut:before{content:"\f0c4"}.fa-cuttlefish:before{content:"\f38c"}.fa-d-and-d:before{content:"\f38d"}.fa-d-and-d-beyond:before{content:"\f6ca"}.fa-dailymotion:before{content:"\f952"}.fa-dashcube:before{content:"\f210"}.fa-database:before{content:"\f1c0"}.fa-deaf:before{content:"\f2a4"}.fa-delicious:before{content:"\f1a5"}.fa-democrat:before{content:"\f747"}.fa-deploydog:before{content:"\f38e"}.fa-deskpro:before{content:"\f38f"}.fa-desktop:before{content:"\f108"}.fa-dev:before{content:"\f6cc"}.fa-deviantart:before{content:"\f1bd"}.fa-dharmachakra:before{content:"\f655"}.fa-dhl:before{content:"\f790"}.fa-diagnoses:before{content:"\f470"}.fa-diaspora:before{content:"\f791"}.fa-dice:before{content:"\f522"}.fa-dice-d20:before{content:"\f6cf"}.fa-dice-d6:before{content:"\f6d1"}.fa-dice-five:before{content:"\f523"}.fa-dice-four:before{content:"\f524"}.fa-dice-one:before{content:"\f525"}.fa-dice-six:before{content:"\f526"}.fa-dice-three:before{content:"\f527"}.fa-dice-two:before{content:"\f528"}.fa-digg:before{content:"\f1a6"}.fa-digital-ocean:before{content:"\f391"}.fa-digital-tachograph:before{content:"\f566"}.fa-directions:before{content:"\f5eb"}.fa-discord:before{content:"\f392"}.fa-discourse:before{content:"\f393"}.fa-divide:before{content:"\f529"}.fa-dizzy:before{content:"\f567"}.fa-dna:before{content:"\f471"}.fa-dochub:before{content:"\f394"}.fa-docker:before{content:"\f395"}.fa-dog:before{content:"\f6d3"}.fa-dollar-sign:before{content:"\f155"}.fa-dolly:before{content:"\f472"}.fa-dolly-flatbed:before{content:"\f474"}.fa-donate:before{content:"\f4b9"}.fa-door-closed:before{content:"\f52a"}.fa-door-open:before{content:"\f52b"}.fa-dot-circle:before{content:"\f192"}.fa-dove:before{content:"\f4ba"}.fa-download:before{content:"\f019"}.fa-draft2digital:before{content:"\f396"}.fa-drafting-compass:before{content:"\f568"}.fa-dragon:before{content:"\f6d5"}.fa-draw-polygon:before{content:"\f5ee"}.fa-dribbble:before{content:"\f17d"}.fa-dribbble-square:before{content:"\f397"}.fa-dropbox:before{content:"\f16b"}.fa-drum:before{content:"\f569"}.fa-drum-steelpan:before{content:"\f56a"}.fa-drumstick-bite:before{content:"\f6d7"}.fa-drupal:before{content:"\f1a9"}.fa-dumbbell:before{content:"\f44b"}.fa-dumpster:before{content:"\f793"}.fa-dumpster-fire:before{content:"\f794"}.fa-dungeon:before{content:"\f6d9"}.fa-dyalog:before{content:"\f399"}.fa-earlybirds:before{content:"\f39a"}.fa-ebay:before{content:"\f4f4"}.fa-edge:before{content:"\f282"}.fa-edit:before{content:"\f044"}.fa-egg:before{content:"\f7fb"}.fa-eject:before{content:"\f052"}.fa-elementor:before{content:"\f430"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-ello:before{content:"\f5f1"}.fa-ember:before{content:"\f423"}.fa-empire:before{content:"\f1d1"}.fa-envelope:before{content:"\f0e0"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-text:before{content:"\f658"}.fa-envelope-square:before{content:"\f199"}.fa-envira:before{content:"\f299"}.fa-equals:before{content:"\f52c"}.fa-eraser:before{content:"\f12d"}.fa-erlang:before{content:"\f39d"}.fa-ethereum:before{content:"\f42e"}.fa-ethernet:before{content:"\f796"}.fa-etsy:before{content:"\f2d7"}.fa-euro-sign:before{content:"\f153"}.fa-evernote:before{content:"\f839"}.fa-exchange-alt:before{content:"\f362"}.fa-exclamation:before{content:"\f12a"}.fa-exclamation-circle:before{content:"\f06a"}.fa-exclamation-triangle:before{content:"\f071"}.fa-expand:before{content:"\f065"}.fa-expand-alt:before{content:"\f424"}.fa-expand-arrows-alt:before{content:"\f31e"}.fa-expeditedssl:before{content:"\f23e"}.fa-external-link-alt:before{content:"\f35d"}.fa-external-link-square-alt:before{content:"\f360"}.fa-eye:before{content:"\f06e"}.fa-eye-dropper:before{content:"\f1fb"}.fa-eye-slash:before{content:"\f070"}.fa-facebook:before{content:"\f09a"}.fa-facebook-f:before{content:"\f39e"}.fa-facebook-messenger:before{content:"\f39f"}.fa-facebook-square:before{content:"\f082"}.fa-fan:before{content:"\f863"}.fa-fantasy-flight-games:before{content:"\f6dc"}.fa-fast-backward:before{content:"\f049"}.fa-fast-forward:before{content:"\f050"}.fa-fax:before{content:"\f1ac"}.fa-feather:before{content:"\f52d"}.fa-feather-alt:before{content:"\f56b"}.fa-fedex:before{content:"\f797"}.fa-fedora:before{content:"\f798"}.fa-female:before{content:"\f182"}.fa-fighter-jet:before{content:"\f0fb"}.fa-figma:before{content:"\f799"}.fa-file:before{content:"\f15b"}.fa-file-alt:before{content:"\f15c"}.fa-file-archive:before{content:"\f1c6"}.fa-file-audio:before{content:"\f1c7"}.fa-file-code:before{content:"\f1c9"}.fa-file-contract:before{content:"\f56c"}.fa-file-csv:before{content:"\f6dd"}.fa-file-download:before{content:"\f56d"}.fa-file-excel:before{content:"\f1c3"}.fa-file-export:before{content:"\f56e"}.fa-file-image:before{content:"\f1c5"}.fa-file-import:before{content:"\f56f"}.fa-file-invoice:before{content:"\f570"}.fa-file-invoice-dollar:before{content:"\f571"}.fa-file-medical:before{content:"\f477"}.fa-file-medical-alt:before{content:"\f478"}.fa-file-pdf:before{content:"\f1c1"}.fa-file-powerpoint:before{content:"\f1c4"}.fa-file-prescription:before{content:"\f572"}.fa-file-signature:before{content:"\f573"}.fa-file-upload:before{content:"\f574"}.fa-file-video:before{content:"\f1c8"}.fa-file-word:before{content:"\f1c2"}.fa-fill:before{content:"\f575"}.fa-fill-drip:before{content:"\f576"}.fa-film:before{content:"\f008"}.fa-filter:before{content:"\f0b0"}.fa-fingerprint:before{content:"\f577"}.fa-fire:before{content:"\f06d"}.fa-fire-alt:before{content:"\f7e4"}.fa-fire-extinguisher:before{content:"\f134"}.fa-firefox:before{content:"\f269"}.fa-firefox-browser:before{content:"\f907"}.fa-first-aid:before{content:"\f479"}.fa-first-order:before{content:"\f2b0"}.fa-first-order-alt:before{content:"\f50a"}.fa-firstdraft:before{content:"\f3a1"}.fa-fish:before{content:"\f578"}.fa-fist-raised:before{content:"\f6de"}.fa-flag:before{content:"\f024"}.fa-flag-checkered:before{content:"\f11e"}.fa-flag-usa:before{content:"\f74d"}.fa-flask:before{content:"\f0c3"}.fa-flickr:before{content:"\f16e"}.fa-flipboard:before{content:"\f44d"}.fa-flushed:before{content:"\f579"}.fa-fly:before{content:"\f417"}.fa-folder:before{content:"\f07b"}.fa-folder-minus:before{content:"\f65d"}.fa-folder-open:before{content:"\f07c"}.fa-folder-plus:before{content:"\f65e"}.fa-font:before{content:"\f031"}.fa-font-awesome:before{content:"\f2b4"}.fa-font-awesome-alt:before{content:"\f35c"}.fa-font-awesome-flag:before{content:"\f425"}.fa-font-awesome-logo-full:before{content:"\f4e6"}.fa-fonticons:before{content:"\f280"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-football-ball:before{content:"\f44e"}.fa-fort-awesome:before{content:"\f286"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-forumbee:before{content:"\f211"}.fa-forward:before{content:"\f04e"}.fa-foursquare:before{content:"\f180"}.fa-free-code-camp:before{content:"\f2c5"}.fa-freebsd:before{content:"\f3a4"}.fa-frog:before{content:"\f52e"}.fa-frown:before{content:"\f119"}.fa-frown-open:before{content:"\f57a"}.fa-fulcrum:before{content:"\f50b"}.fa-funnel-dollar:before{content:"\f662"}.fa-futbol:before{content:"\f1e3"}.fa-galactic-republic:before{content:"\f50c"}.fa-galactic-senate:before{content:"\f50d"}.fa-gamepad:before{content:"\f11b"}.fa-gas-pump:before{content:"\f52f"}.fa-gavel:before{content:"\f0e3"}.fa-gem:before{content:"\f3a5"}.fa-genderless:before{content:"\f22d"}.fa-get-pocket:before{content:"\f265"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-ghost:before{content:"\f6e2"}.fa-gift:before{content:"\f06b"}.fa-gifts:before{content:"\f79c"}.fa-git:before{content:"\f1d3"}.fa-git-alt:before{content:"\f841"}.fa-git-square:before{content:"\f1d2"}.fa-github:before{content:"\f09b"}.fa-github-alt:before{content:"\f113"}.fa-github-square:before{content:"\f092"}.fa-gitkraken:before{content:"\f3a6"}.fa-gitlab:before{content:"\f296"}.fa-gitter:before{content:"\f426"}.fa-glass-cheers:before{content:"\f79f"}.fa-glass-martini:before{content:"\f000"}.fa-glass-martini-alt:before{content:"\f57b"}.fa-glass-whiskey:before{content:"\f7a0"}.fa-glasses:before{content:"\f530"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-globe:before{content:"\f0ac"}.fa-globe-africa:before{content:"\f57c"}.fa-globe-americas:before{content:"\f57d"}.fa-globe-asia:before{content:"\f57e"}.fa-globe-europe:before{content:"\f7a2"}.fa-gofore:before{content:"\f3a7"}.fa-golf-ball:before{content:"\f450"}.fa-goodreads:before{content:"\f3a8"}.fa-goodreads-g:before{content:"\f3a9"}.fa-google:before{content:"\f1a0"}.fa-google-drive:before{content:"\f3aa"}.fa-google-play:before{content:"\f3ab"}.fa-google-plus:before{content:"\f2b3"}.fa-google-plus-g:before{content:"\f0d5"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-wallet:before{content:"\f1ee"}.fa-gopuram:before{content:"\f664"}.fa-graduation-cap:before{content:"\f19d"}.fa-gratipay:before{content:"\f184"}.fa-grav:before{content:"\f2d6"}.fa-greater-than:before{content:"\f531"}.fa-greater-than-equal:before{content:"\f532"}.fa-grimace:before{content:"\f57f"}.fa-grin:before{content:"\f580"}.fa-grin-alt:before{content:"\f581"}.fa-grin-beam:before{content:"\f582"}.fa-grin-beam-sweat:before{content:"\f583"}.fa-grin-hearts:before{content:"\f584"}.fa-grin-squint:before{content:"\f585"}.fa-grin-squint-tears:before{content:"\f586"}.fa-grin-stars:before{content:"\f587"}.fa-grin-tears:before{content:"\f588"}.fa-grin-tongue:before{content:"\f589"}.fa-grin-tongue-squint:before{content:"\f58a"}.fa-grin-tongue-wink:before{content:"\f58b"}.fa-grin-wink:before{content:"\f58c"}.fa-grip-horizontal:before{content:"\f58d"}.fa-grip-lines:before{content:"\f7a4"}.fa-grip-lines-vertical:before{content:"\f7a5"}.fa-grip-vertical:before{content:"\f58e"}.fa-gripfire:before{content:"\f3ac"}.fa-grunt:before{content:"\f3ad"}.fa-guitar:before{content:"\f7a6"}.fa-gulp:before{content:"\f3ae"}.fa-h-square:before{content:"\f0fd"}.fa-hacker-news:before{content:"\f1d4"}.fa-hacker-news-square:before{content:"\f3af"}.fa-hackerrank:before{content:"\f5f7"}.fa-hamburger:before{content:"\f805"}.fa-hammer:before{content:"\f6e3"}.fa-hamsa:before{content:"\f665"}.fa-hand-holding:before{content:"\f4bd"}.fa-hand-holding-heart:before{content:"\f4be"}.fa-hand-holding-usd:before{content:"\f4c0"}.fa-hand-lizard:before{content:"\f258"}.fa-hand-middle-finger:before{content:"\f806"}.fa-hand-paper:before{content:"\f256"}.fa-hand-peace:before{content:"\f25b"}.fa-hand-point-down:before{content:"\f0a7"}.fa-hand-point-left:before{content:"\f0a5"}.fa-hand-point-right:before{content:"\f0a4"}.fa-hand-point-up:before{content:"\f0a6"}.fa-hand-pointer:before{content:"\f25a"}.fa-hand-rock:before{content:"\f255"}.fa-hand-scissors:before{content:"\f257"}.fa-hand-spock:before{content:"\f259"}.fa-hands:before{content:"\f4c2"}.fa-hands-helping:before{content:"\f4c4"}.fa-handshake:before{content:"\f2b5"}.fa-hanukiah:before{content:"\f6e6"}.fa-hard-hat:before{content:"\f807"}.fa-hashtag:before{content:"\f292"}.fa-hat-cowboy:before{content:"\f8c0"}.fa-hat-cowboy-side:before{content:"\f8c1"}.fa-hat-wizard:before{content:"\f6e8"}.fa-hdd:before{content:"\f0a0"}.fa-heading:before{content:"\f1dc"}.fa-headphones:before{content:"\f025"}.fa-headphones-alt:before{content:"\f58f"}.fa-headset:before{content:"\f590"}.fa-heart:before{content:"\f004"}.fa-heart-broken:before{content:"\f7a9"}.fa-heartbeat:before{content:"\f21e"}.fa-helicopter:before{content:"\f533"}.fa-highlighter:before{content:"\f591"}.fa-hiking:before{content:"\f6ec"}.fa-hippo:before{content:"\f6ed"}.fa-hips:before{content:"\f452"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-history:before{content:"\f1da"}.fa-hockey-puck:before{content:"\f453"}.fa-holly-berry:before{content:"\f7aa"}.fa-home:before{content:"\f015"}.fa-hooli:before{content:"\f427"}.fa-hornbill:before{content:"\f592"}.fa-horse:before{content:"\f6f0"}.fa-horse-head:before{content:"\f7ab"}.fa-hospital:before{content:"\f0f8"}.fa-hospital-alt:before{content:"\f47d"}.fa-hospital-symbol:before{content:"\f47e"}.fa-hot-tub:before{content:"\f593"}.fa-hotdog:before{content:"\f80f"}.fa-hotel:before{content:"\f594"}.fa-hotjar:before{content:"\f3b1"}.fa-hourglass:before{content:"\f254"}.fa-hourglass-end:before{content:"\f253"}.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-start:before{content:"\f251"}.fa-house-damage:before{content:"\f6f1"}.fa-houzz:before{content:"\f27c"}.fa-hryvnia:before{content:"\f6f2"}.fa-html5:before{content:"\f13b"}.fa-hubspot:before{content:"\f3b2"}.fa-i-cursor:before{content:"\f246"}.fa-ice-cream:before{content:"\f810"}.fa-icicles:before{content:"\f7ad"}.fa-icons:before{content:"\f86d"}.fa-id-badge:before{content:"\f2c1"}.fa-id-card:before{content:"\f2c2"}.fa-id-card-alt:before{content:"\f47f"}.fa-ideal:before{content:"\f913"}.fa-igloo:before{content:"\f7ae"}.fa-image:before{content:"\f03e"}.fa-images:before{content:"\f302"}.fa-imdb:before{content:"\f2d8"}.fa-inbox:before{content:"\f01c"}.fa-indent:before{content:"\f03c"}.fa-industry:before{content:"\f275"}.fa-infinity:before{content:"\f534"}.fa-info:before{content:"\f129"}.fa-info-circle:before{content:"\f05a"}.fa-instagram:before{content:"\f16d"}.fa-instagram-square:before{content:"\f955"}.fa-intercom:before{content:"\f7af"}.fa-internet-explorer:before{content:"\f26b"}.fa-invision:before{content:"\f7b0"}.fa-ioxhost:before{content:"\f208"}.fa-italic:before{content:"\f033"}.fa-itch-io:before{content:"\f83a"}.fa-itunes:before{content:"\f3b4"}.fa-itunes-note:before{content:"\f3b5"}.fa-java:before{content:"\f4e4"}.fa-jedi:before{content:"\f669"}.fa-jedi-order:before{content:"\f50e"}.fa-jenkins:before{content:"\f3b6"}.fa-jira:before{content:"\f7b1"}.fa-joget:before{content:"\f3b7"}.fa-joint:before{content:"\f595"}.fa-joomla:before{content:"\f1aa"}.fa-journal-whills:before{content:"\f66a"}.fa-js:before{content:"\f3b8"}.fa-js-square:before{content:"\f3b9"}.fa-jsfiddle:before{content:"\f1cc"}.fa-kaaba:before{content:"\f66b"}.fa-kaggle:before{content:"\f5fa"}.fa-key:before{content:"\f084"}.fa-keybase:before{content:"\f4f5"}.fa-keyboard:before{content:"\f11c"}.fa-keycdn:before{content:"\f3ba"}.fa-khanda:before{content:"\f66d"}.fa-kickstarter:before{content:"\f3bb"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-kiss:before{content:"\f596"}.fa-kiss-beam:before{content:"\f597"}.fa-kiss-wink-heart:before{content:"\f598"}.fa-kiwi-bird:before{content:"\f535"}.fa-korvue:before{content:"\f42f"}.fa-landmark:before{content:"\f66f"}.fa-language:before{content:"\f1ab"}.fa-laptop:before{content:"\f109"}.fa-laptop-code:before{content:"\f5fc"}.fa-laptop-medical:before{content:"\f812"}.fa-laravel:before{content:"\f3bd"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-laugh:before{content:"\f599"}.fa-laugh-beam:before{content:"\f59a"}.fa-laugh-squint:before{content:"\f59b"}.fa-laugh-wink:before{content:"\f59c"}.fa-layer-group:before{content:"\f5fd"}.fa-leaf:before{content:"\f06c"}.fa-leanpub:before{content:"\f212"}.fa-lemon:before{content:"\f094"}.fa-less:before{content:"\f41d"}.fa-less-than:before{content:"\f536"}.fa-less-than-equal:before{content:"\f537"}.fa-level-down-alt:before{content:"\f3be"}.fa-level-up-alt:before{content:"\f3bf"}.fa-life-ring:before{content:"\f1cd"}.fa-lightbulb:before{content:"\f0eb"}.fa-line:before{content:"\f3c0"}.fa-link:before{content:"\f0c1"}.fa-linkedin:before{content:"\f08c"}.fa-linkedin-in:before{content:"\f0e1"}.fa-linode:before{content:"\f2b8"}.fa-linux:before{content:"\f17c"}.fa-lira-sign:before{content:"\f195"}.fa-list:before{content:"\f03a"}.fa-list-alt:before{content:"\f022"}.fa-list-ol:before{content:"\f0cb"}.fa-list-ul:before{content:"\f0ca"}.fa-location-arrow:before{content:"\f124"}.fa-lock:before{content:"\f023"}.fa-lock-open:before{content:"\f3c1"}.fa-long-arrow-alt-down:before{content:"\f309"}.fa-long-arrow-alt-left:before{content:"\f30a"}.fa-long-arrow-alt-right:before{content:"\f30b"}.fa-long-arrow-alt-up:before{content:"\f30c"}.fa-low-vision:before{content:"\f2a8"}.fa-luggage-cart:before{content:"\f59d"}.fa-lyft:before{content:"\f3c3"}.fa-magento:before{content:"\f3c4"}.fa-magic:before{content:"\f0d0"}.fa-magnet:before{content:"\f076"}.fa-mail-bulk:before{content:"\f674"}.fa-mailchimp:before{content:"\f59e"}.fa-male:before{content:"\f183"}.fa-mandalorian:before{content:"\f50f"}.fa-map:before{content:"\f279"}.fa-map-marked:before{content:"\f59f"}.fa-map-marked-alt:before{content:"\f5a0"}.fa-map-marker:before{content:"\f041"}.fa-map-marker-alt:before{content:"\f3c5"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-markdown:before{content:"\f60f"}.fa-marker:before{content:"\f5a1"}.fa-mars:before{content:"\f222"}.fa-mars-double:before{content:"\f227"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mask:before{content:"\f6fa"}.fa-mastodon:before{content:"\f4f6"}.fa-maxcdn:before{content:"\f136"}.fa-mdb:before{content:"\f8ca"}.fa-medal:before{content:"\f5a2"}.fa-medapps:before{content:"\f3c6"}.fa-medium:before{content:"\f23a"}.fa-medium-m:before{content:"\f3c7"}.fa-medkit:before{content:"\f0fa"}.fa-medrt:before{content:"\f3c8"}.fa-meetup:before{content:"\f2e0"}.fa-megaport:before{content:"\f5a3"}.fa-meh:before{content:"\f11a"}.fa-meh-blank:before{content:"\f5a4"}.fa-meh-rolling-eyes:before{content:"\f5a5"}.fa-memory:before{content:"\f538"}.fa-mendeley:before{content:"\f7b3"}.fa-menorah:before{content:"\f676"}.fa-mercury:before{content:"\f223"}.fa-meteor:before{content:"\f753"}.fa-microblog:before{content:"\f91a"}.fa-microchip:before{content:"\f2db"}.fa-microphone:before{content:"\f130"}.fa-microphone-alt:before{content:"\f3c9"}.fa-microphone-alt-slash:before{content:"\f539"}.fa-microphone-slash:before{content:"\f131"}.fa-microscope:before{content:"\f610"}.fa-microsoft:before{content:"\f3ca"}.fa-minus:before{content:"\f068"}.fa-minus-circle:before{content:"\f056"}.fa-minus-square:before{content:"\f146"}.fa-mitten:before{content:"\f7b5"}.fa-mix:before{content:"\f3cb"}.fa-mixcloud:before{content:"\f289"}.fa-mixer:before{content:"\f956"}.fa-mizuni:before{content:"\f3cc"}.fa-mobile:before{content:"\f10b"}.fa-mobile-alt:before{content:"\f3cd"}.fa-modx:before{content:"\f285"}.fa-monero:before{content:"\f3d0"}.fa-money-bill:before{content:"\f0d6"}.fa-money-bill-alt:before{content:"\f3d1"}.fa-money-bill-wave:before{content:"\f53a"}.fa-money-bill-wave-alt:before{content:"\f53b"}.fa-money-check:before{content:"\f53c"}.fa-money-check-alt:before{content:"\f53d"}.fa-monument:before{content:"\f5a6"}.fa-moon:before{content:"\f186"}.fa-mortar-pestle:before{content:"\f5a7"}.fa-mosque:before{content:"\f678"}.fa-motorcycle:before{content:"\f21c"}.fa-mountain:before{content:"\f6fc"}.fa-mouse:before{content:"\f8cc"}.fa-mouse-pointer:before{content:"\f245"}.fa-mug-hot:before{content:"\f7b6"}.fa-music:before{content:"\f001"}.fa-napster:before{content:"\f3d2"}.fa-neos:before{content:"\f612"}.fa-network-wired:before{content:"\f6ff"}.fa-neuter:before{content:"\f22c"}.fa-newspaper:before{content:"\f1ea"}.fa-nimblr:before{content:"\f5a8"}.fa-node:before{content:"\f419"}.fa-node-js:before{content:"\f3d3"}.fa-not-equal:before{content:"\f53e"}.fa-notes-medical:before{content:"\f481"}.fa-npm:before{content:"\f3d4"}.fa-ns8:before{content:"\f3d5"}.fa-nutritionix:before{content:"\f3d6"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-oil-can:before{content:"\f613"}.fa-old-republic:before{content:"\f510"}.fa-om:before{content:"\f679"}.fa-opencart:before{content:"\f23d"}.fa-openid:before{content:"\f19b"}.fa-opera:before{content:"\f26a"}.fa-optin-monster:before{content:"\f23c"}.fa-orcid:before{content:"\f8d2"}.fa-osi:before{content:"\f41a"}.fa-otter:before{content:"\f700"}.fa-outdent:before{content:"\f03b"}.fa-page4:before{content:"\f3d7"}.fa-pagelines:before{content:"\f18c"}.fa-pager:before{content:"\f815"}.fa-paint-brush:before{content:"\f1fc"}.fa-paint-roller:before{content:"\f5aa"}.fa-palette:before{content:"\f53f"}.fa-palfed:before{content:"\f3d8"}.fa-pallet:before{content:"\f482"}.fa-paper-plane:before{content:"\f1d8"}.fa-paperclip:before{content:"\f0c6"}.fa-parachute-box:before{content:"\f4cd"}.fa-paragraph:before{content:"\f1dd"}.fa-parking:before{content:"\f540"}.fa-passport:before{content:"\f5ab"}.fa-pastafarianism:before{content:"\f67b"}.fa-paste:before{content:"\f0ea"}.fa-patreon:before{content:"\f3d9"}.fa-pause:before{content:"\f04c"}.fa-pause-circle:before{content:"\f28b"}.fa-paw:before{content:"\f1b0"}.fa-paypal:before{content:"\f1ed"}.fa-peace:before{content:"\f67c"}.fa-pen:before{content:"\f304"}.fa-pen-alt:before{content:"\f305"}.fa-pen-fancy:before{content:"\f5ac"}.fa-pen-nib:before{content:"\f5ad"}.fa-pen-square:before{content:"\f14b"}.fa-pencil-alt:before{content:"\f303"}.fa-pencil-ruler:before{content:"\f5ae"}.fa-penny-arcade:before{content:"\f704"}.fa-people-carry:before{content:"\f4ce"}.fa-pepper-hot:before{content:"\f816"}.fa-percent:before{content:"\f295"}.fa-percentage:before{content:"\f541"}.fa-periscope:before{content:"\f3da"}.fa-person-booth:before{content:"\f756"}.fa-phabricator:before{content:"\f3db"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-phoenix-squadron:before{content:"\f511"}.fa-phone:before{content:"\f095"}.fa-phone-alt:before{content:"\f879"}.fa-phone-slash:before{content:"\f3dd"}.fa-phone-square:before{content:"\f098"}.fa-phone-square-alt:before{content:"\f87b"}.fa-phone-volume:before{content:"\f2a0"}.fa-photo-video:before{content:"\f87c"}.fa-php:before{content:"\f457"}.fa-pied-piper:before{content:"\f2ae"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-pied-piper-hat:before{content:"\f4e5"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-square:before{content:"\f91e"}.fa-piggy-bank:before{content:"\f4d3"}.fa-pills:before{content:"\f484"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-p:before{content:"\f231"}.fa-pinterest-square:before{content:"\f0d3"}.fa-pizza-slice:before{content:"\f818"}.fa-place-of-worship:before{content:"\f67f"}.fa-plane:before{content:"\f072"}.fa-plane-arrival:before{content:"\f5af"}.fa-plane-departure:before{content:"\f5b0"}.fa-play:before{content:"\f04b"}.fa-play-circle:before{content:"\f144"}.fa-playstation:before{content:"\f3df"}.fa-plug:before{content:"\f1e6"}.fa-plus:before{content:"\f067"}.fa-plus-circle:before{content:"\f055"}.fa-plus-square:before{content:"\f0fe"}.fa-podcast:before{content:"\f2ce"}.fa-poll:before{content:"\f681"}.fa-poll-h:before{content:"\f682"}.fa-poo:before{content:"\f2fe"}.fa-poo-storm:before{content:"\f75a"}.fa-poop:before{content:"\f619"}.fa-portrait:before{content:"\f3e0"}.fa-pound-sign:before{content:"\f154"}.fa-power-off:before{content:"\f011"}.fa-pray:before{content:"\f683"}.fa-praying-hands:before{content:"\f684"}.fa-prescription:before{content:"\f5b1"}.fa-prescription-bottle:before{content:"\f485"}.fa-prescription-bottle-alt:before{content:"\f486"}.fa-print:before{content:"\f02f"}.fa-procedures:before{content:"\f487"}.fa-product-hunt:before{content:"\f288"}.fa-project-diagram:before{content:"\f542"}.fa-pushed:before{content:"\f3e1"}.fa-puzzle-piece:before{content:"\f12e"}.fa-python:before{content:"\f3e2"}.fa-qq:before{content:"\f1d6"}.fa-qrcode:before{content:"\f029"}.fa-question:before{content:"\f128"}.fa-question-circle:before{content:"\f059"}.fa-quidditch:before{content:"\f458"}.fa-quinscape:before{content:"\f459"}.fa-quora:before{content:"\f2c4"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-quran:before{content:"\f687"}.fa-r-project:before{content:"\f4f7"}.fa-radiation:before{content:"\f7b9"}.fa-radiation-alt:before{content:"\f7ba"}.fa-rainbow:before{content:"\f75b"}.fa-random:before{content:"\f074"}.fa-raspberry-pi:before{content:"\f7bb"}.fa-ravelry:before{content:"\f2d9"}.fa-react:before{content:"\f41b"}.fa-reacteurope:before{content:"\f75d"}.fa-readme:before{content:"\f4d5"}.fa-rebel:before{content:"\f1d0"}.fa-receipt:before{content:"\f543"}.fa-record-vinyl:before{content:"\f8d9"}.fa-recycle:before{content:"\f1b8"}.fa-red-river:before{content:"\f3e3"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-alien:before{content:"\f281"}.fa-reddit-square:before{content:"\f1a2"}.fa-redhat:before{content:"\f7bc"}.fa-redo:before{content:"\f01e"}.fa-redo-alt:before{content:"\f2f9"}.fa-registered:before{content:"\f25d"}.fa-remove-format:before{content:"\f87d"}.fa-renren:before{content:"\f18b"}.fa-reply:before{content:"\f3e5"}.fa-reply-all:before{content:"\f122"}.fa-replyd:before{content:"\f3e6"}.fa-republican:before{content:"\f75e"}.fa-researchgate:before{content:"\f4f8"}.fa-resolving:before{content:"\f3e7"}.fa-restroom:before{content:"\f7bd"}.fa-retweet:before{content:"\f079"}.fa-rev:before{content:"\f5b2"}.fa-ribbon:before{content:"\f4d6"}.fa-ring:before{content:"\f70b"}.fa-road:before{content:"\f018"}.fa-robot:before{content:"\f544"}.fa-rocket:before{content:"\f135"}.fa-rocketchat:before{content:"\f3e8"}.fa-rockrms:before{content:"\f3e9"}.fa-route:before{content:"\f4d7"}.fa-rss:before{content:"\f09e"}.fa-rss-square:before{content:"\f143"}.fa-ruble-sign:before{content:"\f158"}.fa-ruler:before{content:"\f545"}.fa-ruler-combined:before{content:"\f546"}.fa-ruler-horizontal:before{content:"\f547"}.fa-ruler-vertical:before{content:"\f548"}.fa-running:before{content:"\f70c"}.fa-rupee-sign:before{content:"\f156"}.fa-sad-cry:before{content:"\f5b3"}.fa-sad-tear:before{content:"\f5b4"}.fa-safari:before{content:"\f267"}.fa-salesforce:before{content:"\f83b"}.fa-sass:before{content:"\f41e"}.fa-satellite:before{content:"\f7bf"}.fa-satellite-dish:before{content:"\f7c0"}.fa-save:before{content:"\f0c7"}.fa-schlix:before{content:"\f3ea"}.fa-school:before{content:"\f549"}.fa-screwdriver:before{content:"\f54a"}.fa-scribd:before{content:"\f28a"}.fa-scroll:before{content:"\f70e"}.fa-sd-card:before{content:"\f7c2"}.fa-search:before{content:"\f002"}.fa-search-dollar:before{content:"\f688"}.fa-search-location:before{content:"\f689"}.fa-search-minus:before{content:"\f010"}.fa-search-plus:before{content:"\f00e"}.fa-searchengin:before{content:"\f3eb"}.fa-seedling:before{content:"\f4d8"}.fa-sellcast:before{content:"\f2da"}.fa-sellsy:before{content:"\f213"}.fa-server:before{content:"\f233"}.fa-servicestack:before{content:"\f3ec"}.fa-shapes:before{content:"\f61f"}.fa-share:before{content:"\f064"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-share-square:before{content:"\f14d"}.fa-shekel-sign:before{content:"\f20b"}.fa-shield-alt:before{content:"\f3ed"}.fa-ship:before{content:"\f21a"}.fa-shipping-fast:before{content:"\f48b"}.fa-shirtsinbulk:before{content:"\f214"}.fa-shoe-prints:before{content:"\f54b"}.fa-shopify:before{content:"\f957"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-shopping-cart:before{content:"\f07a"}.fa-shopware:before{content:"\f5b5"}.fa-shower:before{content:"\f2cc"}.fa-shuttle-van:before{content:"\f5b6"}.fa-sign:before{content:"\f4d9"}.fa-sign-in-alt:before{content:"\f2f6"}.fa-sign-language:before{content:"\f2a7"}.fa-sign-out-alt:before{content:"\f2f5"}.fa-signal:before{content:"\f012"}.fa-signature:before{content:"\f5b7"}.fa-sim-card:before{content:"\f7c4"}.fa-simplybuilt:before{content:"\f215"}.fa-sistrix:before{content:"\f3ee"}.fa-sitemap:before{content:"\f0e8"}.fa-sith:before{content:"\f512"}.fa-skating:before{content:"\f7c5"}.fa-sketch:before{content:"\f7c6"}.fa-skiing:before{content:"\f7c9"}.fa-skiing-nordic:before{content:"\f7ca"}.fa-skull:before{content:"\f54c"}.fa-skull-crossbones:before{content:"\f714"}.fa-skyatlas:before{content:"\f216"}.fa-skype:before{content:"\f17e"}.fa-slack:before{content:"\f198"}.fa-slack-hash:before{content:"\f3ef"}.fa-slash:before{content:"\f715"}.fa-sleigh:before{content:"\f7cc"}.fa-sliders-h:before{content:"\f1de"}.fa-slideshare:before{content:"\f1e7"}.fa-smile:before{content:"\f118"}.fa-smile-beam:before{content:"\f5b8"}.fa-smile-wink:before{content:"\f4da"}.fa-smog:before{content:"\f75f"}.fa-smoking:before{content:"\f48d"}.fa-smoking-ban:before{content:"\f54d"}.fa-sms:before{content:"\f7cd"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-snowboarding:before{content:"\f7ce"}.fa-snowflake:before{content:"\f2dc"}.fa-snowman:before{content:"\f7d0"}.fa-snowplow:before{content:"\f7d2"}.fa-socks:before{content:"\f696"}.fa-solar-panel:before{content:"\f5ba"}.fa-sort:before{content:"\f0dc"}.fa-sort-alpha-down:before{content:"\f15d"}.fa-sort-alpha-down-alt:before{content:"\f881"}.fa-sort-alpha-up:before{content:"\f15e"}.fa-sort-alpha-up-alt:before{content:"\f882"}.fa-sort-amount-down:before{content:"\f160"}.fa-sort-amount-down-alt:before{content:"\f884"}.fa-sort-amount-up:before{content:"\f161"}.fa-sort-amount-up-alt:before{content:"\f885"}.fa-sort-down:before{content:"\f0dd"}.fa-sort-numeric-down:before{content:"\f162"}.fa-sort-numeric-down-alt:before{content:"\f886"}.fa-sort-numeric-up:before{content:"\f163"}.fa-sort-numeric-up-alt:before{content:"\f887"}.fa-sort-up:before{content:"\f0de"}.fa-soundcloud:before{content:"\f1be"}.fa-sourcetree:before{content:"\f7d3"}.fa-spa:before{content:"\f5bb"}.fa-space-shuttle:before{content:"\f197"}.fa-speakap:before{content:"\f3f3"}.fa-speaker-deck:before{content:"\f83c"}.fa-spell-check:before{content:"\f891"}.fa-spider:before{content:"\f717"}.fa-spinner:before{content:"\f110"}.fa-splotch:before{content:"\f5bc"}.fa-spotify:before{content:"\f1bc"}.fa-spray-can:before{content:"\f5bd"}.fa-square:before{content:"\f0c8"}.fa-square-full:before{content:"\f45c"}.fa-square-root-alt:before{content:"\f698"}.fa-squarespace:before{content:"\f5be"}.fa-stack-exchange:before{content:"\f18d"}.fa-stack-overflow:before{content:"\f16c"}.fa-stackpath:before{content:"\f842"}.fa-stamp:before{content:"\f5bf"}.fa-star:before{content:"\f005"}.fa-star-and-crescent:before{content:"\f699"}.fa-star-half:before{content:"\f089"}.fa-star-half-alt:before{content:"\f5c0"}.fa-star-of-david:before{content:"\f69a"}.fa-star-of-life:before{content:"\f621"}.fa-staylinked:before{content:"\f3f5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-steam-symbol:before{content:"\f3f6"}.fa-step-backward:before{content:"\f048"}.fa-step-forward:before{content:"\f051"}.fa-stethoscope:before{content:"\f0f1"}.fa-sticker-mule:before{content:"\f3f7"}.fa-sticky-note:before{content:"\f249"}.fa-stop:before{content:"\f04d"}.fa-stop-circle:before{content:"\f28d"}.fa-stopwatch:before{content:"\f2f2"}.fa-store:before{content:"\f54e"}.fa-store-alt:before{content:"\f54f"}.fa-strava:before{content:"\f428"}.fa-stream:before{content:"\f550"}.fa-street-view:before{content:"\f21d"}.fa-strikethrough:before{content:"\f0cc"}.fa-stripe:before{content:"\f429"}.fa-stripe-s:before{content:"\f42a"}.fa-stroopwafel:before{content:"\f551"}.fa-studiovinari:before{content:"\f3f8"}.fa-stumbleupon:before{content:"\f1a4"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-subscript:before{content:"\f12c"}.fa-subway:before{content:"\f239"}.fa-suitcase:before{content:"\f0f2"}.fa-suitcase-rolling:before{content:"\f5c1"}.fa-sun:before{content:"\f185"}.fa-superpowers:before{content:"\f2dd"}.fa-superscript:before{content:"\f12b"}.fa-supple:before{content:"\f3f9"}.fa-surprise:before{content:"\f5c2"}.fa-suse:before{content:"\f7d6"}.fa-swatchbook:before{content:"\f5c3"}.fa-swift:before{content:"\f8e1"}.fa-swimmer:before{content:"\f5c4"}.fa-swimming-pool:before{content:"\f5c5"}.fa-symfony:before{content:"\f83d"}.fa-synagogue:before{content:"\f69b"}.fa-sync:before{content:"\f021"}.fa-sync-alt:before{content:"\f2f1"}.fa-syringe:before{content:"\f48e"}.fa-table:before{content:"\f0ce"}.fa-table-tennis:before{content:"\f45d"}.fa-tablet:before{content:"\f10a"}.fa-tablet-alt:before{content:"\f3fa"}.fa-tablets:before{content:"\f490"}.fa-tachometer-alt:before{content:"\f3fd"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-tape:before{content:"\f4db"}.fa-tasks:before{content:"\f0ae"}.fa-taxi:before{content:"\f1ba"}.fa-teamspeak:before{content:"\f4f9"}.fa-teeth:before{content:"\f62e"}.fa-teeth-open:before{content:"\f62f"}.fa-telegram:before{content:"\f2c6"}.fa-telegram-plane:before{content:"\f3fe"}.fa-temperature-high:before{content:"\f769"}.fa-temperature-low:before{content:"\f76b"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-tenge:before{content:"\f7d7"}.fa-terminal:before{content:"\f120"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-th:before{content:"\f00a"}.fa-th-large:before{content:"\f009"}.fa-th-list:before{content:"\f00b"}.fa-the-red-yeti:before{content:"\f69d"}.fa-theater-masks:before{content:"\f630"}.fa-themeco:before{content:"\f5c6"}.fa-themeisle:before{content:"\f2b2"}.fa-thermometer:before{content:"\f491"}.fa-thermometer-empty:before{content:"\f2cb"}.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-think-peaks:before{content:"\f731"}.fa-thumbs-down:before{content:"\f165"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbtack:before{content:"\f08d"}.fa-ticket-alt:before{content:"\f3ff"}.fa-times:before{content:"\f00d"}.fa-times-circle:before{content:"\f057"}.fa-tint:before{content:"\f043"}.fa-tint-slash:before{content:"\f5c7"}.fa-tired:before{content:"\f5c8"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-toilet:before{content:"\f7d8"}.fa-toilet-paper:before{content:"\f71e"}.fa-toolbox:before{content:"\f552"}.fa-tools:before{content:"\f7d9"}.fa-tooth:before{content:"\f5c9"}.fa-torah:before{content:"\f6a0"}.fa-torii-gate:before{content:"\f6a1"}.fa-tractor:before{content:"\f722"}.fa-trade-federation:before{content:"\f513"}.fa-trademark:before{content:"\f25c"}.fa-traffic-light:before{content:"\f637"}.fa-trailer:before{content:"\f941"}.fa-train:before{content:"\f238"}.fa-tram:before{content:"\f7da"}.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-trash:before{content:"\f1f8"}.fa-trash-alt:before{content:"\f2ed"}.fa-trash-restore:before{content:"\f829"}.fa-trash-restore-alt:before{content:"\f82a"}.fa-tree:before{content:"\f1bb"}.fa-trello:before{content:"\f181"}.fa-tripadvisor:before{content:"\f262"}.fa-trophy:before{content:"\f091"}.fa-truck:before{content:"\f0d1"}.fa-truck-loading:before{content:"\f4de"}.fa-truck-monster:before{content:"\f63b"}.fa-truck-moving:before{content:"\f4df"}.fa-truck-pickup:before{content:"\f63c"}.fa-tshirt:before{content:"\f553"}.fa-tty:before{content:"\f1e4"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-tv:before{content:"\f26c"}.fa-twitch:before{content:"\f1e8"}.fa-twitter:before{content:"\f099"}.fa-twitter-square:before{content:"\f081"}.fa-typo3:before{content:"\f42b"}.fa-uber:before{content:"\f402"}.fa-ubuntu:before{content:"\f7df"}.fa-uikit:before{content:"\f403"}.fa-umbraco:before{content:"\f8e8"}.fa-umbrella:before{content:"\f0e9"}.fa-umbrella-beach:before{content:"\f5ca"}.fa-underline:before{content:"\f0cd"}.fa-undo:before{content:"\f0e2"}.fa-undo-alt:before{content:"\f2ea"}.fa-uniregistry:before{content:"\f404"}.fa-unity:before{content:"\f949"}.fa-universal-access:before{content:"\f29a"}.fa-university:before{content:"\f19c"}.fa-unlink:before{content:"\f127"}.fa-unlock:before{content:"\f09c"}.fa-unlock-alt:before{content:"\f13e"}.fa-untappd:before{content:"\f405"}.fa-upload:before{content:"\f093"}.fa-ups:before{content:"\f7e0"}.fa-usb:before{content:"\f287"}.fa-user:before{content:"\f007"}.fa-user-alt:before{content:"\f406"}.fa-user-alt-slash:before{content:"\f4fa"}.fa-user-astronaut:before{content:"\f4fb"}.fa-user-check:before{content:"\f4fc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-clock:before{content:"\f4fd"}.fa-user-cog:before{content:"\f4fe"}.fa-user-edit:before{content:"\f4ff"}.fa-user-friends:before{content:"\f500"}.fa-user-graduate:before{content:"\f501"}.fa-user-injured:before{content:"\f728"}.fa-user-lock:before{content:"\f502"}.fa-user-md:before{content:"\f0f0"}.fa-user-minus:before{content:"\f503"}.fa-user-ninja:before{content:"\f504"}.fa-user-nurse:before{content:"\f82f"}.fa-user-plus:before{content:"\f234"}.fa-user-secret:before{content:"\f21b"}.fa-user-shield:before{content:"\f505"}.fa-user-slash:before{content:"\f506"}.fa-user-tag:before{content:"\f507"}.fa-user-tie:before{content:"\f508"}.fa-user-times:before{content:"\f235"}.fa-users:before{content:"\f0c0"}.fa-users-cog:before{content:"\f509"}.fa-usps:before{content:"\f7e1"}.fa-ussunnah:before{content:"\f407"}.fa-utensil-spoon:before{content:"\f2e5"}.fa-utensils:before{content:"\f2e7"}.fa-vaadin:before{content:"\f408"}.fa-vector-square:before{content:"\f5cb"}.fa-venus:before{content:"\f221"}.fa-venus-double:before{content:"\f226"}.fa-venus-mars:before{content:"\f228"}.fa-viacoin:before{content:"\f237"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-vial:before{content:"\f492"}.fa-vials:before{content:"\f493"}.fa-viber:before{content:"\f409"}.fa-video:before{content:"\f03d"}.fa-video-slash:before{content:"\f4e2"}.fa-vihara:before{content:"\f6a7"}.fa-vimeo:before{content:"\f40a"}.fa-vimeo-square:before{content:"\f194"}.fa-vimeo-v:before{content:"\f27d"}.fa-vine:before{content:"\f1ca"}.fa-vk:before{content:"\f189"}.fa-vnv:before{content:"\f40b"}.fa-voicemail:before{content:"\f897"}.fa-volleyball-ball:before{content:"\f45f"}.fa-volume-down:before{content:"\f027"}.fa-volume-mute:before{content:"\f6a9"}.fa-volume-off:before{content:"\f026"}.fa-volume-up:before{content:"\f028"}.fa-vote-yea:before{content:"\f772"}.fa-vr-cardboard:before{content:"\f729"}.fa-vuejs:before{content:"\f41f"}.fa-walking:before{content:"\f554"}.fa-wallet:before{content:"\f555"}.fa-warehouse:before{content:"\f494"}.fa-water:before{content:"\f773"}.fa-wave-square:before{content:"\f83e"}.fa-waze:before{content:"\f83f"}.fa-weebly:before{content:"\f5cc"}.fa-weibo:before{content:"\f18a"}.fa-weight:before{content:"\f496"}.fa-weight-hanging:before{content:"\f5cd"}.fa-weixin:before{content:"\f1d7"}.fa-whatsapp:before{content:"\f232"}.fa-whatsapp-square:before{content:"\f40c"}.fa-wheelchair:before{content:"\f193"}.fa-whmcs:before{content:"\f40d"}.fa-wifi:before{content:"\f1eb"}.fa-wikipedia-w:before{content:"\f266"}.fa-wind:before{content:"\f72e"}.fa-window-close:before{content:"\f410"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-windows:before{content:"\f17a"}.fa-wine-bottle:before{content:"\f72f"}.fa-wine-glass:before{content:"\f4e3"}.fa-wine-glass-alt:before{content:"\f5ce"}.fa-wix:before{content:"\f5cf"}.fa-wizards-of-the-coast:before{content:"\f730"}.fa-wolf-pack-battalion:before{content:"\f514"}.fa-won-sign:before{content:"\f159"}.fa-wordpress:before{content:"\f19a"}.fa-wordpress-simple:before{content:"\f411"}.fa-wpbeginner:before{content:"\f297"}.fa-wpexplorer:before{content:"\f2de"}.fa-wpforms:before{content:"\f298"}.fa-wpressr:before{content:"\f3e4"}.fa-wrench:before{content:"\f0ad"}.fa-x-ray:before{content:"\f497"}.fa-xbox:before{content:"\f412"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-y-combinator:before{content:"\f23b"}.fa-yahoo:before{content:"\f19e"}.fa-yammer:before{content:"\f840"}.fa-yandex:before{content:"\f413"}.fa-yandex-international:before{content:"\f414"}.fa-yarn:before{content:"\f7e3"}.fa-yelp:before{content:"\f1e9"}.fa-yen-sign:before{content:"\f157"}.fa-yin-yang:before{content:"\f6ad"}.fa-yoast:before{content:"\f2b1"}.fa-youtube:before{content:"\f167"}.fa-youtube-square:before{content:"\f431"}.fa-zhihu:before{content:"\f63f"}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}@font-face{font-family:"Font Awesome 5 Brands";font-style:normal;font-weight:400;font-display:auto;src:url(../webfonts/fa-brands-400.eot);src:url(../webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.woff) format("woff"),url(../webfonts/fa-brands-400.ttf) format("truetype"),url(../webfonts/fa-brands-400.svg#fontawesome) format("svg")}.fab{font-family:"Font Awesome 5 Brands"}@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:400;font-display:auto;src:url(../webfonts/fa-regular-400.eot);src:url(../webfonts/fa-regular-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.woff) format("woff"),url(../webfonts/fa-regular-400.ttf) format("truetype"),url(../webfonts/fa-regular-400.svg#fontawesome) format("svg")}.fab,.far{font-weight:400}@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:900;font-display:auto;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa,.far,.fas{font-family:"Font Awesome 5 Free"}.fa,.fas{font-weight:900} \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/brands.css b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/brands.css new file mode 100755 index 0000000..46f4266 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/brands.css @@ -0,0 +1,15 @@ +/*! + * Font Awesome Free 5.12.1 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +@font-face { + font-family: 'Font Awesome 5 Brands'; + font-style: normal; + font-weight: 400; + font-display: auto; + src: url("../webfonts/fa-brands-400.eot"); + src: url("../webfonts/fa-brands-400.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.woff") format("woff"), url("../webfonts/fa-brands-400.ttf") format("truetype"), url("../webfonts/fa-brands-400.svg#fontawesome") format("svg"); } + +.fab { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/brands.min.css b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/brands.min.css new file mode 100755 index 0000000..1455bae --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/brands.min.css @@ -0,0 +1,5 @@ +/*! + * Font Awesome Free 5.12.1 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +@font-face{font-family:"Font Awesome 5 Brands";font-style:normal;font-weight:400;font-display:auto;src:url(../webfonts/fa-brands-400.eot);src:url(../webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.woff) format("woff"),url(../webfonts/fa-brands-400.ttf) format("truetype"),url(../webfonts/fa-brands-400.svg#fontawesome) format("svg")}.fab{font-family:"Font Awesome 5 Brands";font-weight:400} \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/fontawesome.css b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/fontawesome.css new file mode 100755 index 0000000..b3e0c53 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/fontawesome.css @@ -0,0 +1,4429 @@ +/*! + * Font Awesome Free 5.12.1 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +.fa, +.fas, +.far, +.fal, +.fad, +.fab { + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + display: inline-block; + font-style: normal; + font-variant: normal; + text-rendering: auto; + line-height: 1; } + +.fa-lg { + font-size: 1.33333em; + line-height: 0.75em; + vertical-align: -.0667em; } + +.fa-xs { + font-size: .75em; } + +.fa-sm { + font-size: .875em; } + +.fa-1x { + font-size: 1em; } + +.fa-2x { + font-size: 2em; } + +.fa-3x { + font-size: 3em; } + +.fa-4x { + font-size: 4em; } + +.fa-5x { + font-size: 5em; } + +.fa-6x { + font-size: 6em; } + +.fa-7x { + font-size: 7em; } + +.fa-8x { + font-size: 8em; } + +.fa-9x { + font-size: 9em; } + +.fa-10x { + font-size: 10em; } + +.fa-fw { + text-align: center; + width: 1.25em; } + +.fa-ul { + list-style-type: none; + margin-left: 2.5em; + padding-left: 0; } + .fa-ul > li { + position: relative; } + +.fa-li { + left: -2em; + position: absolute; + text-align: center; + width: 2em; + line-height: inherit; } + +.fa-border { + border: solid 0.08em #eee; + border-radius: .1em; + padding: .2em .25em .15em; } + +.fa-pull-left { + float: left; } + +.fa-pull-right { + float: right; } + +.fa.fa-pull-left, +.fas.fa-pull-left, +.far.fa-pull-left, +.fal.fa-pull-left, +.fab.fa-pull-left { + margin-right: .3em; } + +.fa.fa-pull-right, +.fas.fa-pull-right, +.far.fa-pull-right, +.fal.fa-pull-right, +.fab.fa-pull-right { + margin-left: .3em; } + +.fa-spin { + -webkit-animation: fa-spin 2s infinite linear; + animation: fa-spin 2s infinite linear; } + +.fa-pulse { + -webkit-animation: fa-spin 1s infinite steps(8); + animation: fa-spin 1s infinite steps(8); } + +@-webkit-keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); } } + +@keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); } } + +.fa-rotate-90 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)"; + -webkit-transform: rotate(90deg); + transform: rotate(90deg); } + +.fa-rotate-180 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)"; + -webkit-transform: rotate(180deg); + transform: rotate(180deg); } + +.fa-rotate-270 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)"; + -webkit-transform: rotate(270deg); + transform: rotate(270deg); } + +.fa-flip-horizontal { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)"; + -webkit-transform: scale(-1, 1); + transform: scale(-1, 1); } + +.fa-flip-vertical { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; + -webkit-transform: scale(1, -1); + transform: scale(1, -1); } + +.fa-flip-both, .fa-flip-horizontal.fa-flip-vertical { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; + -webkit-transform: scale(-1, -1); + transform: scale(-1, -1); } + +:root .fa-rotate-90, +:root .fa-rotate-180, +:root .fa-rotate-270, +:root .fa-flip-horizontal, +:root .fa-flip-vertical, +:root .fa-flip-both { + -webkit-filter: none; + filter: none; } + +.fa-stack { + display: inline-block; + height: 2em; + line-height: 2em; + position: relative; + vertical-align: middle; + width: 2.5em; } + +.fa-stack-1x, +.fa-stack-2x { + left: 0; + position: absolute; + text-align: center; + width: 100%; } + +.fa-stack-1x { + line-height: inherit; } + +.fa-stack-2x { + font-size: 2em; } + +.fa-inverse { + color: #fff; } + +/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen +readers do not read off random characters that represent icons */ +.fa-500px:before { + content: "\f26e"; } + +.fa-accessible-icon:before { + content: "\f368"; } + +.fa-accusoft:before { + content: "\f369"; } + +.fa-acquisitions-incorporated:before { + content: "\f6af"; } + +.fa-ad:before { + content: "\f641"; } + +.fa-address-book:before { + content: "\f2b9"; } + +.fa-address-card:before { + content: "\f2bb"; } + +.fa-adjust:before { + content: "\f042"; } + +.fa-adn:before { + content: "\f170"; } + +.fa-adobe:before { + content: "\f778"; } + +.fa-adversal:before { + content: "\f36a"; } + +.fa-affiliatetheme:before { + content: "\f36b"; } + +.fa-air-freshener:before { + content: "\f5d0"; } + +.fa-airbnb:before { + content: "\f834"; } + +.fa-algolia:before { + content: "\f36c"; } + +.fa-align-center:before { + content: "\f037"; } + +.fa-align-justify:before { + content: "\f039"; } + +.fa-align-left:before { + content: "\f036"; } + +.fa-align-right:before { + content: "\f038"; } + +.fa-alipay:before { + content: "\f642"; } + +.fa-allergies:before { + content: "\f461"; } + +.fa-amazon:before { + content: "\f270"; } + +.fa-amazon-pay:before { + content: "\f42c"; } + +.fa-ambulance:before { + content: "\f0f9"; } + +.fa-american-sign-language-interpreting:before { + content: "\f2a3"; } + +.fa-amilia:before { + content: "\f36d"; } + +.fa-anchor:before { + content: "\f13d"; } + +.fa-android:before { + content: "\f17b"; } + +.fa-angellist:before { + content: "\f209"; } + +.fa-angle-double-down:before { + content: "\f103"; } + +.fa-angle-double-left:before { + content: "\f100"; } + +.fa-angle-double-right:before { + content: "\f101"; } + +.fa-angle-double-up:before { + content: "\f102"; } + +.fa-angle-down:before { + content: "\f107"; } + +.fa-angle-left:before { + content: "\f104"; } + +.fa-angle-right:before { + content: "\f105"; } + +.fa-angle-up:before { + content: "\f106"; } + +.fa-angry:before { + content: "\f556"; } + +.fa-angrycreative:before { + content: "\f36e"; } + +.fa-angular:before { + content: "\f420"; } + +.fa-ankh:before { + content: "\f644"; } + +.fa-app-store:before { + content: "\f36f"; } + +.fa-app-store-ios:before { + content: "\f370"; } + +.fa-apper:before { + content: "\f371"; } + +.fa-apple:before { + content: "\f179"; } + +.fa-apple-alt:before { + content: "\f5d1"; } + +.fa-apple-pay:before { + content: "\f415"; } + +.fa-archive:before { + content: "\f187"; } + +.fa-archway:before { + content: "\f557"; } + +.fa-arrow-alt-circle-down:before { + content: "\f358"; } + +.fa-arrow-alt-circle-left:before { + content: "\f359"; } + +.fa-arrow-alt-circle-right:before { + content: "\f35a"; } + +.fa-arrow-alt-circle-up:before { + content: "\f35b"; } + +.fa-arrow-circle-down:before { + content: "\f0ab"; } + +.fa-arrow-circle-left:before { + content: "\f0a8"; } + +.fa-arrow-circle-right:before { + content: "\f0a9"; } + +.fa-arrow-circle-up:before { + content: "\f0aa"; } + +.fa-arrow-down:before { + content: "\f063"; } + +.fa-arrow-left:before { + content: "\f060"; } + +.fa-arrow-right:before { + content: "\f061"; } + +.fa-arrow-up:before { + content: "\f062"; } + +.fa-arrows-alt:before { + content: "\f0b2"; } + +.fa-arrows-alt-h:before { + content: "\f337"; } + +.fa-arrows-alt-v:before { + content: "\f338"; } + +.fa-artstation:before { + content: "\f77a"; } + +.fa-assistive-listening-systems:before { + content: "\f2a2"; } + +.fa-asterisk:before { + content: "\f069"; } + +.fa-asymmetrik:before { + content: "\f372"; } + +.fa-at:before { + content: "\f1fa"; } + +.fa-atlas:before { + content: "\f558"; } + +.fa-atlassian:before { + content: "\f77b"; } + +.fa-atom:before { + content: "\f5d2"; } + +.fa-audible:before { + content: "\f373"; } + +.fa-audio-description:before { + content: "\f29e"; } + +.fa-autoprefixer:before { + content: "\f41c"; } + +.fa-avianex:before { + content: "\f374"; } + +.fa-aviato:before { + content: "\f421"; } + +.fa-award:before { + content: "\f559"; } + +.fa-aws:before { + content: "\f375"; } + +.fa-baby:before { + content: "\f77c"; } + +.fa-baby-carriage:before { + content: "\f77d"; } + +.fa-backspace:before { + content: "\f55a"; } + +.fa-backward:before { + content: "\f04a"; } + +.fa-bacon:before { + content: "\f7e5"; } + +.fa-bahai:before { + content: "\f666"; } + +.fa-balance-scale:before { + content: "\f24e"; } + +.fa-balance-scale-left:before { + content: "\f515"; } + +.fa-balance-scale-right:before { + content: "\f516"; } + +.fa-ban:before { + content: "\f05e"; } + +.fa-band-aid:before { + content: "\f462"; } + +.fa-bandcamp:before { + content: "\f2d5"; } + +.fa-barcode:before { + content: "\f02a"; } + +.fa-bars:before { + content: "\f0c9"; } + +.fa-baseball-ball:before { + content: "\f433"; } + +.fa-basketball-ball:before { + content: "\f434"; } + +.fa-bath:before { + content: "\f2cd"; } + +.fa-battery-empty:before { + content: "\f244"; } + +.fa-battery-full:before { + content: "\f240"; } + +.fa-battery-half:before { + content: "\f242"; } + +.fa-battery-quarter:before { + content: "\f243"; } + +.fa-battery-three-quarters:before { + content: "\f241"; } + +.fa-battle-net:before { + content: "\f835"; } + +.fa-bed:before { + content: "\f236"; } + +.fa-beer:before { + content: "\f0fc"; } + +.fa-behance:before { + content: "\f1b4"; } + +.fa-behance-square:before { + content: "\f1b5"; } + +.fa-bell:before { + content: "\f0f3"; } + +.fa-bell-slash:before { + content: "\f1f6"; } + +.fa-bezier-curve:before { + content: "\f55b"; } + +.fa-bible:before { + content: "\f647"; } + +.fa-bicycle:before { + content: "\f206"; } + +.fa-biking:before { + content: "\f84a"; } + +.fa-bimobject:before { + content: "\f378"; } + +.fa-binoculars:before { + content: "\f1e5"; } + +.fa-biohazard:before { + content: "\f780"; } + +.fa-birthday-cake:before { + content: "\f1fd"; } + +.fa-bitbucket:before { + content: "\f171"; } + +.fa-bitcoin:before { + content: "\f379"; } + +.fa-bity:before { + content: "\f37a"; } + +.fa-black-tie:before { + content: "\f27e"; } + +.fa-blackberry:before { + content: "\f37b"; } + +.fa-blender:before { + content: "\f517"; } + +.fa-blender-phone:before { + content: "\f6b6"; } + +.fa-blind:before { + content: "\f29d"; } + +.fa-blog:before { + content: "\f781"; } + +.fa-blogger:before { + content: "\f37c"; } + +.fa-blogger-b:before { + content: "\f37d"; } + +.fa-bluetooth:before { + content: "\f293"; } + +.fa-bluetooth-b:before { + content: "\f294"; } + +.fa-bold:before { + content: "\f032"; } + +.fa-bolt:before { + content: "\f0e7"; } + +.fa-bomb:before { + content: "\f1e2"; } + +.fa-bone:before { + content: "\f5d7"; } + +.fa-bong:before { + content: "\f55c"; } + +.fa-book:before { + content: "\f02d"; } + +.fa-book-dead:before { + content: "\f6b7"; } + +.fa-book-medical:before { + content: "\f7e6"; } + +.fa-book-open:before { + content: "\f518"; } + +.fa-book-reader:before { + content: "\f5da"; } + +.fa-bookmark:before { + content: "\f02e"; } + +.fa-bootstrap:before { + content: "\f836"; } + +.fa-border-all:before { + content: "\f84c"; } + +.fa-border-none:before { + content: "\f850"; } + +.fa-border-style:before { + content: "\f853"; } + +.fa-bowling-ball:before { + content: "\f436"; } + +.fa-box:before { + content: "\f466"; } + +.fa-box-open:before { + content: "\f49e"; } + +.fa-boxes:before { + content: "\f468"; } + +.fa-braille:before { + content: "\f2a1"; } + +.fa-brain:before { + content: "\f5dc"; } + +.fa-bread-slice:before { + content: "\f7ec"; } + +.fa-briefcase:before { + content: "\f0b1"; } + +.fa-briefcase-medical:before { + content: "\f469"; } + +.fa-broadcast-tower:before { + content: "\f519"; } + +.fa-broom:before { + content: "\f51a"; } + +.fa-brush:before { + content: "\f55d"; } + +.fa-btc:before { + content: "\f15a"; } + +.fa-buffer:before { + content: "\f837"; } + +.fa-bug:before { + content: "\f188"; } + +.fa-building:before { + content: "\f1ad"; } + +.fa-bullhorn:before { + content: "\f0a1"; } + +.fa-bullseye:before { + content: "\f140"; } + +.fa-burn:before { + content: "\f46a"; } + +.fa-buromobelexperte:before { + content: "\f37f"; } + +.fa-bus:before { + content: "\f207"; } + +.fa-bus-alt:before { + content: "\f55e"; } + +.fa-business-time:before { + content: "\f64a"; } + +.fa-buy-n-large:before { + content: "\f8a6"; } + +.fa-buysellads:before { + content: "\f20d"; } + +.fa-calculator:before { + content: "\f1ec"; } + +.fa-calendar:before { + content: "\f133"; } + +.fa-calendar-alt:before { + content: "\f073"; } + +.fa-calendar-check:before { + content: "\f274"; } + +.fa-calendar-day:before { + content: "\f783"; } + +.fa-calendar-minus:before { + content: "\f272"; } + +.fa-calendar-plus:before { + content: "\f271"; } + +.fa-calendar-times:before { + content: "\f273"; } + +.fa-calendar-week:before { + content: "\f784"; } + +.fa-camera:before { + content: "\f030"; } + +.fa-camera-retro:before { + content: "\f083"; } + +.fa-campground:before { + content: "\f6bb"; } + +.fa-canadian-maple-leaf:before { + content: "\f785"; } + +.fa-candy-cane:before { + content: "\f786"; } + +.fa-cannabis:before { + content: "\f55f"; } + +.fa-capsules:before { + content: "\f46b"; } + +.fa-car:before { + content: "\f1b9"; } + +.fa-car-alt:before { + content: "\f5de"; } + +.fa-car-battery:before { + content: "\f5df"; } + +.fa-car-crash:before { + content: "\f5e1"; } + +.fa-car-side:before { + content: "\f5e4"; } + +.fa-caravan:before { + content: "\f8ff"; } + +.fa-caret-down:before { + content: "\f0d7"; } + +.fa-caret-left:before { + content: "\f0d9"; } + +.fa-caret-right:before { + content: "\f0da"; } + +.fa-caret-square-down:before { + content: "\f150"; } + +.fa-caret-square-left:before { + content: "\f191"; } + +.fa-caret-square-right:before { + content: "\f152"; } + +.fa-caret-square-up:before { + content: "\f151"; } + +.fa-caret-up:before { + content: "\f0d8"; } + +.fa-carrot:before { + content: "\f787"; } + +.fa-cart-arrow-down:before { + content: "\f218"; } + +.fa-cart-plus:before { + content: "\f217"; } + +.fa-cash-register:before { + content: "\f788"; } + +.fa-cat:before { + content: "\f6be"; } + +.fa-cc-amazon-pay:before { + content: "\f42d"; } + +.fa-cc-amex:before { + content: "\f1f3"; } + +.fa-cc-apple-pay:before { + content: "\f416"; } + +.fa-cc-diners-club:before { + content: "\f24c"; } + +.fa-cc-discover:before { + content: "\f1f2"; } + +.fa-cc-jcb:before { + content: "\f24b"; } + +.fa-cc-mastercard:before { + content: "\f1f1"; } + +.fa-cc-paypal:before { + content: "\f1f4"; } + +.fa-cc-stripe:before { + content: "\f1f5"; } + +.fa-cc-visa:before { + content: "\f1f0"; } + +.fa-centercode:before { + content: "\f380"; } + +.fa-centos:before { + content: "\f789"; } + +.fa-certificate:before { + content: "\f0a3"; } + +.fa-chair:before { + content: "\f6c0"; } + +.fa-chalkboard:before { + content: "\f51b"; } + +.fa-chalkboard-teacher:before { + content: "\f51c"; } + +.fa-charging-station:before { + content: "\f5e7"; } + +.fa-chart-area:before { + content: "\f1fe"; } + +.fa-chart-bar:before { + content: "\f080"; } + +.fa-chart-line:before { + content: "\f201"; } + +.fa-chart-pie:before { + content: "\f200"; } + +.fa-check:before { + content: "\f00c"; } + +.fa-check-circle:before { + content: "\f058"; } + +.fa-check-double:before { + content: "\f560"; } + +.fa-check-square:before { + content: "\f14a"; } + +.fa-cheese:before { + content: "\f7ef"; } + +.fa-chess:before { + content: "\f439"; } + +.fa-chess-bishop:before { + content: "\f43a"; } + +.fa-chess-board:before { + content: "\f43c"; } + +.fa-chess-king:before { + content: "\f43f"; } + +.fa-chess-knight:before { + content: "\f441"; } + +.fa-chess-pawn:before { + content: "\f443"; } + +.fa-chess-queen:before { + content: "\f445"; } + +.fa-chess-rook:before { + content: "\f447"; } + +.fa-chevron-circle-down:before { + content: "\f13a"; } + +.fa-chevron-circle-left:before { + content: "\f137"; } + +.fa-chevron-circle-right:before { + content: "\f138"; } + +.fa-chevron-circle-up:before { + content: "\f139"; } + +.fa-chevron-down:before { + content: "\f078"; } + +.fa-chevron-left:before { + content: "\f053"; } + +.fa-chevron-right:before { + content: "\f054"; } + +.fa-chevron-up:before { + content: "\f077"; } + +.fa-child:before { + content: "\f1ae"; } + +.fa-chrome:before { + content: "\f268"; } + +.fa-chromecast:before { + content: "\f838"; } + +.fa-church:before { + content: "\f51d"; } + +.fa-circle:before { + content: "\f111"; } + +.fa-circle-notch:before { + content: "\f1ce"; } + +.fa-city:before { + content: "\f64f"; } + +.fa-clinic-medical:before { + content: "\f7f2"; } + +.fa-clipboard:before { + content: "\f328"; } + +.fa-clipboard-check:before { + content: "\f46c"; } + +.fa-clipboard-list:before { + content: "\f46d"; } + +.fa-clock:before { + content: "\f017"; } + +.fa-clone:before { + content: "\f24d"; } + +.fa-closed-captioning:before { + content: "\f20a"; } + +.fa-cloud:before { + content: "\f0c2"; } + +.fa-cloud-download-alt:before { + content: "\f381"; } + +.fa-cloud-meatball:before { + content: "\f73b"; } + +.fa-cloud-moon:before { + content: "\f6c3"; } + +.fa-cloud-moon-rain:before { + content: "\f73c"; } + +.fa-cloud-rain:before { + content: "\f73d"; } + +.fa-cloud-showers-heavy:before { + content: "\f740"; } + +.fa-cloud-sun:before { + content: "\f6c4"; } + +.fa-cloud-sun-rain:before { + content: "\f743"; } + +.fa-cloud-upload-alt:before { + content: "\f382"; } + +.fa-cloudscale:before { + content: "\f383"; } + +.fa-cloudsmith:before { + content: "\f384"; } + +.fa-cloudversify:before { + content: "\f385"; } + +.fa-cocktail:before { + content: "\f561"; } + +.fa-code:before { + content: "\f121"; } + +.fa-code-branch:before { + content: "\f126"; } + +.fa-codepen:before { + content: "\f1cb"; } + +.fa-codiepie:before { + content: "\f284"; } + +.fa-coffee:before { + content: "\f0f4"; } + +.fa-cog:before { + content: "\f013"; } + +.fa-cogs:before { + content: "\f085"; } + +.fa-coins:before { + content: "\f51e"; } + +.fa-columns:before { + content: "\f0db"; } + +.fa-comment:before { + content: "\f075"; } + +.fa-comment-alt:before { + content: "\f27a"; } + +.fa-comment-dollar:before { + content: "\f651"; } + +.fa-comment-dots:before { + content: "\f4ad"; } + +.fa-comment-medical:before { + content: "\f7f5"; } + +.fa-comment-slash:before { + content: "\f4b3"; } + +.fa-comments:before { + content: "\f086"; } + +.fa-comments-dollar:before { + content: "\f653"; } + +.fa-compact-disc:before { + content: "\f51f"; } + +.fa-compass:before { + content: "\f14e"; } + +.fa-compress:before { + content: "\f066"; } + +.fa-compress-alt:before { + content: "\f422"; } + +.fa-compress-arrows-alt:before { + content: "\f78c"; } + +.fa-concierge-bell:before { + content: "\f562"; } + +.fa-confluence:before { + content: "\f78d"; } + +.fa-connectdevelop:before { + content: "\f20e"; } + +.fa-contao:before { + content: "\f26d"; } + +.fa-cookie:before { + content: "\f563"; } + +.fa-cookie-bite:before { + content: "\f564"; } + +.fa-copy:before { + content: "\f0c5"; } + +.fa-copyright:before { + content: "\f1f9"; } + +.fa-cotton-bureau:before { + content: "\f89e"; } + +.fa-couch:before { + content: "\f4b8"; } + +.fa-cpanel:before { + content: "\f388"; } + +.fa-creative-commons:before { + content: "\f25e"; } + +.fa-creative-commons-by:before { + content: "\f4e7"; } + +.fa-creative-commons-nc:before { + content: "\f4e8"; } + +.fa-creative-commons-nc-eu:before { + content: "\f4e9"; } + +.fa-creative-commons-nc-jp:before { + content: "\f4ea"; } + +.fa-creative-commons-nd:before { + content: "\f4eb"; } + +.fa-creative-commons-pd:before { + content: "\f4ec"; } + +.fa-creative-commons-pd-alt:before { + content: "\f4ed"; } + +.fa-creative-commons-remix:before { + content: "\f4ee"; } + +.fa-creative-commons-sa:before { + content: "\f4ef"; } + +.fa-creative-commons-sampling:before { + content: "\f4f0"; } + +.fa-creative-commons-sampling-plus:before { + content: "\f4f1"; } + +.fa-creative-commons-share:before { + content: "\f4f2"; } + +.fa-creative-commons-zero:before { + content: "\f4f3"; } + +.fa-credit-card:before { + content: "\f09d"; } + +.fa-critical-role:before { + content: "\f6c9"; } + +.fa-crop:before { + content: "\f125"; } + +.fa-crop-alt:before { + content: "\f565"; } + +.fa-cross:before { + content: "\f654"; } + +.fa-crosshairs:before { + content: "\f05b"; } + +.fa-crow:before { + content: "\f520"; } + +.fa-crown:before { + content: "\f521"; } + +.fa-crutch:before { + content: "\f7f7"; } + +.fa-css3:before { + content: "\f13c"; } + +.fa-css3-alt:before { + content: "\f38b"; } + +.fa-cube:before { + content: "\f1b2"; } + +.fa-cubes:before { + content: "\f1b3"; } + +.fa-cut:before { + content: "\f0c4"; } + +.fa-cuttlefish:before { + content: "\f38c"; } + +.fa-d-and-d:before { + content: "\f38d"; } + +.fa-d-and-d-beyond:before { + content: "\f6ca"; } + +.fa-dailymotion:before { + content: "\f952"; } + +.fa-dashcube:before { + content: "\f210"; } + +.fa-database:before { + content: "\f1c0"; } + +.fa-deaf:before { + content: "\f2a4"; } + +.fa-delicious:before { + content: "\f1a5"; } + +.fa-democrat:before { + content: "\f747"; } + +.fa-deploydog:before { + content: "\f38e"; } + +.fa-deskpro:before { + content: "\f38f"; } + +.fa-desktop:before { + content: "\f108"; } + +.fa-dev:before { + content: "\f6cc"; } + +.fa-deviantart:before { + content: "\f1bd"; } + +.fa-dharmachakra:before { + content: "\f655"; } + +.fa-dhl:before { + content: "\f790"; } + +.fa-diagnoses:before { + content: "\f470"; } + +.fa-diaspora:before { + content: "\f791"; } + +.fa-dice:before { + content: "\f522"; } + +.fa-dice-d20:before { + content: "\f6cf"; } + +.fa-dice-d6:before { + content: "\f6d1"; } + +.fa-dice-five:before { + content: "\f523"; } + +.fa-dice-four:before { + content: "\f524"; } + +.fa-dice-one:before { + content: "\f525"; } + +.fa-dice-six:before { + content: "\f526"; } + +.fa-dice-three:before { + content: "\f527"; } + +.fa-dice-two:before { + content: "\f528"; } + +.fa-digg:before { + content: "\f1a6"; } + +.fa-digital-ocean:before { + content: "\f391"; } + +.fa-digital-tachograph:before { + content: "\f566"; } + +.fa-directions:before { + content: "\f5eb"; } + +.fa-discord:before { + content: "\f392"; } + +.fa-discourse:before { + content: "\f393"; } + +.fa-divide:before { + content: "\f529"; } + +.fa-dizzy:before { + content: "\f567"; } + +.fa-dna:before { + content: "\f471"; } + +.fa-dochub:before { + content: "\f394"; } + +.fa-docker:before { + content: "\f395"; } + +.fa-dog:before { + content: "\f6d3"; } + +.fa-dollar-sign:before { + content: "\f155"; } + +.fa-dolly:before { + content: "\f472"; } + +.fa-dolly-flatbed:before { + content: "\f474"; } + +.fa-donate:before { + content: "\f4b9"; } + +.fa-door-closed:before { + content: "\f52a"; } + +.fa-door-open:before { + content: "\f52b"; } + +.fa-dot-circle:before { + content: "\f192"; } + +.fa-dove:before { + content: "\f4ba"; } + +.fa-download:before { + content: "\f019"; } + +.fa-draft2digital:before { + content: "\f396"; } + +.fa-drafting-compass:before { + content: "\f568"; } + +.fa-dragon:before { + content: "\f6d5"; } + +.fa-draw-polygon:before { + content: "\f5ee"; } + +.fa-dribbble:before { + content: "\f17d"; } + +.fa-dribbble-square:before { + content: "\f397"; } + +.fa-dropbox:before { + content: "\f16b"; } + +.fa-drum:before { + content: "\f569"; } + +.fa-drum-steelpan:before { + content: "\f56a"; } + +.fa-drumstick-bite:before { + content: "\f6d7"; } + +.fa-drupal:before { + content: "\f1a9"; } + +.fa-dumbbell:before { + content: "\f44b"; } + +.fa-dumpster:before { + content: "\f793"; } + +.fa-dumpster-fire:before { + content: "\f794"; } + +.fa-dungeon:before { + content: "\f6d9"; } + +.fa-dyalog:before { + content: "\f399"; } + +.fa-earlybirds:before { + content: "\f39a"; } + +.fa-ebay:before { + content: "\f4f4"; } + +.fa-edge:before { + content: "\f282"; } + +.fa-edit:before { + content: "\f044"; } + +.fa-egg:before { + content: "\f7fb"; } + +.fa-eject:before { + content: "\f052"; } + +.fa-elementor:before { + content: "\f430"; } + +.fa-ellipsis-h:before { + content: "\f141"; } + +.fa-ellipsis-v:before { + content: "\f142"; } + +.fa-ello:before { + content: "\f5f1"; } + +.fa-ember:before { + content: "\f423"; } + +.fa-empire:before { + content: "\f1d1"; } + +.fa-envelope:before { + content: "\f0e0"; } + +.fa-envelope-open:before { + content: "\f2b6"; } + +.fa-envelope-open-text:before { + content: "\f658"; } + +.fa-envelope-square:before { + content: "\f199"; } + +.fa-envira:before { + content: "\f299"; } + +.fa-equals:before { + content: "\f52c"; } + +.fa-eraser:before { + content: "\f12d"; } + +.fa-erlang:before { + content: "\f39d"; } + +.fa-ethereum:before { + content: "\f42e"; } + +.fa-ethernet:before { + content: "\f796"; } + +.fa-etsy:before { + content: "\f2d7"; } + +.fa-euro-sign:before { + content: "\f153"; } + +.fa-evernote:before { + content: "\f839"; } + +.fa-exchange-alt:before { + content: "\f362"; } + +.fa-exclamation:before { + content: "\f12a"; } + +.fa-exclamation-circle:before { + content: "\f06a"; } + +.fa-exclamation-triangle:before { + content: "\f071"; } + +.fa-expand:before { + content: "\f065"; } + +.fa-expand-alt:before { + content: "\f424"; } + +.fa-expand-arrows-alt:before { + content: "\f31e"; } + +.fa-expeditedssl:before { + content: "\f23e"; } + +.fa-external-link-alt:before { + content: "\f35d"; } + +.fa-external-link-square-alt:before { + content: "\f360"; } + +.fa-eye:before { + content: "\f06e"; } + +.fa-eye-dropper:before { + content: "\f1fb"; } + +.fa-eye-slash:before { + content: "\f070"; } + +.fa-facebook:before { + content: "\f09a"; } + +.fa-facebook-f:before { + content: "\f39e"; } + +.fa-facebook-messenger:before { + content: "\f39f"; } + +.fa-facebook-square:before { + content: "\f082"; } + +.fa-fan:before { + content: "\f863"; } + +.fa-fantasy-flight-games:before { + content: "\f6dc"; } + +.fa-fast-backward:before { + content: "\f049"; } + +.fa-fast-forward:before { + content: "\f050"; } + +.fa-fax:before { + content: "\f1ac"; } + +.fa-feather:before { + content: "\f52d"; } + +.fa-feather-alt:before { + content: "\f56b"; } + +.fa-fedex:before { + content: "\f797"; } + +.fa-fedora:before { + content: "\f798"; } + +.fa-female:before { + content: "\f182"; } + +.fa-fighter-jet:before { + content: "\f0fb"; } + +.fa-figma:before { + content: "\f799"; } + +.fa-file:before { + content: "\f15b"; } + +.fa-file-alt:before { + content: "\f15c"; } + +.fa-file-archive:before { + content: "\f1c6"; } + +.fa-file-audio:before { + content: "\f1c7"; } + +.fa-file-code:before { + content: "\f1c9"; } + +.fa-file-contract:before { + content: "\f56c"; } + +.fa-file-csv:before { + content: "\f6dd"; } + +.fa-file-download:before { + content: "\f56d"; } + +.fa-file-excel:before { + content: "\f1c3"; } + +.fa-file-export:before { + content: "\f56e"; } + +.fa-file-image:before { + content: "\f1c5"; } + +.fa-file-import:before { + content: "\f56f"; } + +.fa-file-invoice:before { + content: "\f570"; } + +.fa-file-invoice-dollar:before { + content: "\f571"; } + +.fa-file-medical:before { + content: "\f477"; } + +.fa-file-medical-alt:before { + content: "\f478"; } + +.fa-file-pdf:before { + content: "\f1c1"; } + +.fa-file-powerpoint:before { + content: "\f1c4"; } + +.fa-file-prescription:before { + content: "\f572"; } + +.fa-file-signature:before { + content: "\f573"; } + +.fa-file-upload:before { + content: "\f574"; } + +.fa-file-video:before { + content: "\f1c8"; } + +.fa-file-word:before { + content: "\f1c2"; } + +.fa-fill:before { + content: "\f575"; } + +.fa-fill-drip:before { + content: "\f576"; } + +.fa-film:before { + content: "\f008"; } + +.fa-filter:before { + content: "\f0b0"; } + +.fa-fingerprint:before { + content: "\f577"; } + +.fa-fire:before { + content: "\f06d"; } + +.fa-fire-alt:before { + content: "\f7e4"; } + +.fa-fire-extinguisher:before { + content: "\f134"; } + +.fa-firefox:before { + content: "\f269"; } + +.fa-firefox-browser:before { + content: "\f907"; } + +.fa-first-aid:before { + content: "\f479"; } + +.fa-first-order:before { + content: "\f2b0"; } + +.fa-first-order-alt:before { + content: "\f50a"; } + +.fa-firstdraft:before { + content: "\f3a1"; } + +.fa-fish:before { + content: "\f578"; } + +.fa-fist-raised:before { + content: "\f6de"; } + +.fa-flag:before { + content: "\f024"; } + +.fa-flag-checkered:before { + content: "\f11e"; } + +.fa-flag-usa:before { + content: "\f74d"; } + +.fa-flask:before { + content: "\f0c3"; } + +.fa-flickr:before { + content: "\f16e"; } + +.fa-flipboard:before { + content: "\f44d"; } + +.fa-flushed:before { + content: "\f579"; } + +.fa-fly:before { + content: "\f417"; } + +.fa-folder:before { + content: "\f07b"; } + +.fa-folder-minus:before { + content: "\f65d"; } + +.fa-folder-open:before { + content: "\f07c"; } + +.fa-folder-plus:before { + content: "\f65e"; } + +.fa-font:before { + content: "\f031"; } + +.fa-font-awesome:before { + content: "\f2b4"; } + +.fa-font-awesome-alt:before { + content: "\f35c"; } + +.fa-font-awesome-flag:before { + content: "\f425"; } + +.fa-font-awesome-logo-full:before { + content: "\f4e6"; } + +.fa-fonticons:before { + content: "\f280"; } + +.fa-fonticons-fi:before { + content: "\f3a2"; } + +.fa-football-ball:before { + content: "\f44e"; } + +.fa-fort-awesome:before { + content: "\f286"; } + +.fa-fort-awesome-alt:before { + content: "\f3a3"; } + +.fa-forumbee:before { + content: "\f211"; } + +.fa-forward:before { + content: "\f04e"; } + +.fa-foursquare:before { + content: "\f180"; } + +.fa-free-code-camp:before { + content: "\f2c5"; } + +.fa-freebsd:before { + content: "\f3a4"; } + +.fa-frog:before { + content: "\f52e"; } + +.fa-frown:before { + content: "\f119"; } + +.fa-frown-open:before { + content: "\f57a"; } + +.fa-fulcrum:before { + content: "\f50b"; } + +.fa-funnel-dollar:before { + content: "\f662"; } + +.fa-futbol:before { + content: "\f1e3"; } + +.fa-galactic-republic:before { + content: "\f50c"; } + +.fa-galactic-senate:before { + content: "\f50d"; } + +.fa-gamepad:before { + content: "\f11b"; } + +.fa-gas-pump:before { + content: "\f52f"; } + +.fa-gavel:before { + content: "\f0e3"; } + +.fa-gem:before { + content: "\f3a5"; } + +.fa-genderless:before { + content: "\f22d"; } + +.fa-get-pocket:before { + content: "\f265"; } + +.fa-gg:before { + content: "\f260"; } + +.fa-gg-circle:before { + content: "\f261"; } + +.fa-ghost:before { + content: "\f6e2"; } + +.fa-gift:before { + content: "\f06b"; } + +.fa-gifts:before { + content: "\f79c"; } + +.fa-git:before { + content: "\f1d3"; } + +.fa-git-alt:before { + content: "\f841"; } + +.fa-git-square:before { + content: "\f1d2"; } + +.fa-github:before { + content: "\f09b"; } + +.fa-github-alt:before { + content: "\f113"; } + +.fa-github-square:before { + content: "\f092"; } + +.fa-gitkraken:before { + content: "\f3a6"; } + +.fa-gitlab:before { + content: "\f296"; } + +.fa-gitter:before { + content: "\f426"; } + +.fa-glass-cheers:before { + content: "\f79f"; } + +.fa-glass-martini:before { + content: "\f000"; } + +.fa-glass-martini-alt:before { + content: "\f57b"; } + +.fa-glass-whiskey:before { + content: "\f7a0"; } + +.fa-glasses:before { + content: "\f530"; } + +.fa-glide:before { + content: "\f2a5"; } + +.fa-glide-g:before { + content: "\f2a6"; } + +.fa-globe:before { + content: "\f0ac"; } + +.fa-globe-africa:before { + content: "\f57c"; } + +.fa-globe-americas:before { + content: "\f57d"; } + +.fa-globe-asia:before { + content: "\f57e"; } + +.fa-globe-europe:before { + content: "\f7a2"; } + +.fa-gofore:before { + content: "\f3a7"; } + +.fa-golf-ball:before { + content: "\f450"; } + +.fa-goodreads:before { + content: "\f3a8"; } + +.fa-goodreads-g:before { + content: "\f3a9"; } + +.fa-google:before { + content: "\f1a0"; } + +.fa-google-drive:before { + content: "\f3aa"; } + +.fa-google-play:before { + content: "\f3ab"; } + +.fa-google-plus:before { + content: "\f2b3"; } + +.fa-google-plus-g:before { + content: "\f0d5"; } + +.fa-google-plus-square:before { + content: "\f0d4"; } + +.fa-google-wallet:before { + content: "\f1ee"; } + +.fa-gopuram:before { + content: "\f664"; } + +.fa-graduation-cap:before { + content: "\f19d"; } + +.fa-gratipay:before { + content: "\f184"; } + +.fa-grav:before { + content: "\f2d6"; } + +.fa-greater-than:before { + content: "\f531"; } + +.fa-greater-than-equal:before { + content: "\f532"; } + +.fa-grimace:before { + content: "\f57f"; } + +.fa-grin:before { + content: "\f580"; } + +.fa-grin-alt:before { + content: "\f581"; } + +.fa-grin-beam:before { + content: "\f582"; } + +.fa-grin-beam-sweat:before { + content: "\f583"; } + +.fa-grin-hearts:before { + content: "\f584"; } + +.fa-grin-squint:before { + content: "\f585"; } + +.fa-grin-squint-tears:before { + content: "\f586"; } + +.fa-grin-stars:before { + content: "\f587"; } + +.fa-grin-tears:before { + content: "\f588"; } + +.fa-grin-tongue:before { + content: "\f589"; } + +.fa-grin-tongue-squint:before { + content: "\f58a"; } + +.fa-grin-tongue-wink:before { + content: "\f58b"; } + +.fa-grin-wink:before { + content: "\f58c"; } + +.fa-grip-horizontal:before { + content: "\f58d"; } + +.fa-grip-lines:before { + content: "\f7a4"; } + +.fa-grip-lines-vertical:before { + content: "\f7a5"; } + +.fa-grip-vertical:before { + content: "\f58e"; } + +.fa-gripfire:before { + content: "\f3ac"; } + +.fa-grunt:before { + content: "\f3ad"; } + +.fa-guitar:before { + content: "\f7a6"; } + +.fa-gulp:before { + content: "\f3ae"; } + +.fa-h-square:before { + content: "\f0fd"; } + +.fa-hacker-news:before { + content: "\f1d4"; } + +.fa-hacker-news-square:before { + content: "\f3af"; } + +.fa-hackerrank:before { + content: "\f5f7"; } + +.fa-hamburger:before { + content: "\f805"; } + +.fa-hammer:before { + content: "\f6e3"; } + +.fa-hamsa:before { + content: "\f665"; } + +.fa-hand-holding:before { + content: "\f4bd"; } + +.fa-hand-holding-heart:before { + content: "\f4be"; } + +.fa-hand-holding-usd:before { + content: "\f4c0"; } + +.fa-hand-lizard:before { + content: "\f258"; } + +.fa-hand-middle-finger:before { + content: "\f806"; } + +.fa-hand-paper:before { + content: "\f256"; } + +.fa-hand-peace:before { + content: "\f25b"; } + +.fa-hand-point-down:before { + content: "\f0a7"; } + +.fa-hand-point-left:before { + content: "\f0a5"; } + +.fa-hand-point-right:before { + content: "\f0a4"; } + +.fa-hand-point-up:before { + content: "\f0a6"; } + +.fa-hand-pointer:before { + content: "\f25a"; } + +.fa-hand-rock:before { + content: "\f255"; } + +.fa-hand-scissors:before { + content: "\f257"; } + +.fa-hand-spock:before { + content: "\f259"; } + +.fa-hands:before { + content: "\f4c2"; } + +.fa-hands-helping:before { + content: "\f4c4"; } + +.fa-handshake:before { + content: "\f2b5"; } + +.fa-hanukiah:before { + content: "\f6e6"; } + +.fa-hard-hat:before { + content: "\f807"; } + +.fa-hashtag:before { + content: "\f292"; } + +.fa-hat-cowboy:before { + content: "\f8c0"; } + +.fa-hat-cowboy-side:before { + content: "\f8c1"; } + +.fa-hat-wizard:before { + content: "\f6e8"; } + +.fa-hdd:before { + content: "\f0a0"; } + +.fa-heading:before { + content: "\f1dc"; } + +.fa-headphones:before { + content: "\f025"; } + +.fa-headphones-alt:before { + content: "\f58f"; } + +.fa-headset:before { + content: "\f590"; } + +.fa-heart:before { + content: "\f004"; } + +.fa-heart-broken:before { + content: "\f7a9"; } + +.fa-heartbeat:before { + content: "\f21e"; } + +.fa-helicopter:before { + content: "\f533"; } + +.fa-highlighter:before { + content: "\f591"; } + +.fa-hiking:before { + content: "\f6ec"; } + +.fa-hippo:before { + content: "\f6ed"; } + +.fa-hips:before { + content: "\f452"; } + +.fa-hire-a-helper:before { + content: "\f3b0"; } + +.fa-history:before { + content: "\f1da"; } + +.fa-hockey-puck:before { + content: "\f453"; } + +.fa-holly-berry:before { + content: "\f7aa"; } + +.fa-home:before { + content: "\f015"; } + +.fa-hooli:before { + content: "\f427"; } + +.fa-hornbill:before { + content: "\f592"; } + +.fa-horse:before { + content: "\f6f0"; } + +.fa-horse-head:before { + content: "\f7ab"; } + +.fa-hospital:before { + content: "\f0f8"; } + +.fa-hospital-alt:before { + content: "\f47d"; } + +.fa-hospital-symbol:before { + content: "\f47e"; } + +.fa-hot-tub:before { + content: "\f593"; } + +.fa-hotdog:before { + content: "\f80f"; } + +.fa-hotel:before { + content: "\f594"; } + +.fa-hotjar:before { + content: "\f3b1"; } + +.fa-hourglass:before { + content: "\f254"; } + +.fa-hourglass-end:before { + content: "\f253"; } + +.fa-hourglass-half:before { + content: "\f252"; } + +.fa-hourglass-start:before { + content: "\f251"; } + +.fa-house-damage:before { + content: "\f6f1"; } + +.fa-houzz:before { + content: "\f27c"; } + +.fa-hryvnia:before { + content: "\f6f2"; } + +.fa-html5:before { + content: "\f13b"; } + +.fa-hubspot:before { + content: "\f3b2"; } + +.fa-i-cursor:before { + content: "\f246"; } + +.fa-ice-cream:before { + content: "\f810"; } + +.fa-icicles:before { + content: "\f7ad"; } + +.fa-icons:before { + content: "\f86d"; } + +.fa-id-badge:before { + content: "\f2c1"; } + +.fa-id-card:before { + content: "\f2c2"; } + +.fa-id-card-alt:before { + content: "\f47f"; } + +.fa-ideal:before { + content: "\f913"; } + +.fa-igloo:before { + content: "\f7ae"; } + +.fa-image:before { + content: "\f03e"; } + +.fa-images:before { + content: "\f302"; } + +.fa-imdb:before { + content: "\f2d8"; } + +.fa-inbox:before { + content: "\f01c"; } + +.fa-indent:before { + content: "\f03c"; } + +.fa-industry:before { + content: "\f275"; } + +.fa-infinity:before { + content: "\f534"; } + +.fa-info:before { + content: "\f129"; } + +.fa-info-circle:before { + content: "\f05a"; } + +.fa-instagram:before { + content: "\f16d"; } + +.fa-instagram-square:before { + content: "\f955"; } + +.fa-intercom:before { + content: "\f7af"; } + +.fa-internet-explorer:before { + content: "\f26b"; } + +.fa-invision:before { + content: "\f7b0"; } + +.fa-ioxhost:before { + content: "\f208"; } + +.fa-italic:before { + content: "\f033"; } + +.fa-itch-io:before { + content: "\f83a"; } + +.fa-itunes:before { + content: "\f3b4"; } + +.fa-itunes-note:before { + content: "\f3b5"; } + +.fa-java:before { + content: "\f4e4"; } + +.fa-jedi:before { + content: "\f669"; } + +.fa-jedi-order:before { + content: "\f50e"; } + +.fa-jenkins:before { + content: "\f3b6"; } + +.fa-jira:before { + content: "\f7b1"; } + +.fa-joget:before { + content: "\f3b7"; } + +.fa-joint:before { + content: "\f595"; } + +.fa-joomla:before { + content: "\f1aa"; } + +.fa-journal-whills:before { + content: "\f66a"; } + +.fa-js:before { + content: "\f3b8"; } + +.fa-js-square:before { + content: "\f3b9"; } + +.fa-jsfiddle:before { + content: "\f1cc"; } + +.fa-kaaba:before { + content: "\f66b"; } + +.fa-kaggle:before { + content: "\f5fa"; } + +.fa-key:before { + content: "\f084"; } + +.fa-keybase:before { + content: "\f4f5"; } + +.fa-keyboard:before { + content: "\f11c"; } + +.fa-keycdn:before { + content: "\f3ba"; } + +.fa-khanda:before { + content: "\f66d"; } + +.fa-kickstarter:before { + content: "\f3bb"; } + +.fa-kickstarter-k:before { + content: "\f3bc"; } + +.fa-kiss:before { + content: "\f596"; } + +.fa-kiss-beam:before { + content: "\f597"; } + +.fa-kiss-wink-heart:before { + content: "\f598"; } + +.fa-kiwi-bird:before { + content: "\f535"; } + +.fa-korvue:before { + content: "\f42f"; } + +.fa-landmark:before { + content: "\f66f"; } + +.fa-language:before { + content: "\f1ab"; } + +.fa-laptop:before { + content: "\f109"; } + +.fa-laptop-code:before { + content: "\f5fc"; } + +.fa-laptop-medical:before { + content: "\f812"; } + +.fa-laravel:before { + content: "\f3bd"; } + +.fa-lastfm:before { + content: "\f202"; } + +.fa-lastfm-square:before { + content: "\f203"; } + +.fa-laugh:before { + content: "\f599"; } + +.fa-laugh-beam:before { + content: "\f59a"; } + +.fa-laugh-squint:before { + content: "\f59b"; } + +.fa-laugh-wink:before { + content: "\f59c"; } + +.fa-layer-group:before { + content: "\f5fd"; } + +.fa-leaf:before { + content: "\f06c"; } + +.fa-leanpub:before { + content: "\f212"; } + +.fa-lemon:before { + content: "\f094"; } + +.fa-less:before { + content: "\f41d"; } + +.fa-less-than:before { + content: "\f536"; } + +.fa-less-than-equal:before { + content: "\f537"; } + +.fa-level-down-alt:before { + content: "\f3be"; } + +.fa-level-up-alt:before { + content: "\f3bf"; } + +.fa-life-ring:before { + content: "\f1cd"; } + +.fa-lightbulb:before { + content: "\f0eb"; } + +.fa-line:before { + content: "\f3c0"; } + +.fa-link:before { + content: "\f0c1"; } + +.fa-linkedin:before { + content: "\f08c"; } + +.fa-linkedin-in:before { + content: "\f0e1"; } + +.fa-linode:before { + content: "\f2b8"; } + +.fa-linux:before { + content: "\f17c"; } + +.fa-lira-sign:before { + content: "\f195"; } + +.fa-list:before { + content: "\f03a"; } + +.fa-list-alt:before { + content: "\f022"; } + +.fa-list-ol:before { + content: "\f0cb"; } + +.fa-list-ul:before { + content: "\f0ca"; } + +.fa-location-arrow:before { + content: "\f124"; } + +.fa-lock:before { + content: "\f023"; } + +.fa-lock-open:before { + content: "\f3c1"; } + +.fa-long-arrow-alt-down:before { + content: "\f309"; } + +.fa-long-arrow-alt-left:before { + content: "\f30a"; } + +.fa-long-arrow-alt-right:before { + content: "\f30b"; } + +.fa-long-arrow-alt-up:before { + content: "\f30c"; } + +.fa-low-vision:before { + content: "\f2a8"; } + +.fa-luggage-cart:before { + content: "\f59d"; } + +.fa-lyft:before { + content: "\f3c3"; } + +.fa-magento:before { + content: "\f3c4"; } + +.fa-magic:before { + content: "\f0d0"; } + +.fa-magnet:before { + content: "\f076"; } + +.fa-mail-bulk:before { + content: "\f674"; } + +.fa-mailchimp:before { + content: "\f59e"; } + +.fa-male:before { + content: "\f183"; } + +.fa-mandalorian:before { + content: "\f50f"; } + +.fa-map:before { + content: "\f279"; } + +.fa-map-marked:before { + content: "\f59f"; } + +.fa-map-marked-alt:before { + content: "\f5a0"; } + +.fa-map-marker:before { + content: "\f041"; } + +.fa-map-marker-alt:before { + content: "\f3c5"; } + +.fa-map-pin:before { + content: "\f276"; } + +.fa-map-signs:before { + content: "\f277"; } + +.fa-markdown:before { + content: "\f60f"; } + +.fa-marker:before { + content: "\f5a1"; } + +.fa-mars:before { + content: "\f222"; } + +.fa-mars-double:before { + content: "\f227"; } + +.fa-mars-stroke:before { + content: "\f229"; } + +.fa-mars-stroke-h:before { + content: "\f22b"; } + +.fa-mars-stroke-v:before { + content: "\f22a"; } + +.fa-mask:before { + content: "\f6fa"; } + +.fa-mastodon:before { + content: "\f4f6"; } + +.fa-maxcdn:before { + content: "\f136"; } + +.fa-mdb:before { + content: "\f8ca"; } + +.fa-medal:before { + content: "\f5a2"; } + +.fa-medapps:before { + content: "\f3c6"; } + +.fa-medium:before { + content: "\f23a"; } + +.fa-medium-m:before { + content: "\f3c7"; } + +.fa-medkit:before { + content: "\f0fa"; } + +.fa-medrt:before { + content: "\f3c8"; } + +.fa-meetup:before { + content: "\f2e0"; } + +.fa-megaport:before { + content: "\f5a3"; } + +.fa-meh:before { + content: "\f11a"; } + +.fa-meh-blank:before { + content: "\f5a4"; } + +.fa-meh-rolling-eyes:before { + content: "\f5a5"; } + +.fa-memory:before { + content: "\f538"; } + +.fa-mendeley:before { + content: "\f7b3"; } + +.fa-menorah:before { + content: "\f676"; } + +.fa-mercury:before { + content: "\f223"; } + +.fa-meteor:before { + content: "\f753"; } + +.fa-microblog:before { + content: "\f91a"; } + +.fa-microchip:before { + content: "\f2db"; } + +.fa-microphone:before { + content: "\f130"; } + +.fa-microphone-alt:before { + content: "\f3c9"; } + +.fa-microphone-alt-slash:before { + content: "\f539"; } + +.fa-microphone-slash:before { + content: "\f131"; } + +.fa-microscope:before { + content: "\f610"; } + +.fa-microsoft:before { + content: "\f3ca"; } + +.fa-minus:before { + content: "\f068"; } + +.fa-minus-circle:before { + content: "\f056"; } + +.fa-minus-square:before { + content: "\f146"; } + +.fa-mitten:before { + content: "\f7b5"; } + +.fa-mix:before { + content: "\f3cb"; } + +.fa-mixcloud:before { + content: "\f289"; } + +.fa-mixer:before { + content: "\f956"; } + +.fa-mizuni:before { + content: "\f3cc"; } + +.fa-mobile:before { + content: "\f10b"; } + +.fa-mobile-alt:before { + content: "\f3cd"; } + +.fa-modx:before { + content: "\f285"; } + +.fa-monero:before { + content: "\f3d0"; } + +.fa-money-bill:before { + content: "\f0d6"; } + +.fa-money-bill-alt:before { + content: "\f3d1"; } + +.fa-money-bill-wave:before { + content: "\f53a"; } + +.fa-money-bill-wave-alt:before { + content: "\f53b"; } + +.fa-money-check:before { + content: "\f53c"; } + +.fa-money-check-alt:before { + content: "\f53d"; } + +.fa-monument:before { + content: "\f5a6"; } + +.fa-moon:before { + content: "\f186"; } + +.fa-mortar-pestle:before { + content: "\f5a7"; } + +.fa-mosque:before { + content: "\f678"; } + +.fa-motorcycle:before { + content: "\f21c"; } + +.fa-mountain:before { + content: "\f6fc"; } + +.fa-mouse:before { + content: "\f8cc"; } + +.fa-mouse-pointer:before { + content: "\f245"; } + +.fa-mug-hot:before { + content: "\f7b6"; } + +.fa-music:before { + content: "\f001"; } + +.fa-napster:before { + content: "\f3d2"; } + +.fa-neos:before { + content: "\f612"; } + +.fa-network-wired:before { + content: "\f6ff"; } + +.fa-neuter:before { + content: "\f22c"; } + +.fa-newspaper:before { + content: "\f1ea"; } + +.fa-nimblr:before { + content: "\f5a8"; } + +.fa-node:before { + content: "\f419"; } + +.fa-node-js:before { + content: "\f3d3"; } + +.fa-not-equal:before { + content: "\f53e"; } + +.fa-notes-medical:before { + content: "\f481"; } + +.fa-npm:before { + content: "\f3d4"; } + +.fa-ns8:before { + content: "\f3d5"; } + +.fa-nutritionix:before { + content: "\f3d6"; } + +.fa-object-group:before { + content: "\f247"; } + +.fa-object-ungroup:before { + content: "\f248"; } + +.fa-odnoklassniki:before { + content: "\f263"; } + +.fa-odnoklassniki-square:before { + content: "\f264"; } + +.fa-oil-can:before { + content: "\f613"; } + +.fa-old-republic:before { + content: "\f510"; } + +.fa-om:before { + content: "\f679"; } + +.fa-opencart:before { + content: "\f23d"; } + +.fa-openid:before { + content: "\f19b"; } + +.fa-opera:before { + content: "\f26a"; } + +.fa-optin-monster:before { + content: "\f23c"; } + +.fa-orcid:before { + content: "\f8d2"; } + +.fa-osi:before { + content: "\f41a"; } + +.fa-otter:before { + content: "\f700"; } + +.fa-outdent:before { + content: "\f03b"; } + +.fa-page4:before { + content: "\f3d7"; } + +.fa-pagelines:before { + content: "\f18c"; } + +.fa-pager:before { + content: "\f815"; } + +.fa-paint-brush:before { + content: "\f1fc"; } + +.fa-paint-roller:before { + content: "\f5aa"; } + +.fa-palette:before { + content: "\f53f"; } + +.fa-palfed:before { + content: "\f3d8"; } + +.fa-pallet:before { + content: "\f482"; } + +.fa-paper-plane:before { + content: "\f1d8"; } + +.fa-paperclip:before { + content: "\f0c6"; } + +.fa-parachute-box:before { + content: "\f4cd"; } + +.fa-paragraph:before { + content: "\f1dd"; } + +.fa-parking:before { + content: "\f540"; } + +.fa-passport:before { + content: "\f5ab"; } + +.fa-pastafarianism:before { + content: "\f67b"; } + +.fa-paste:before { + content: "\f0ea"; } + +.fa-patreon:before { + content: "\f3d9"; } + +.fa-pause:before { + content: "\f04c"; } + +.fa-pause-circle:before { + content: "\f28b"; } + +.fa-paw:before { + content: "\f1b0"; } + +.fa-paypal:before { + content: "\f1ed"; } + +.fa-peace:before { + content: "\f67c"; } + +.fa-pen:before { + content: "\f304"; } + +.fa-pen-alt:before { + content: "\f305"; } + +.fa-pen-fancy:before { + content: "\f5ac"; } + +.fa-pen-nib:before { + content: "\f5ad"; } + +.fa-pen-square:before { + content: "\f14b"; } + +.fa-pencil-alt:before { + content: "\f303"; } + +.fa-pencil-ruler:before { + content: "\f5ae"; } + +.fa-penny-arcade:before { + content: "\f704"; } + +.fa-people-carry:before { + content: "\f4ce"; } + +.fa-pepper-hot:before { + content: "\f816"; } + +.fa-percent:before { + content: "\f295"; } + +.fa-percentage:before { + content: "\f541"; } + +.fa-periscope:before { + content: "\f3da"; } + +.fa-person-booth:before { + content: "\f756"; } + +.fa-phabricator:before { + content: "\f3db"; } + +.fa-phoenix-framework:before { + content: "\f3dc"; } + +.fa-phoenix-squadron:before { + content: "\f511"; } + +.fa-phone:before { + content: "\f095"; } + +.fa-phone-alt:before { + content: "\f879"; } + +.fa-phone-slash:before { + content: "\f3dd"; } + +.fa-phone-square:before { + content: "\f098"; } + +.fa-phone-square-alt:before { + content: "\f87b"; } + +.fa-phone-volume:before { + content: "\f2a0"; } + +.fa-photo-video:before { + content: "\f87c"; } + +.fa-php:before { + content: "\f457"; } + +.fa-pied-piper:before { + content: "\f2ae"; } + +.fa-pied-piper-alt:before { + content: "\f1a8"; } + +.fa-pied-piper-hat:before { + content: "\f4e5"; } + +.fa-pied-piper-pp:before { + content: "\f1a7"; } + +.fa-pied-piper-square:before { + content: "\f91e"; } + +.fa-piggy-bank:before { + content: "\f4d3"; } + +.fa-pills:before { + content: "\f484"; } + +.fa-pinterest:before { + content: "\f0d2"; } + +.fa-pinterest-p:before { + content: "\f231"; } + +.fa-pinterest-square:before { + content: "\f0d3"; } + +.fa-pizza-slice:before { + content: "\f818"; } + +.fa-place-of-worship:before { + content: "\f67f"; } + +.fa-plane:before { + content: "\f072"; } + +.fa-plane-arrival:before { + content: "\f5af"; } + +.fa-plane-departure:before { + content: "\f5b0"; } + +.fa-play:before { + content: "\f04b"; } + +.fa-play-circle:before { + content: "\f144"; } + +.fa-playstation:before { + content: "\f3df"; } + +.fa-plug:before { + content: "\f1e6"; } + +.fa-plus:before { + content: "\f067"; } + +.fa-plus-circle:before { + content: "\f055"; } + +.fa-plus-square:before { + content: "\f0fe"; } + +.fa-podcast:before { + content: "\f2ce"; } + +.fa-poll:before { + content: "\f681"; } + +.fa-poll-h:before { + content: "\f682"; } + +.fa-poo:before { + content: "\f2fe"; } + +.fa-poo-storm:before { + content: "\f75a"; } + +.fa-poop:before { + content: "\f619"; } + +.fa-portrait:before { + content: "\f3e0"; } + +.fa-pound-sign:before { + content: "\f154"; } + +.fa-power-off:before { + content: "\f011"; } + +.fa-pray:before { + content: "\f683"; } + +.fa-praying-hands:before { + content: "\f684"; } + +.fa-prescription:before { + content: "\f5b1"; } + +.fa-prescription-bottle:before { + content: "\f485"; } + +.fa-prescription-bottle-alt:before { + content: "\f486"; } + +.fa-print:before { + content: "\f02f"; } + +.fa-procedures:before { + content: "\f487"; } + +.fa-product-hunt:before { + content: "\f288"; } + +.fa-project-diagram:before { + content: "\f542"; } + +.fa-pushed:before { + content: "\f3e1"; } + +.fa-puzzle-piece:before { + content: "\f12e"; } + +.fa-python:before { + content: "\f3e2"; } + +.fa-qq:before { + content: "\f1d6"; } + +.fa-qrcode:before { + content: "\f029"; } + +.fa-question:before { + content: "\f128"; } + +.fa-question-circle:before { + content: "\f059"; } + +.fa-quidditch:before { + content: "\f458"; } + +.fa-quinscape:before { + content: "\f459"; } + +.fa-quora:before { + content: "\f2c4"; } + +.fa-quote-left:before { + content: "\f10d"; } + +.fa-quote-right:before { + content: "\f10e"; } + +.fa-quran:before { + content: "\f687"; } + +.fa-r-project:before { + content: "\f4f7"; } + +.fa-radiation:before { + content: "\f7b9"; } + +.fa-radiation-alt:before { + content: "\f7ba"; } + +.fa-rainbow:before { + content: "\f75b"; } + +.fa-random:before { + content: "\f074"; } + +.fa-raspberry-pi:before { + content: "\f7bb"; } + +.fa-ravelry:before { + content: "\f2d9"; } + +.fa-react:before { + content: "\f41b"; } + +.fa-reacteurope:before { + content: "\f75d"; } + +.fa-readme:before { + content: "\f4d5"; } + +.fa-rebel:before { + content: "\f1d0"; } + +.fa-receipt:before { + content: "\f543"; } + +.fa-record-vinyl:before { + content: "\f8d9"; } + +.fa-recycle:before { + content: "\f1b8"; } + +.fa-red-river:before { + content: "\f3e3"; } + +.fa-reddit:before { + content: "\f1a1"; } + +.fa-reddit-alien:before { + content: "\f281"; } + +.fa-reddit-square:before { + content: "\f1a2"; } + +.fa-redhat:before { + content: "\f7bc"; } + +.fa-redo:before { + content: "\f01e"; } + +.fa-redo-alt:before { + content: "\f2f9"; } + +.fa-registered:before { + content: "\f25d"; } + +.fa-remove-format:before { + content: "\f87d"; } + +.fa-renren:before { + content: "\f18b"; } + +.fa-reply:before { + content: "\f3e5"; } + +.fa-reply-all:before { + content: "\f122"; } + +.fa-replyd:before { + content: "\f3e6"; } + +.fa-republican:before { + content: "\f75e"; } + +.fa-researchgate:before { + content: "\f4f8"; } + +.fa-resolving:before { + content: "\f3e7"; } + +.fa-restroom:before { + content: "\f7bd"; } + +.fa-retweet:before { + content: "\f079"; } + +.fa-rev:before { + content: "\f5b2"; } + +.fa-ribbon:before { + content: "\f4d6"; } + +.fa-ring:before { + content: "\f70b"; } + +.fa-road:before { + content: "\f018"; } + +.fa-robot:before { + content: "\f544"; } + +.fa-rocket:before { + content: "\f135"; } + +.fa-rocketchat:before { + content: "\f3e8"; } + +.fa-rockrms:before { + content: "\f3e9"; } + +.fa-route:before { + content: "\f4d7"; } + +.fa-rss:before { + content: "\f09e"; } + +.fa-rss-square:before { + content: "\f143"; } + +.fa-ruble-sign:before { + content: "\f158"; } + +.fa-ruler:before { + content: "\f545"; } + +.fa-ruler-combined:before { + content: "\f546"; } + +.fa-ruler-horizontal:before { + content: "\f547"; } + +.fa-ruler-vertical:before { + content: "\f548"; } + +.fa-running:before { + content: "\f70c"; } + +.fa-rupee-sign:before { + content: "\f156"; } + +.fa-sad-cry:before { + content: "\f5b3"; } + +.fa-sad-tear:before { + content: "\f5b4"; } + +.fa-safari:before { + content: "\f267"; } + +.fa-salesforce:before { + content: "\f83b"; } + +.fa-sass:before { + content: "\f41e"; } + +.fa-satellite:before { + content: "\f7bf"; } + +.fa-satellite-dish:before { + content: "\f7c0"; } + +.fa-save:before { + content: "\f0c7"; } + +.fa-schlix:before { + content: "\f3ea"; } + +.fa-school:before { + content: "\f549"; } + +.fa-screwdriver:before { + content: "\f54a"; } + +.fa-scribd:before { + content: "\f28a"; } + +.fa-scroll:before { + content: "\f70e"; } + +.fa-sd-card:before { + content: "\f7c2"; } + +.fa-search:before { + content: "\f002"; } + +.fa-search-dollar:before { + content: "\f688"; } + +.fa-search-location:before { + content: "\f689"; } + +.fa-search-minus:before { + content: "\f010"; } + +.fa-search-plus:before { + content: "\f00e"; } + +.fa-searchengin:before { + content: "\f3eb"; } + +.fa-seedling:before { + content: "\f4d8"; } + +.fa-sellcast:before { + content: "\f2da"; } + +.fa-sellsy:before { + content: "\f213"; } + +.fa-server:before { + content: "\f233"; } + +.fa-servicestack:before { + content: "\f3ec"; } + +.fa-shapes:before { + content: "\f61f"; } + +.fa-share:before { + content: "\f064"; } + +.fa-share-alt:before { + content: "\f1e0"; } + +.fa-share-alt-square:before { + content: "\f1e1"; } + +.fa-share-square:before { + content: "\f14d"; } + +.fa-shekel-sign:before { + content: "\f20b"; } + +.fa-shield-alt:before { + content: "\f3ed"; } + +.fa-ship:before { + content: "\f21a"; } + +.fa-shipping-fast:before { + content: "\f48b"; } + +.fa-shirtsinbulk:before { + content: "\f214"; } + +.fa-shoe-prints:before { + content: "\f54b"; } + +.fa-shopify:before { + content: "\f957"; } + +.fa-shopping-bag:before { + content: "\f290"; } + +.fa-shopping-basket:before { + content: "\f291"; } + +.fa-shopping-cart:before { + content: "\f07a"; } + +.fa-shopware:before { + content: "\f5b5"; } + +.fa-shower:before { + content: "\f2cc"; } + +.fa-shuttle-van:before { + content: "\f5b6"; } + +.fa-sign:before { + content: "\f4d9"; } + +.fa-sign-in-alt:before { + content: "\f2f6"; } + +.fa-sign-language:before { + content: "\f2a7"; } + +.fa-sign-out-alt:before { + content: "\f2f5"; } + +.fa-signal:before { + content: "\f012"; } + +.fa-signature:before { + content: "\f5b7"; } + +.fa-sim-card:before { + content: "\f7c4"; } + +.fa-simplybuilt:before { + content: "\f215"; } + +.fa-sistrix:before { + content: "\f3ee"; } + +.fa-sitemap:before { + content: "\f0e8"; } + +.fa-sith:before { + content: "\f512"; } + +.fa-skating:before { + content: "\f7c5"; } + +.fa-sketch:before { + content: "\f7c6"; } + +.fa-skiing:before { + content: "\f7c9"; } + +.fa-skiing-nordic:before { + content: "\f7ca"; } + +.fa-skull:before { + content: "\f54c"; } + +.fa-skull-crossbones:before { + content: "\f714"; } + +.fa-skyatlas:before { + content: "\f216"; } + +.fa-skype:before { + content: "\f17e"; } + +.fa-slack:before { + content: "\f198"; } + +.fa-slack-hash:before { + content: "\f3ef"; } + +.fa-slash:before { + content: "\f715"; } + +.fa-sleigh:before { + content: "\f7cc"; } + +.fa-sliders-h:before { + content: "\f1de"; } + +.fa-slideshare:before { + content: "\f1e7"; } + +.fa-smile:before { + content: "\f118"; } + +.fa-smile-beam:before { + content: "\f5b8"; } + +.fa-smile-wink:before { + content: "\f4da"; } + +.fa-smog:before { + content: "\f75f"; } + +.fa-smoking:before { + content: "\f48d"; } + +.fa-smoking-ban:before { + content: "\f54d"; } + +.fa-sms:before { + content: "\f7cd"; } + +.fa-snapchat:before { + content: "\f2ab"; } + +.fa-snapchat-ghost:before { + content: "\f2ac"; } + +.fa-snapchat-square:before { + content: "\f2ad"; } + +.fa-snowboarding:before { + content: "\f7ce"; } + +.fa-snowflake:before { + content: "\f2dc"; } + +.fa-snowman:before { + content: "\f7d0"; } + +.fa-snowplow:before { + content: "\f7d2"; } + +.fa-socks:before { + content: "\f696"; } + +.fa-solar-panel:before { + content: "\f5ba"; } + +.fa-sort:before { + content: "\f0dc"; } + +.fa-sort-alpha-down:before { + content: "\f15d"; } + +.fa-sort-alpha-down-alt:before { + content: "\f881"; } + +.fa-sort-alpha-up:before { + content: "\f15e"; } + +.fa-sort-alpha-up-alt:before { + content: "\f882"; } + +.fa-sort-amount-down:before { + content: "\f160"; } + +.fa-sort-amount-down-alt:before { + content: "\f884"; } + +.fa-sort-amount-up:before { + content: "\f161"; } + +.fa-sort-amount-up-alt:before { + content: "\f885"; } + +.fa-sort-down:before { + content: "\f0dd"; } + +.fa-sort-numeric-down:before { + content: "\f162"; } + +.fa-sort-numeric-down-alt:before { + content: "\f886"; } + +.fa-sort-numeric-up:before { + content: "\f163"; } + +.fa-sort-numeric-up-alt:before { + content: "\f887"; } + +.fa-sort-up:before { + content: "\f0de"; } + +.fa-soundcloud:before { + content: "\f1be"; } + +.fa-sourcetree:before { + content: "\f7d3"; } + +.fa-spa:before { + content: "\f5bb"; } + +.fa-space-shuttle:before { + content: "\f197"; } + +.fa-speakap:before { + content: "\f3f3"; } + +.fa-speaker-deck:before { + content: "\f83c"; } + +.fa-spell-check:before { + content: "\f891"; } + +.fa-spider:before { + content: "\f717"; } + +.fa-spinner:before { + content: "\f110"; } + +.fa-splotch:before { + content: "\f5bc"; } + +.fa-spotify:before { + content: "\f1bc"; } + +.fa-spray-can:before { + content: "\f5bd"; } + +.fa-square:before { + content: "\f0c8"; } + +.fa-square-full:before { + content: "\f45c"; } + +.fa-square-root-alt:before { + content: "\f698"; } + +.fa-squarespace:before { + content: "\f5be"; } + +.fa-stack-exchange:before { + content: "\f18d"; } + +.fa-stack-overflow:before { + content: "\f16c"; } + +.fa-stackpath:before { + content: "\f842"; } + +.fa-stamp:before { + content: "\f5bf"; } + +.fa-star:before { + content: "\f005"; } + +.fa-star-and-crescent:before { + content: "\f699"; } + +.fa-star-half:before { + content: "\f089"; } + +.fa-star-half-alt:before { + content: "\f5c0"; } + +.fa-star-of-david:before { + content: "\f69a"; } + +.fa-star-of-life:before { + content: "\f621"; } + +.fa-staylinked:before { + content: "\f3f5"; } + +.fa-steam:before { + content: "\f1b6"; } + +.fa-steam-square:before { + content: "\f1b7"; } + +.fa-steam-symbol:before { + content: "\f3f6"; } + +.fa-step-backward:before { + content: "\f048"; } + +.fa-step-forward:before { + content: "\f051"; } + +.fa-stethoscope:before { + content: "\f0f1"; } + +.fa-sticker-mule:before { + content: "\f3f7"; } + +.fa-sticky-note:before { + content: "\f249"; } + +.fa-stop:before { + content: "\f04d"; } + +.fa-stop-circle:before { + content: "\f28d"; } + +.fa-stopwatch:before { + content: "\f2f2"; } + +.fa-store:before { + content: "\f54e"; } + +.fa-store-alt:before { + content: "\f54f"; } + +.fa-strava:before { + content: "\f428"; } + +.fa-stream:before { + content: "\f550"; } + +.fa-street-view:before { + content: "\f21d"; } + +.fa-strikethrough:before { + content: "\f0cc"; } + +.fa-stripe:before { + content: "\f429"; } + +.fa-stripe-s:before { + content: "\f42a"; } + +.fa-stroopwafel:before { + content: "\f551"; } + +.fa-studiovinari:before { + content: "\f3f8"; } + +.fa-stumbleupon:before { + content: "\f1a4"; } + +.fa-stumbleupon-circle:before { + content: "\f1a3"; } + +.fa-subscript:before { + content: "\f12c"; } + +.fa-subway:before { + content: "\f239"; } + +.fa-suitcase:before { + content: "\f0f2"; } + +.fa-suitcase-rolling:before { + content: "\f5c1"; } + +.fa-sun:before { + content: "\f185"; } + +.fa-superpowers:before { + content: "\f2dd"; } + +.fa-superscript:before { + content: "\f12b"; } + +.fa-supple:before { + content: "\f3f9"; } + +.fa-surprise:before { + content: "\f5c2"; } + +.fa-suse:before { + content: "\f7d6"; } + +.fa-swatchbook:before { + content: "\f5c3"; } + +.fa-swift:before { + content: "\f8e1"; } + +.fa-swimmer:before { + content: "\f5c4"; } + +.fa-swimming-pool:before { + content: "\f5c5"; } + +.fa-symfony:before { + content: "\f83d"; } + +.fa-synagogue:before { + content: "\f69b"; } + +.fa-sync:before { + content: "\f021"; } + +.fa-sync-alt:before { + content: "\f2f1"; } + +.fa-syringe:before { + content: "\f48e"; } + +.fa-table:before { + content: "\f0ce"; } + +.fa-table-tennis:before { + content: "\f45d"; } + +.fa-tablet:before { + content: "\f10a"; } + +.fa-tablet-alt:before { + content: "\f3fa"; } + +.fa-tablets:before { + content: "\f490"; } + +.fa-tachometer-alt:before { + content: "\f3fd"; } + +.fa-tag:before { + content: "\f02b"; } + +.fa-tags:before { + content: "\f02c"; } + +.fa-tape:before { + content: "\f4db"; } + +.fa-tasks:before { + content: "\f0ae"; } + +.fa-taxi:before { + content: "\f1ba"; } + +.fa-teamspeak:before { + content: "\f4f9"; } + +.fa-teeth:before { + content: "\f62e"; } + +.fa-teeth-open:before { + content: "\f62f"; } + +.fa-telegram:before { + content: "\f2c6"; } + +.fa-telegram-plane:before { + content: "\f3fe"; } + +.fa-temperature-high:before { + content: "\f769"; } + +.fa-temperature-low:before { + content: "\f76b"; } + +.fa-tencent-weibo:before { + content: "\f1d5"; } + +.fa-tenge:before { + content: "\f7d7"; } + +.fa-terminal:before { + content: "\f120"; } + +.fa-text-height:before { + content: "\f034"; } + +.fa-text-width:before { + content: "\f035"; } + +.fa-th:before { + content: "\f00a"; } + +.fa-th-large:before { + content: "\f009"; } + +.fa-th-list:before { + content: "\f00b"; } + +.fa-the-red-yeti:before { + content: "\f69d"; } + +.fa-theater-masks:before { + content: "\f630"; } + +.fa-themeco:before { + content: "\f5c6"; } + +.fa-themeisle:before { + content: "\f2b2"; } + +.fa-thermometer:before { + content: "\f491"; } + +.fa-thermometer-empty:before { + content: "\f2cb"; } + +.fa-thermometer-full:before { + content: "\f2c7"; } + +.fa-thermometer-half:before { + content: "\f2c9"; } + +.fa-thermometer-quarter:before { + content: "\f2ca"; } + +.fa-thermometer-three-quarters:before { + content: "\f2c8"; } + +.fa-think-peaks:before { + content: "\f731"; } + +.fa-thumbs-down:before { + content: "\f165"; } + +.fa-thumbs-up:before { + content: "\f164"; } + +.fa-thumbtack:before { + content: "\f08d"; } + +.fa-ticket-alt:before { + content: "\f3ff"; } + +.fa-times:before { + content: "\f00d"; } + +.fa-times-circle:before { + content: "\f057"; } + +.fa-tint:before { + content: "\f043"; } + +.fa-tint-slash:before { + content: "\f5c7"; } + +.fa-tired:before { + content: "\f5c8"; } + +.fa-toggle-off:before { + content: "\f204"; } + +.fa-toggle-on:before { + content: "\f205"; } + +.fa-toilet:before { + content: "\f7d8"; } + +.fa-toilet-paper:before { + content: "\f71e"; } + +.fa-toolbox:before { + content: "\f552"; } + +.fa-tools:before { + content: "\f7d9"; } + +.fa-tooth:before { + content: "\f5c9"; } + +.fa-torah:before { + content: "\f6a0"; } + +.fa-torii-gate:before { + content: "\f6a1"; } + +.fa-tractor:before { + content: "\f722"; } + +.fa-trade-federation:before { + content: "\f513"; } + +.fa-trademark:before { + content: "\f25c"; } + +.fa-traffic-light:before { + content: "\f637"; } + +.fa-trailer:before { + content: "\f941"; } + +.fa-train:before { + content: "\f238"; } + +.fa-tram:before { + content: "\f7da"; } + +.fa-transgender:before { + content: "\f224"; } + +.fa-transgender-alt:before { + content: "\f225"; } + +.fa-trash:before { + content: "\f1f8"; } + +.fa-trash-alt:before { + content: "\f2ed"; } + +.fa-trash-restore:before { + content: "\f829"; } + +.fa-trash-restore-alt:before { + content: "\f82a"; } + +.fa-tree:before { + content: "\f1bb"; } + +.fa-trello:before { + content: "\f181"; } + +.fa-tripadvisor:before { + content: "\f262"; } + +.fa-trophy:before { + content: "\f091"; } + +.fa-truck:before { + content: "\f0d1"; } + +.fa-truck-loading:before { + content: "\f4de"; } + +.fa-truck-monster:before { + content: "\f63b"; } + +.fa-truck-moving:before { + content: "\f4df"; } + +.fa-truck-pickup:before { + content: "\f63c"; } + +.fa-tshirt:before { + content: "\f553"; } + +.fa-tty:before { + content: "\f1e4"; } + +.fa-tumblr:before { + content: "\f173"; } + +.fa-tumblr-square:before { + content: "\f174"; } + +.fa-tv:before { + content: "\f26c"; } + +.fa-twitch:before { + content: "\f1e8"; } + +.fa-twitter:before { + content: "\f099"; } + +.fa-twitter-square:before { + content: "\f081"; } + +.fa-typo3:before { + content: "\f42b"; } + +.fa-uber:before { + content: "\f402"; } + +.fa-ubuntu:before { + content: "\f7df"; } + +.fa-uikit:before { + content: "\f403"; } + +.fa-umbraco:before { + content: "\f8e8"; } + +.fa-umbrella:before { + content: "\f0e9"; } + +.fa-umbrella-beach:before { + content: "\f5ca"; } + +.fa-underline:before { + content: "\f0cd"; } + +.fa-undo:before { + content: "\f0e2"; } + +.fa-undo-alt:before { + content: "\f2ea"; } + +.fa-uniregistry:before { + content: "\f404"; } + +.fa-unity:before { + content: "\f949"; } + +.fa-universal-access:before { + content: "\f29a"; } + +.fa-university:before { + content: "\f19c"; } + +.fa-unlink:before { + content: "\f127"; } + +.fa-unlock:before { + content: "\f09c"; } + +.fa-unlock-alt:before { + content: "\f13e"; } + +.fa-untappd:before { + content: "\f405"; } + +.fa-upload:before { + content: "\f093"; } + +.fa-ups:before { + content: "\f7e0"; } + +.fa-usb:before { + content: "\f287"; } + +.fa-user:before { + content: "\f007"; } + +.fa-user-alt:before { + content: "\f406"; } + +.fa-user-alt-slash:before { + content: "\f4fa"; } + +.fa-user-astronaut:before { + content: "\f4fb"; } + +.fa-user-check:before { + content: "\f4fc"; } + +.fa-user-circle:before { + content: "\f2bd"; } + +.fa-user-clock:before { + content: "\f4fd"; } + +.fa-user-cog:before { + content: "\f4fe"; } + +.fa-user-edit:before { + content: "\f4ff"; } + +.fa-user-friends:before { + content: "\f500"; } + +.fa-user-graduate:before { + content: "\f501"; } + +.fa-user-injured:before { + content: "\f728"; } + +.fa-user-lock:before { + content: "\f502"; } + +.fa-user-md:before { + content: "\f0f0"; } + +.fa-user-minus:before { + content: "\f503"; } + +.fa-user-ninja:before { + content: "\f504"; } + +.fa-user-nurse:before { + content: "\f82f"; } + +.fa-user-plus:before { + content: "\f234"; } + +.fa-user-secret:before { + content: "\f21b"; } + +.fa-user-shield:before { + content: "\f505"; } + +.fa-user-slash:before { + content: "\f506"; } + +.fa-user-tag:before { + content: "\f507"; } + +.fa-user-tie:before { + content: "\f508"; } + +.fa-user-times:before { + content: "\f235"; } + +.fa-users:before { + content: "\f0c0"; } + +.fa-users-cog:before { + content: "\f509"; } + +.fa-usps:before { + content: "\f7e1"; } + +.fa-ussunnah:before { + content: "\f407"; } + +.fa-utensil-spoon:before { + content: "\f2e5"; } + +.fa-utensils:before { + content: "\f2e7"; } + +.fa-vaadin:before { + content: "\f408"; } + +.fa-vector-square:before { + content: "\f5cb"; } + +.fa-venus:before { + content: "\f221"; } + +.fa-venus-double:before { + content: "\f226"; } + +.fa-venus-mars:before { + content: "\f228"; } + +.fa-viacoin:before { + content: "\f237"; } + +.fa-viadeo:before { + content: "\f2a9"; } + +.fa-viadeo-square:before { + content: "\f2aa"; } + +.fa-vial:before { + content: "\f492"; } + +.fa-vials:before { + content: "\f493"; } + +.fa-viber:before { + content: "\f409"; } + +.fa-video:before { + content: "\f03d"; } + +.fa-video-slash:before { + content: "\f4e2"; } + +.fa-vihara:before { + content: "\f6a7"; } + +.fa-vimeo:before { + content: "\f40a"; } + +.fa-vimeo-square:before { + content: "\f194"; } + +.fa-vimeo-v:before { + content: "\f27d"; } + +.fa-vine:before { + content: "\f1ca"; } + +.fa-vk:before { + content: "\f189"; } + +.fa-vnv:before { + content: "\f40b"; } + +.fa-voicemail:before { + content: "\f897"; } + +.fa-volleyball-ball:before { + content: "\f45f"; } + +.fa-volume-down:before { + content: "\f027"; } + +.fa-volume-mute:before { + content: "\f6a9"; } + +.fa-volume-off:before { + content: "\f026"; } + +.fa-volume-up:before { + content: "\f028"; } + +.fa-vote-yea:before { + content: "\f772"; } + +.fa-vr-cardboard:before { + content: "\f729"; } + +.fa-vuejs:before { + content: "\f41f"; } + +.fa-walking:before { + content: "\f554"; } + +.fa-wallet:before { + content: "\f555"; } + +.fa-warehouse:before { + content: "\f494"; } + +.fa-water:before { + content: "\f773"; } + +.fa-wave-square:before { + content: "\f83e"; } + +.fa-waze:before { + content: "\f83f"; } + +.fa-weebly:before { + content: "\f5cc"; } + +.fa-weibo:before { + content: "\f18a"; } + +.fa-weight:before { + content: "\f496"; } + +.fa-weight-hanging:before { + content: "\f5cd"; } + +.fa-weixin:before { + content: "\f1d7"; } + +.fa-whatsapp:before { + content: "\f232"; } + +.fa-whatsapp-square:before { + content: "\f40c"; } + +.fa-wheelchair:before { + content: "\f193"; } + +.fa-whmcs:before { + content: "\f40d"; } + +.fa-wifi:before { + content: "\f1eb"; } + +.fa-wikipedia-w:before { + content: "\f266"; } + +.fa-wind:before { + content: "\f72e"; } + +.fa-window-close:before { + content: "\f410"; } + +.fa-window-maximize:before { + content: "\f2d0"; } + +.fa-window-minimize:before { + content: "\f2d1"; } + +.fa-window-restore:before { + content: "\f2d2"; } + +.fa-windows:before { + content: "\f17a"; } + +.fa-wine-bottle:before { + content: "\f72f"; } + +.fa-wine-glass:before { + content: "\f4e3"; } + +.fa-wine-glass-alt:before { + content: "\f5ce"; } + +.fa-wix:before { + content: "\f5cf"; } + +.fa-wizards-of-the-coast:before { + content: "\f730"; } + +.fa-wolf-pack-battalion:before { + content: "\f514"; } + +.fa-won-sign:before { + content: "\f159"; } + +.fa-wordpress:before { + content: "\f19a"; } + +.fa-wordpress-simple:before { + content: "\f411"; } + +.fa-wpbeginner:before { + content: "\f297"; } + +.fa-wpexplorer:before { + content: "\f2de"; } + +.fa-wpforms:before { + content: "\f298"; } + +.fa-wpressr:before { + content: "\f3e4"; } + +.fa-wrench:before { + content: "\f0ad"; } + +.fa-x-ray:before { + content: "\f497"; } + +.fa-xbox:before { + content: "\f412"; } + +.fa-xing:before { + content: "\f168"; } + +.fa-xing-square:before { + content: "\f169"; } + +.fa-y-combinator:before { + content: "\f23b"; } + +.fa-yahoo:before { + content: "\f19e"; } + +.fa-yammer:before { + content: "\f840"; } + +.fa-yandex:before { + content: "\f413"; } + +.fa-yandex-international:before { + content: "\f414"; } + +.fa-yarn:before { + content: "\f7e3"; } + +.fa-yelp:before { + content: "\f1e9"; } + +.fa-yen-sign:before { + content: "\f157"; } + +.fa-yin-yang:before { + content: "\f6ad"; } + +.fa-yoast:before { + content: "\f2b1"; } + +.fa-youtube:before { + content: "\f167"; } + +.fa-youtube-square:before { + content: "\f431"; } + +.fa-zhihu:before { + content: "\f63f"; } + +.sr-only { + border: 0; + clip: rect(0, 0, 0, 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; } + +.sr-only-focusable:active, .sr-only-focusable:focus { + clip: auto; + height: auto; + margin: 0; + overflow: visible; + position: static; + width: auto; } diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/fontawesome.min.css b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/fontawesome.min.css new file mode 100755 index 0000000..e00f0ed --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/fontawesome.min.css @@ -0,0 +1,5 @@ +/*! + * Font Awesome Free 5.12.1 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +.fa,.fab,.fad,.fal,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:.08em solid #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fab.fa-pull-left,.fal.fa-pull-left,.far.fa-pull-left,.fas.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fab.fa-pull-right,.fal.fa-pull-right,.far.fa-pull-right,.fas.fa-pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-webkit-transform:scaleY(-1);transform:scaleY(-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical,.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-webkit-transform:scale(-1);transform:scale(-1)}:root .fa-flip-both,:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{-webkit-filter:none;filter:none}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-500px:before{content:"\f26e"}.fa-accessible-icon:before{content:"\f368"}.fa-accusoft:before{content:"\f369"}.fa-acquisitions-incorporated:before{content:"\f6af"}.fa-ad:before{content:"\f641"}.fa-address-book:before{content:"\f2b9"}.fa-address-card:before{content:"\f2bb"}.fa-adjust:before{content:"\f042"}.fa-adn:before{content:"\f170"}.fa-adobe:before{content:"\f778"}.fa-adversal:before{content:"\f36a"}.fa-affiliatetheme:before{content:"\f36b"}.fa-air-freshener:before{content:"\f5d0"}.fa-airbnb:before{content:"\f834"}.fa-algolia:before{content:"\f36c"}.fa-align-center:before{content:"\f037"}.fa-align-justify:before{content:"\f039"}.fa-align-left:before{content:"\f036"}.fa-align-right:before{content:"\f038"}.fa-alipay:before{content:"\f642"}.fa-allergies:before{content:"\f461"}.fa-amazon:before{content:"\f270"}.fa-amazon-pay:before{content:"\f42c"}.fa-ambulance:before{content:"\f0f9"}.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-amilia:before{content:"\f36d"}.fa-anchor:before{content:"\f13d"}.fa-android:before{content:"\f17b"}.fa-angellist:before{content:"\f209"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-down:before{content:"\f107"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angry:before{content:"\f556"}.fa-angrycreative:before{content:"\f36e"}.fa-angular:before{content:"\f420"}.fa-ankh:before{content:"\f644"}.fa-app-store:before{content:"\f36f"}.fa-app-store-ios:before{content:"\f370"}.fa-apper:before{content:"\f371"}.fa-apple:before{content:"\f179"}.fa-apple-alt:before{content:"\f5d1"}.fa-apple-pay:before{content:"\f415"}.fa-archive:before{content:"\f187"}.fa-archway:before{content:"\f557"}.fa-arrow-alt-circle-down:before{content:"\f358"}.fa-arrow-alt-circle-left:before{content:"\f359"}.fa-arrow-alt-circle-right:before{content:"\f35a"}.fa-arrow-alt-circle-up:before{content:"\f35b"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-down:before{content:"\f063"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrows-alt:before{content:"\f0b2"}.fa-arrows-alt-h:before{content:"\f337"}.fa-arrows-alt-v:before{content:"\f338"}.fa-artstation:before{content:"\f77a"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asterisk:before{content:"\f069"}.fa-asymmetrik:before{content:"\f372"}.fa-at:before{content:"\f1fa"}.fa-atlas:before{content:"\f558"}.fa-atlassian:before{content:"\f77b"}.fa-atom:before{content:"\f5d2"}.fa-audible:before{content:"\f373"}.fa-audio-description:before{content:"\f29e"}.fa-autoprefixer:before{content:"\f41c"}.fa-avianex:before{content:"\f374"}.fa-aviato:before{content:"\f421"}.fa-award:before{content:"\f559"}.fa-aws:before{content:"\f375"}.fa-baby:before{content:"\f77c"}.fa-baby-carriage:before{content:"\f77d"}.fa-backspace:before{content:"\f55a"}.fa-backward:before{content:"\f04a"}.fa-bacon:before{content:"\f7e5"}.fa-bahai:before{content:"\f666"}.fa-balance-scale:before{content:"\f24e"}.fa-balance-scale-left:before{content:"\f515"}.fa-balance-scale-right:before{content:"\f516"}.fa-ban:before{content:"\f05e"}.fa-band-aid:before{content:"\f462"}.fa-bandcamp:before{content:"\f2d5"}.fa-barcode:before{content:"\f02a"}.fa-bars:before{content:"\f0c9"}.fa-baseball-ball:before{content:"\f433"}.fa-basketball-ball:before{content:"\f434"}.fa-bath:before{content:"\f2cd"}.fa-battery-empty:before{content:"\f244"}.fa-battery-full:before{content:"\f240"}.fa-battery-half:before{content:"\f242"}.fa-battery-quarter:before{content:"\f243"}.fa-battery-three-quarters:before{content:"\f241"}.fa-battle-net:before{content:"\f835"}.fa-bed:before{content:"\f236"}.fa-beer:before{content:"\f0fc"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-bell:before{content:"\f0f3"}.fa-bell-slash:before{content:"\f1f6"}.fa-bezier-curve:before{content:"\f55b"}.fa-bible:before{content:"\f647"}.fa-bicycle:before{content:"\f206"}.fa-biking:before{content:"\f84a"}.fa-bimobject:before{content:"\f378"}.fa-binoculars:before{content:"\f1e5"}.fa-biohazard:before{content:"\f780"}.fa-birthday-cake:before{content:"\f1fd"}.fa-bitbucket:before{content:"\f171"}.fa-bitcoin:before{content:"\f379"}.fa-bity:before{content:"\f37a"}.fa-black-tie:before{content:"\f27e"}.fa-blackberry:before{content:"\f37b"}.fa-blender:before{content:"\f517"}.fa-blender-phone:before{content:"\f6b6"}.fa-blind:before{content:"\f29d"}.fa-blog:before{content:"\f781"}.fa-blogger:before{content:"\f37c"}.fa-blogger-b:before{content:"\f37d"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-bold:before{content:"\f032"}.fa-bolt:before{content:"\f0e7"}.fa-bomb:before{content:"\f1e2"}.fa-bone:before{content:"\f5d7"}.fa-bong:before{content:"\f55c"}.fa-book:before{content:"\f02d"}.fa-book-dead:before{content:"\f6b7"}.fa-book-medical:before{content:"\f7e6"}.fa-book-open:before{content:"\f518"}.fa-book-reader:before{content:"\f5da"}.fa-bookmark:before{content:"\f02e"}.fa-bootstrap:before{content:"\f836"}.fa-border-all:before{content:"\f84c"}.fa-border-none:before{content:"\f850"}.fa-border-style:before{content:"\f853"}.fa-bowling-ball:before{content:"\f436"}.fa-box:before{content:"\f466"}.fa-box-open:before{content:"\f49e"}.fa-boxes:before{content:"\f468"}.fa-braille:before{content:"\f2a1"}.fa-brain:before{content:"\f5dc"}.fa-bread-slice:before{content:"\f7ec"}.fa-briefcase:before{content:"\f0b1"}.fa-briefcase-medical:before{content:"\f469"}.fa-broadcast-tower:before{content:"\f519"}.fa-broom:before{content:"\f51a"}.fa-brush:before{content:"\f55d"}.fa-btc:before{content:"\f15a"}.fa-buffer:before{content:"\f837"}.fa-bug:before{content:"\f188"}.fa-building:before{content:"\f1ad"}.fa-bullhorn:before{content:"\f0a1"}.fa-bullseye:before{content:"\f140"}.fa-burn:before{content:"\f46a"}.fa-buromobelexperte:before{content:"\f37f"}.fa-bus:before{content:"\f207"}.fa-bus-alt:before{content:"\f55e"}.fa-business-time:before{content:"\f64a"}.fa-buy-n-large:before{content:"\f8a6"}.fa-buysellads:before{content:"\f20d"}.fa-calculator:before{content:"\f1ec"}.fa-calendar:before{content:"\f133"}.fa-calendar-alt:before{content:"\f073"}.fa-calendar-check:before{content:"\f274"}.fa-calendar-day:before{content:"\f783"}.fa-calendar-minus:before{content:"\f272"}.fa-calendar-plus:before{content:"\f271"}.fa-calendar-times:before{content:"\f273"}.fa-calendar-week:before{content:"\f784"}.fa-camera:before{content:"\f030"}.fa-camera-retro:before{content:"\f083"}.fa-campground:before{content:"\f6bb"}.fa-canadian-maple-leaf:before{content:"\f785"}.fa-candy-cane:before{content:"\f786"}.fa-cannabis:before{content:"\f55f"}.fa-capsules:before{content:"\f46b"}.fa-car:before{content:"\f1b9"}.fa-car-alt:before{content:"\f5de"}.fa-car-battery:before{content:"\f5df"}.fa-car-crash:before{content:"\f5e1"}.fa-car-side:before{content:"\f5e4"}.fa-caravan:before{content:"\f8ff"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-caret-square-down:before{content:"\f150"}.fa-caret-square-left:before{content:"\f191"}.fa-caret-square-right:before{content:"\f152"}.fa-caret-square-up:before{content:"\f151"}.fa-caret-up:before{content:"\f0d8"}.fa-carrot:before{content:"\f787"}.fa-cart-arrow-down:before{content:"\f218"}.fa-cart-plus:before{content:"\f217"}.fa-cash-register:before{content:"\f788"}.fa-cat:before{content:"\f6be"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-apple-pay:before{content:"\f416"}.fa-cc-diners-club:before{content:"\f24c"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-cc-visa:before{content:"\f1f0"}.fa-centercode:before{content:"\f380"}.fa-centos:before{content:"\f789"}.fa-certificate:before{content:"\f0a3"}.fa-chair:before{content:"\f6c0"}.fa-chalkboard:before{content:"\f51b"}.fa-chalkboard-teacher:before{content:"\f51c"}.fa-charging-station:before{content:"\f5e7"}.fa-chart-area:before{content:"\f1fe"}.fa-chart-bar:before{content:"\f080"}.fa-chart-line:before{content:"\f201"}.fa-chart-pie:before{content:"\f200"}.fa-check:before{content:"\f00c"}.fa-check-circle:before{content:"\f058"}.fa-check-double:before{content:"\f560"}.fa-check-square:before{content:"\f14a"}.fa-cheese:before{content:"\f7ef"}.fa-chess:before{content:"\f439"}.fa-chess-bishop:before{content:"\f43a"}.fa-chess-board:before{content:"\f43c"}.fa-chess-king:before{content:"\f43f"}.fa-chess-knight:before{content:"\f441"}.fa-chess-pawn:before{content:"\f443"}.fa-chess-queen:before{content:"\f445"}.fa-chess-rook:before{content:"\f447"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-down:before{content:"\f078"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-chevron-up:before{content:"\f077"}.fa-child:before{content:"\f1ae"}.fa-chrome:before{content:"\f268"}.fa-chromecast:before{content:"\f838"}.fa-church:before{content:"\f51d"}.fa-circle:before{content:"\f111"}.fa-circle-notch:before{content:"\f1ce"}.fa-city:before{content:"\f64f"}.fa-clinic-medical:before{content:"\f7f2"}.fa-clipboard:before{content:"\f328"}.fa-clipboard-check:before{content:"\f46c"}.fa-clipboard-list:before{content:"\f46d"}.fa-clock:before{content:"\f017"}.fa-clone:before{content:"\f24d"}.fa-closed-captioning:before{content:"\f20a"}.fa-cloud:before{content:"\f0c2"}.fa-cloud-download-alt:before{content:"\f381"}.fa-cloud-meatball:before{content:"\f73b"}.fa-cloud-moon:before{content:"\f6c3"}.fa-cloud-moon-rain:before{content:"\f73c"}.fa-cloud-rain:before{content:"\f73d"}.fa-cloud-showers-heavy:before{content:"\f740"}.fa-cloud-sun:before{content:"\f6c4"}.fa-cloud-sun-rain:before{content:"\f743"}.fa-cloud-upload-alt:before{content:"\f382"}.fa-cloudscale:before{content:"\f383"}.fa-cloudsmith:before{content:"\f384"}.fa-cloudversify:before{content:"\f385"}.fa-cocktail:before{content:"\f561"}.fa-code:before{content:"\f121"}.fa-code-branch:before{content:"\f126"}.fa-codepen:before{content:"\f1cb"}.fa-codiepie:before{content:"\f284"}.fa-coffee:before{content:"\f0f4"}.fa-cog:before{content:"\f013"}.fa-cogs:before{content:"\f085"}.fa-coins:before{content:"\f51e"}.fa-columns:before{content:"\f0db"}.fa-comment:before{content:"\f075"}.fa-comment-alt:before{content:"\f27a"}.fa-comment-dollar:before{content:"\f651"}.fa-comment-dots:before{content:"\f4ad"}.fa-comment-medical:before{content:"\f7f5"}.fa-comment-slash:before{content:"\f4b3"}.fa-comments:before{content:"\f086"}.fa-comments-dollar:before{content:"\f653"}.fa-compact-disc:before{content:"\f51f"}.fa-compass:before{content:"\f14e"}.fa-compress:before{content:"\f066"}.fa-compress-alt:before{content:"\f422"}.fa-compress-arrows-alt:before{content:"\f78c"}.fa-concierge-bell:before{content:"\f562"}.fa-confluence:before{content:"\f78d"}.fa-connectdevelop:before{content:"\f20e"}.fa-contao:before{content:"\f26d"}.fa-cookie:before{content:"\f563"}.fa-cookie-bite:before{content:"\f564"}.fa-copy:before{content:"\f0c5"}.fa-copyright:before{content:"\f1f9"}.fa-cotton-bureau:before{content:"\f89e"}.fa-couch:before{content:"\f4b8"}.fa-cpanel:before{content:"\f388"}.fa-creative-commons:before{content:"\f25e"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-creative-commons-nc-eu:before{content:"\f4e9"}.fa-creative-commons-nc-jp:before{content:"\f4ea"}.fa-creative-commons-nd:before{content:"\f4eb"}.fa-creative-commons-pd:before{content:"\f4ec"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-creative-commons-remix:before{content:"\f4ee"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-creative-commons-sampling-plus:before{content:"\f4f1"}.fa-creative-commons-share:before{content:"\f4f2"}.fa-creative-commons-zero:before{content:"\f4f3"}.fa-credit-card:before{content:"\f09d"}.fa-critical-role:before{content:"\f6c9"}.fa-crop:before{content:"\f125"}.fa-crop-alt:before{content:"\f565"}.fa-cross:before{content:"\f654"}.fa-crosshairs:before{content:"\f05b"}.fa-crow:before{content:"\f520"}.fa-crown:before{content:"\f521"}.fa-crutch:before{content:"\f7f7"}.fa-css3:before{content:"\f13c"}.fa-css3-alt:before{content:"\f38b"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-cut:before{content:"\f0c4"}.fa-cuttlefish:before{content:"\f38c"}.fa-d-and-d:before{content:"\f38d"}.fa-d-and-d-beyond:before{content:"\f6ca"}.fa-dailymotion:before{content:"\f952"}.fa-dashcube:before{content:"\f210"}.fa-database:before{content:"\f1c0"}.fa-deaf:before{content:"\f2a4"}.fa-delicious:before{content:"\f1a5"}.fa-democrat:before{content:"\f747"}.fa-deploydog:before{content:"\f38e"}.fa-deskpro:before{content:"\f38f"}.fa-desktop:before{content:"\f108"}.fa-dev:before{content:"\f6cc"}.fa-deviantart:before{content:"\f1bd"}.fa-dharmachakra:before{content:"\f655"}.fa-dhl:before{content:"\f790"}.fa-diagnoses:before{content:"\f470"}.fa-diaspora:before{content:"\f791"}.fa-dice:before{content:"\f522"}.fa-dice-d20:before{content:"\f6cf"}.fa-dice-d6:before{content:"\f6d1"}.fa-dice-five:before{content:"\f523"}.fa-dice-four:before{content:"\f524"}.fa-dice-one:before{content:"\f525"}.fa-dice-six:before{content:"\f526"}.fa-dice-three:before{content:"\f527"}.fa-dice-two:before{content:"\f528"}.fa-digg:before{content:"\f1a6"}.fa-digital-ocean:before{content:"\f391"}.fa-digital-tachograph:before{content:"\f566"}.fa-directions:before{content:"\f5eb"}.fa-discord:before{content:"\f392"}.fa-discourse:before{content:"\f393"}.fa-divide:before{content:"\f529"}.fa-dizzy:before{content:"\f567"}.fa-dna:before{content:"\f471"}.fa-dochub:before{content:"\f394"}.fa-docker:before{content:"\f395"}.fa-dog:before{content:"\f6d3"}.fa-dollar-sign:before{content:"\f155"}.fa-dolly:before{content:"\f472"}.fa-dolly-flatbed:before{content:"\f474"}.fa-donate:before{content:"\f4b9"}.fa-door-closed:before{content:"\f52a"}.fa-door-open:before{content:"\f52b"}.fa-dot-circle:before{content:"\f192"}.fa-dove:before{content:"\f4ba"}.fa-download:before{content:"\f019"}.fa-draft2digital:before{content:"\f396"}.fa-drafting-compass:before{content:"\f568"}.fa-dragon:before{content:"\f6d5"}.fa-draw-polygon:before{content:"\f5ee"}.fa-dribbble:before{content:"\f17d"}.fa-dribbble-square:before{content:"\f397"}.fa-dropbox:before{content:"\f16b"}.fa-drum:before{content:"\f569"}.fa-drum-steelpan:before{content:"\f56a"}.fa-drumstick-bite:before{content:"\f6d7"}.fa-drupal:before{content:"\f1a9"}.fa-dumbbell:before{content:"\f44b"}.fa-dumpster:before{content:"\f793"}.fa-dumpster-fire:before{content:"\f794"}.fa-dungeon:before{content:"\f6d9"}.fa-dyalog:before{content:"\f399"}.fa-earlybirds:before{content:"\f39a"}.fa-ebay:before{content:"\f4f4"}.fa-edge:before{content:"\f282"}.fa-edit:before{content:"\f044"}.fa-egg:before{content:"\f7fb"}.fa-eject:before{content:"\f052"}.fa-elementor:before{content:"\f430"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-ello:before{content:"\f5f1"}.fa-ember:before{content:"\f423"}.fa-empire:before{content:"\f1d1"}.fa-envelope:before{content:"\f0e0"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-text:before{content:"\f658"}.fa-envelope-square:before{content:"\f199"}.fa-envira:before{content:"\f299"}.fa-equals:before{content:"\f52c"}.fa-eraser:before{content:"\f12d"}.fa-erlang:before{content:"\f39d"}.fa-ethereum:before{content:"\f42e"}.fa-ethernet:before{content:"\f796"}.fa-etsy:before{content:"\f2d7"}.fa-euro-sign:before{content:"\f153"}.fa-evernote:before{content:"\f839"}.fa-exchange-alt:before{content:"\f362"}.fa-exclamation:before{content:"\f12a"}.fa-exclamation-circle:before{content:"\f06a"}.fa-exclamation-triangle:before{content:"\f071"}.fa-expand:before{content:"\f065"}.fa-expand-alt:before{content:"\f424"}.fa-expand-arrows-alt:before{content:"\f31e"}.fa-expeditedssl:before{content:"\f23e"}.fa-external-link-alt:before{content:"\f35d"}.fa-external-link-square-alt:before{content:"\f360"}.fa-eye:before{content:"\f06e"}.fa-eye-dropper:before{content:"\f1fb"}.fa-eye-slash:before{content:"\f070"}.fa-facebook:before{content:"\f09a"}.fa-facebook-f:before{content:"\f39e"}.fa-facebook-messenger:before{content:"\f39f"}.fa-facebook-square:before{content:"\f082"}.fa-fan:before{content:"\f863"}.fa-fantasy-flight-games:before{content:"\f6dc"}.fa-fast-backward:before{content:"\f049"}.fa-fast-forward:before{content:"\f050"}.fa-fax:before{content:"\f1ac"}.fa-feather:before{content:"\f52d"}.fa-feather-alt:before{content:"\f56b"}.fa-fedex:before{content:"\f797"}.fa-fedora:before{content:"\f798"}.fa-female:before{content:"\f182"}.fa-fighter-jet:before{content:"\f0fb"}.fa-figma:before{content:"\f799"}.fa-file:before{content:"\f15b"}.fa-file-alt:before{content:"\f15c"}.fa-file-archive:before{content:"\f1c6"}.fa-file-audio:before{content:"\f1c7"}.fa-file-code:before{content:"\f1c9"}.fa-file-contract:before{content:"\f56c"}.fa-file-csv:before{content:"\f6dd"}.fa-file-download:before{content:"\f56d"}.fa-file-excel:before{content:"\f1c3"}.fa-file-export:before{content:"\f56e"}.fa-file-image:before{content:"\f1c5"}.fa-file-import:before{content:"\f56f"}.fa-file-invoice:before{content:"\f570"}.fa-file-invoice-dollar:before{content:"\f571"}.fa-file-medical:before{content:"\f477"}.fa-file-medical-alt:before{content:"\f478"}.fa-file-pdf:before{content:"\f1c1"}.fa-file-powerpoint:before{content:"\f1c4"}.fa-file-prescription:before{content:"\f572"}.fa-file-signature:before{content:"\f573"}.fa-file-upload:before{content:"\f574"}.fa-file-video:before{content:"\f1c8"}.fa-file-word:before{content:"\f1c2"}.fa-fill:before{content:"\f575"}.fa-fill-drip:before{content:"\f576"}.fa-film:before{content:"\f008"}.fa-filter:before{content:"\f0b0"}.fa-fingerprint:before{content:"\f577"}.fa-fire:before{content:"\f06d"}.fa-fire-alt:before{content:"\f7e4"}.fa-fire-extinguisher:before{content:"\f134"}.fa-firefox:before{content:"\f269"}.fa-firefox-browser:before{content:"\f907"}.fa-first-aid:before{content:"\f479"}.fa-first-order:before{content:"\f2b0"}.fa-first-order-alt:before{content:"\f50a"}.fa-firstdraft:before{content:"\f3a1"}.fa-fish:before{content:"\f578"}.fa-fist-raised:before{content:"\f6de"}.fa-flag:before{content:"\f024"}.fa-flag-checkered:before{content:"\f11e"}.fa-flag-usa:before{content:"\f74d"}.fa-flask:before{content:"\f0c3"}.fa-flickr:before{content:"\f16e"}.fa-flipboard:before{content:"\f44d"}.fa-flushed:before{content:"\f579"}.fa-fly:before{content:"\f417"}.fa-folder:before{content:"\f07b"}.fa-folder-minus:before{content:"\f65d"}.fa-folder-open:before{content:"\f07c"}.fa-folder-plus:before{content:"\f65e"}.fa-font:before{content:"\f031"}.fa-font-awesome:before{content:"\f2b4"}.fa-font-awesome-alt:before{content:"\f35c"}.fa-font-awesome-flag:before{content:"\f425"}.fa-font-awesome-logo-full:before{content:"\f4e6"}.fa-fonticons:before{content:"\f280"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-football-ball:before{content:"\f44e"}.fa-fort-awesome:before{content:"\f286"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-forumbee:before{content:"\f211"}.fa-forward:before{content:"\f04e"}.fa-foursquare:before{content:"\f180"}.fa-free-code-camp:before{content:"\f2c5"}.fa-freebsd:before{content:"\f3a4"}.fa-frog:before{content:"\f52e"}.fa-frown:before{content:"\f119"}.fa-frown-open:before{content:"\f57a"}.fa-fulcrum:before{content:"\f50b"}.fa-funnel-dollar:before{content:"\f662"}.fa-futbol:before{content:"\f1e3"}.fa-galactic-republic:before{content:"\f50c"}.fa-galactic-senate:before{content:"\f50d"}.fa-gamepad:before{content:"\f11b"}.fa-gas-pump:before{content:"\f52f"}.fa-gavel:before{content:"\f0e3"}.fa-gem:before{content:"\f3a5"}.fa-genderless:before{content:"\f22d"}.fa-get-pocket:before{content:"\f265"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-ghost:before{content:"\f6e2"}.fa-gift:before{content:"\f06b"}.fa-gifts:before{content:"\f79c"}.fa-git:before{content:"\f1d3"}.fa-git-alt:before{content:"\f841"}.fa-git-square:before{content:"\f1d2"}.fa-github:before{content:"\f09b"}.fa-github-alt:before{content:"\f113"}.fa-github-square:before{content:"\f092"}.fa-gitkraken:before{content:"\f3a6"}.fa-gitlab:before{content:"\f296"}.fa-gitter:before{content:"\f426"}.fa-glass-cheers:before{content:"\f79f"}.fa-glass-martini:before{content:"\f000"}.fa-glass-martini-alt:before{content:"\f57b"}.fa-glass-whiskey:before{content:"\f7a0"}.fa-glasses:before{content:"\f530"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-globe:before{content:"\f0ac"}.fa-globe-africa:before{content:"\f57c"}.fa-globe-americas:before{content:"\f57d"}.fa-globe-asia:before{content:"\f57e"}.fa-globe-europe:before{content:"\f7a2"}.fa-gofore:before{content:"\f3a7"}.fa-golf-ball:before{content:"\f450"}.fa-goodreads:before{content:"\f3a8"}.fa-goodreads-g:before{content:"\f3a9"}.fa-google:before{content:"\f1a0"}.fa-google-drive:before{content:"\f3aa"}.fa-google-play:before{content:"\f3ab"}.fa-google-plus:before{content:"\f2b3"}.fa-google-plus-g:before{content:"\f0d5"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-wallet:before{content:"\f1ee"}.fa-gopuram:before{content:"\f664"}.fa-graduation-cap:before{content:"\f19d"}.fa-gratipay:before{content:"\f184"}.fa-grav:before{content:"\f2d6"}.fa-greater-than:before{content:"\f531"}.fa-greater-than-equal:before{content:"\f532"}.fa-grimace:before{content:"\f57f"}.fa-grin:before{content:"\f580"}.fa-grin-alt:before{content:"\f581"}.fa-grin-beam:before{content:"\f582"}.fa-grin-beam-sweat:before{content:"\f583"}.fa-grin-hearts:before{content:"\f584"}.fa-grin-squint:before{content:"\f585"}.fa-grin-squint-tears:before{content:"\f586"}.fa-grin-stars:before{content:"\f587"}.fa-grin-tears:before{content:"\f588"}.fa-grin-tongue:before{content:"\f589"}.fa-grin-tongue-squint:before{content:"\f58a"}.fa-grin-tongue-wink:before{content:"\f58b"}.fa-grin-wink:before{content:"\f58c"}.fa-grip-horizontal:before{content:"\f58d"}.fa-grip-lines:before{content:"\f7a4"}.fa-grip-lines-vertical:before{content:"\f7a5"}.fa-grip-vertical:before{content:"\f58e"}.fa-gripfire:before{content:"\f3ac"}.fa-grunt:before{content:"\f3ad"}.fa-guitar:before{content:"\f7a6"}.fa-gulp:before{content:"\f3ae"}.fa-h-square:before{content:"\f0fd"}.fa-hacker-news:before{content:"\f1d4"}.fa-hacker-news-square:before{content:"\f3af"}.fa-hackerrank:before{content:"\f5f7"}.fa-hamburger:before{content:"\f805"}.fa-hammer:before{content:"\f6e3"}.fa-hamsa:before{content:"\f665"}.fa-hand-holding:before{content:"\f4bd"}.fa-hand-holding-heart:before{content:"\f4be"}.fa-hand-holding-usd:before{content:"\f4c0"}.fa-hand-lizard:before{content:"\f258"}.fa-hand-middle-finger:before{content:"\f806"}.fa-hand-paper:before{content:"\f256"}.fa-hand-peace:before{content:"\f25b"}.fa-hand-point-down:before{content:"\f0a7"}.fa-hand-point-left:before{content:"\f0a5"}.fa-hand-point-right:before{content:"\f0a4"}.fa-hand-point-up:before{content:"\f0a6"}.fa-hand-pointer:before{content:"\f25a"}.fa-hand-rock:before{content:"\f255"}.fa-hand-scissors:before{content:"\f257"}.fa-hand-spock:before{content:"\f259"}.fa-hands:before{content:"\f4c2"}.fa-hands-helping:before{content:"\f4c4"}.fa-handshake:before{content:"\f2b5"}.fa-hanukiah:before{content:"\f6e6"}.fa-hard-hat:before{content:"\f807"}.fa-hashtag:before{content:"\f292"}.fa-hat-cowboy:before{content:"\f8c0"}.fa-hat-cowboy-side:before{content:"\f8c1"}.fa-hat-wizard:before{content:"\f6e8"}.fa-hdd:before{content:"\f0a0"}.fa-heading:before{content:"\f1dc"}.fa-headphones:before{content:"\f025"}.fa-headphones-alt:before{content:"\f58f"}.fa-headset:before{content:"\f590"}.fa-heart:before{content:"\f004"}.fa-heart-broken:before{content:"\f7a9"}.fa-heartbeat:before{content:"\f21e"}.fa-helicopter:before{content:"\f533"}.fa-highlighter:before{content:"\f591"}.fa-hiking:before{content:"\f6ec"}.fa-hippo:before{content:"\f6ed"}.fa-hips:before{content:"\f452"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-history:before{content:"\f1da"}.fa-hockey-puck:before{content:"\f453"}.fa-holly-berry:before{content:"\f7aa"}.fa-home:before{content:"\f015"}.fa-hooli:before{content:"\f427"}.fa-hornbill:before{content:"\f592"}.fa-horse:before{content:"\f6f0"}.fa-horse-head:before{content:"\f7ab"}.fa-hospital:before{content:"\f0f8"}.fa-hospital-alt:before{content:"\f47d"}.fa-hospital-symbol:before{content:"\f47e"}.fa-hot-tub:before{content:"\f593"}.fa-hotdog:before{content:"\f80f"}.fa-hotel:before{content:"\f594"}.fa-hotjar:before{content:"\f3b1"}.fa-hourglass:before{content:"\f254"}.fa-hourglass-end:before{content:"\f253"}.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-start:before{content:"\f251"}.fa-house-damage:before{content:"\f6f1"}.fa-houzz:before{content:"\f27c"}.fa-hryvnia:before{content:"\f6f2"}.fa-html5:before{content:"\f13b"}.fa-hubspot:before{content:"\f3b2"}.fa-i-cursor:before{content:"\f246"}.fa-ice-cream:before{content:"\f810"}.fa-icicles:before{content:"\f7ad"}.fa-icons:before{content:"\f86d"}.fa-id-badge:before{content:"\f2c1"}.fa-id-card:before{content:"\f2c2"}.fa-id-card-alt:before{content:"\f47f"}.fa-ideal:before{content:"\f913"}.fa-igloo:before{content:"\f7ae"}.fa-image:before{content:"\f03e"}.fa-images:before{content:"\f302"}.fa-imdb:before{content:"\f2d8"}.fa-inbox:before{content:"\f01c"}.fa-indent:before{content:"\f03c"}.fa-industry:before{content:"\f275"}.fa-infinity:before{content:"\f534"}.fa-info:before{content:"\f129"}.fa-info-circle:before{content:"\f05a"}.fa-instagram:before{content:"\f16d"}.fa-instagram-square:before{content:"\f955"}.fa-intercom:before{content:"\f7af"}.fa-internet-explorer:before{content:"\f26b"}.fa-invision:before{content:"\f7b0"}.fa-ioxhost:before{content:"\f208"}.fa-italic:before{content:"\f033"}.fa-itch-io:before{content:"\f83a"}.fa-itunes:before{content:"\f3b4"}.fa-itunes-note:before{content:"\f3b5"}.fa-java:before{content:"\f4e4"}.fa-jedi:before{content:"\f669"}.fa-jedi-order:before{content:"\f50e"}.fa-jenkins:before{content:"\f3b6"}.fa-jira:before{content:"\f7b1"}.fa-joget:before{content:"\f3b7"}.fa-joint:before{content:"\f595"}.fa-joomla:before{content:"\f1aa"}.fa-journal-whills:before{content:"\f66a"}.fa-js:before{content:"\f3b8"}.fa-js-square:before{content:"\f3b9"}.fa-jsfiddle:before{content:"\f1cc"}.fa-kaaba:before{content:"\f66b"}.fa-kaggle:before{content:"\f5fa"}.fa-key:before{content:"\f084"}.fa-keybase:before{content:"\f4f5"}.fa-keyboard:before{content:"\f11c"}.fa-keycdn:before{content:"\f3ba"}.fa-khanda:before{content:"\f66d"}.fa-kickstarter:before{content:"\f3bb"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-kiss:before{content:"\f596"}.fa-kiss-beam:before{content:"\f597"}.fa-kiss-wink-heart:before{content:"\f598"}.fa-kiwi-bird:before{content:"\f535"}.fa-korvue:before{content:"\f42f"}.fa-landmark:before{content:"\f66f"}.fa-language:before{content:"\f1ab"}.fa-laptop:before{content:"\f109"}.fa-laptop-code:before{content:"\f5fc"}.fa-laptop-medical:before{content:"\f812"}.fa-laravel:before{content:"\f3bd"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-laugh:before{content:"\f599"}.fa-laugh-beam:before{content:"\f59a"}.fa-laugh-squint:before{content:"\f59b"}.fa-laugh-wink:before{content:"\f59c"}.fa-layer-group:before{content:"\f5fd"}.fa-leaf:before{content:"\f06c"}.fa-leanpub:before{content:"\f212"}.fa-lemon:before{content:"\f094"}.fa-less:before{content:"\f41d"}.fa-less-than:before{content:"\f536"}.fa-less-than-equal:before{content:"\f537"}.fa-level-down-alt:before{content:"\f3be"}.fa-level-up-alt:before{content:"\f3bf"}.fa-life-ring:before{content:"\f1cd"}.fa-lightbulb:before{content:"\f0eb"}.fa-line:before{content:"\f3c0"}.fa-link:before{content:"\f0c1"}.fa-linkedin:before{content:"\f08c"}.fa-linkedin-in:before{content:"\f0e1"}.fa-linode:before{content:"\f2b8"}.fa-linux:before{content:"\f17c"}.fa-lira-sign:before{content:"\f195"}.fa-list:before{content:"\f03a"}.fa-list-alt:before{content:"\f022"}.fa-list-ol:before{content:"\f0cb"}.fa-list-ul:before{content:"\f0ca"}.fa-location-arrow:before{content:"\f124"}.fa-lock:before{content:"\f023"}.fa-lock-open:before{content:"\f3c1"}.fa-long-arrow-alt-down:before{content:"\f309"}.fa-long-arrow-alt-left:before{content:"\f30a"}.fa-long-arrow-alt-right:before{content:"\f30b"}.fa-long-arrow-alt-up:before{content:"\f30c"}.fa-low-vision:before{content:"\f2a8"}.fa-luggage-cart:before{content:"\f59d"}.fa-lyft:before{content:"\f3c3"}.fa-magento:before{content:"\f3c4"}.fa-magic:before{content:"\f0d0"}.fa-magnet:before{content:"\f076"}.fa-mail-bulk:before{content:"\f674"}.fa-mailchimp:before{content:"\f59e"}.fa-male:before{content:"\f183"}.fa-mandalorian:before{content:"\f50f"}.fa-map:before{content:"\f279"}.fa-map-marked:before{content:"\f59f"}.fa-map-marked-alt:before{content:"\f5a0"}.fa-map-marker:before{content:"\f041"}.fa-map-marker-alt:before{content:"\f3c5"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-markdown:before{content:"\f60f"}.fa-marker:before{content:"\f5a1"}.fa-mars:before{content:"\f222"}.fa-mars-double:before{content:"\f227"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mask:before{content:"\f6fa"}.fa-mastodon:before{content:"\f4f6"}.fa-maxcdn:before{content:"\f136"}.fa-mdb:before{content:"\f8ca"}.fa-medal:before{content:"\f5a2"}.fa-medapps:before{content:"\f3c6"}.fa-medium:before{content:"\f23a"}.fa-medium-m:before{content:"\f3c7"}.fa-medkit:before{content:"\f0fa"}.fa-medrt:before{content:"\f3c8"}.fa-meetup:before{content:"\f2e0"}.fa-megaport:before{content:"\f5a3"}.fa-meh:before{content:"\f11a"}.fa-meh-blank:before{content:"\f5a4"}.fa-meh-rolling-eyes:before{content:"\f5a5"}.fa-memory:before{content:"\f538"}.fa-mendeley:before{content:"\f7b3"}.fa-menorah:before{content:"\f676"}.fa-mercury:before{content:"\f223"}.fa-meteor:before{content:"\f753"}.fa-microblog:before{content:"\f91a"}.fa-microchip:before{content:"\f2db"}.fa-microphone:before{content:"\f130"}.fa-microphone-alt:before{content:"\f3c9"}.fa-microphone-alt-slash:before{content:"\f539"}.fa-microphone-slash:before{content:"\f131"}.fa-microscope:before{content:"\f610"}.fa-microsoft:before{content:"\f3ca"}.fa-minus:before{content:"\f068"}.fa-minus-circle:before{content:"\f056"}.fa-minus-square:before{content:"\f146"}.fa-mitten:before{content:"\f7b5"}.fa-mix:before{content:"\f3cb"}.fa-mixcloud:before{content:"\f289"}.fa-mixer:before{content:"\f956"}.fa-mizuni:before{content:"\f3cc"}.fa-mobile:before{content:"\f10b"}.fa-mobile-alt:before{content:"\f3cd"}.fa-modx:before{content:"\f285"}.fa-monero:before{content:"\f3d0"}.fa-money-bill:before{content:"\f0d6"}.fa-money-bill-alt:before{content:"\f3d1"}.fa-money-bill-wave:before{content:"\f53a"}.fa-money-bill-wave-alt:before{content:"\f53b"}.fa-money-check:before{content:"\f53c"}.fa-money-check-alt:before{content:"\f53d"}.fa-monument:before{content:"\f5a6"}.fa-moon:before{content:"\f186"}.fa-mortar-pestle:before{content:"\f5a7"}.fa-mosque:before{content:"\f678"}.fa-motorcycle:before{content:"\f21c"}.fa-mountain:before{content:"\f6fc"}.fa-mouse:before{content:"\f8cc"}.fa-mouse-pointer:before{content:"\f245"}.fa-mug-hot:before{content:"\f7b6"}.fa-music:before{content:"\f001"}.fa-napster:before{content:"\f3d2"}.fa-neos:before{content:"\f612"}.fa-network-wired:before{content:"\f6ff"}.fa-neuter:before{content:"\f22c"}.fa-newspaper:before{content:"\f1ea"}.fa-nimblr:before{content:"\f5a8"}.fa-node:before{content:"\f419"}.fa-node-js:before{content:"\f3d3"}.fa-not-equal:before{content:"\f53e"}.fa-notes-medical:before{content:"\f481"}.fa-npm:before{content:"\f3d4"}.fa-ns8:before{content:"\f3d5"}.fa-nutritionix:before{content:"\f3d6"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-oil-can:before{content:"\f613"}.fa-old-republic:before{content:"\f510"}.fa-om:before{content:"\f679"}.fa-opencart:before{content:"\f23d"}.fa-openid:before{content:"\f19b"}.fa-opera:before{content:"\f26a"}.fa-optin-monster:before{content:"\f23c"}.fa-orcid:before{content:"\f8d2"}.fa-osi:before{content:"\f41a"}.fa-otter:before{content:"\f700"}.fa-outdent:before{content:"\f03b"}.fa-page4:before{content:"\f3d7"}.fa-pagelines:before{content:"\f18c"}.fa-pager:before{content:"\f815"}.fa-paint-brush:before{content:"\f1fc"}.fa-paint-roller:before{content:"\f5aa"}.fa-palette:before{content:"\f53f"}.fa-palfed:before{content:"\f3d8"}.fa-pallet:before{content:"\f482"}.fa-paper-plane:before{content:"\f1d8"}.fa-paperclip:before{content:"\f0c6"}.fa-parachute-box:before{content:"\f4cd"}.fa-paragraph:before{content:"\f1dd"}.fa-parking:before{content:"\f540"}.fa-passport:before{content:"\f5ab"}.fa-pastafarianism:before{content:"\f67b"}.fa-paste:before{content:"\f0ea"}.fa-patreon:before{content:"\f3d9"}.fa-pause:before{content:"\f04c"}.fa-pause-circle:before{content:"\f28b"}.fa-paw:before{content:"\f1b0"}.fa-paypal:before{content:"\f1ed"}.fa-peace:before{content:"\f67c"}.fa-pen:before{content:"\f304"}.fa-pen-alt:before{content:"\f305"}.fa-pen-fancy:before{content:"\f5ac"}.fa-pen-nib:before{content:"\f5ad"}.fa-pen-square:before{content:"\f14b"}.fa-pencil-alt:before{content:"\f303"}.fa-pencil-ruler:before{content:"\f5ae"}.fa-penny-arcade:before{content:"\f704"}.fa-people-carry:before{content:"\f4ce"}.fa-pepper-hot:before{content:"\f816"}.fa-percent:before{content:"\f295"}.fa-percentage:before{content:"\f541"}.fa-periscope:before{content:"\f3da"}.fa-person-booth:before{content:"\f756"}.fa-phabricator:before{content:"\f3db"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-phoenix-squadron:before{content:"\f511"}.fa-phone:before{content:"\f095"}.fa-phone-alt:before{content:"\f879"}.fa-phone-slash:before{content:"\f3dd"}.fa-phone-square:before{content:"\f098"}.fa-phone-square-alt:before{content:"\f87b"}.fa-phone-volume:before{content:"\f2a0"}.fa-photo-video:before{content:"\f87c"}.fa-php:before{content:"\f457"}.fa-pied-piper:before{content:"\f2ae"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-pied-piper-hat:before{content:"\f4e5"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-square:before{content:"\f91e"}.fa-piggy-bank:before{content:"\f4d3"}.fa-pills:before{content:"\f484"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-p:before{content:"\f231"}.fa-pinterest-square:before{content:"\f0d3"}.fa-pizza-slice:before{content:"\f818"}.fa-place-of-worship:before{content:"\f67f"}.fa-plane:before{content:"\f072"}.fa-plane-arrival:before{content:"\f5af"}.fa-plane-departure:before{content:"\f5b0"}.fa-play:before{content:"\f04b"}.fa-play-circle:before{content:"\f144"}.fa-playstation:before{content:"\f3df"}.fa-plug:before{content:"\f1e6"}.fa-plus:before{content:"\f067"}.fa-plus-circle:before{content:"\f055"}.fa-plus-square:before{content:"\f0fe"}.fa-podcast:before{content:"\f2ce"}.fa-poll:before{content:"\f681"}.fa-poll-h:before{content:"\f682"}.fa-poo:before{content:"\f2fe"}.fa-poo-storm:before{content:"\f75a"}.fa-poop:before{content:"\f619"}.fa-portrait:before{content:"\f3e0"}.fa-pound-sign:before{content:"\f154"}.fa-power-off:before{content:"\f011"}.fa-pray:before{content:"\f683"}.fa-praying-hands:before{content:"\f684"}.fa-prescription:before{content:"\f5b1"}.fa-prescription-bottle:before{content:"\f485"}.fa-prescription-bottle-alt:before{content:"\f486"}.fa-print:before{content:"\f02f"}.fa-procedures:before{content:"\f487"}.fa-product-hunt:before{content:"\f288"}.fa-project-diagram:before{content:"\f542"}.fa-pushed:before{content:"\f3e1"}.fa-puzzle-piece:before{content:"\f12e"}.fa-python:before{content:"\f3e2"}.fa-qq:before{content:"\f1d6"}.fa-qrcode:before{content:"\f029"}.fa-question:before{content:"\f128"}.fa-question-circle:before{content:"\f059"}.fa-quidditch:before{content:"\f458"}.fa-quinscape:before{content:"\f459"}.fa-quora:before{content:"\f2c4"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-quran:before{content:"\f687"}.fa-r-project:before{content:"\f4f7"}.fa-radiation:before{content:"\f7b9"}.fa-radiation-alt:before{content:"\f7ba"}.fa-rainbow:before{content:"\f75b"}.fa-random:before{content:"\f074"}.fa-raspberry-pi:before{content:"\f7bb"}.fa-ravelry:before{content:"\f2d9"}.fa-react:before{content:"\f41b"}.fa-reacteurope:before{content:"\f75d"}.fa-readme:before{content:"\f4d5"}.fa-rebel:before{content:"\f1d0"}.fa-receipt:before{content:"\f543"}.fa-record-vinyl:before{content:"\f8d9"}.fa-recycle:before{content:"\f1b8"}.fa-red-river:before{content:"\f3e3"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-alien:before{content:"\f281"}.fa-reddit-square:before{content:"\f1a2"}.fa-redhat:before{content:"\f7bc"}.fa-redo:before{content:"\f01e"}.fa-redo-alt:before{content:"\f2f9"}.fa-registered:before{content:"\f25d"}.fa-remove-format:before{content:"\f87d"}.fa-renren:before{content:"\f18b"}.fa-reply:before{content:"\f3e5"}.fa-reply-all:before{content:"\f122"}.fa-replyd:before{content:"\f3e6"}.fa-republican:before{content:"\f75e"}.fa-researchgate:before{content:"\f4f8"}.fa-resolving:before{content:"\f3e7"}.fa-restroom:before{content:"\f7bd"}.fa-retweet:before{content:"\f079"}.fa-rev:before{content:"\f5b2"}.fa-ribbon:before{content:"\f4d6"}.fa-ring:before{content:"\f70b"}.fa-road:before{content:"\f018"}.fa-robot:before{content:"\f544"}.fa-rocket:before{content:"\f135"}.fa-rocketchat:before{content:"\f3e8"}.fa-rockrms:before{content:"\f3e9"}.fa-route:before{content:"\f4d7"}.fa-rss:before{content:"\f09e"}.fa-rss-square:before{content:"\f143"}.fa-ruble-sign:before{content:"\f158"}.fa-ruler:before{content:"\f545"}.fa-ruler-combined:before{content:"\f546"}.fa-ruler-horizontal:before{content:"\f547"}.fa-ruler-vertical:before{content:"\f548"}.fa-running:before{content:"\f70c"}.fa-rupee-sign:before{content:"\f156"}.fa-sad-cry:before{content:"\f5b3"}.fa-sad-tear:before{content:"\f5b4"}.fa-safari:before{content:"\f267"}.fa-salesforce:before{content:"\f83b"}.fa-sass:before{content:"\f41e"}.fa-satellite:before{content:"\f7bf"}.fa-satellite-dish:before{content:"\f7c0"}.fa-save:before{content:"\f0c7"}.fa-schlix:before{content:"\f3ea"}.fa-school:before{content:"\f549"}.fa-screwdriver:before{content:"\f54a"}.fa-scribd:before{content:"\f28a"}.fa-scroll:before{content:"\f70e"}.fa-sd-card:before{content:"\f7c2"}.fa-search:before{content:"\f002"}.fa-search-dollar:before{content:"\f688"}.fa-search-location:before{content:"\f689"}.fa-search-minus:before{content:"\f010"}.fa-search-plus:before{content:"\f00e"}.fa-searchengin:before{content:"\f3eb"}.fa-seedling:before{content:"\f4d8"}.fa-sellcast:before{content:"\f2da"}.fa-sellsy:before{content:"\f213"}.fa-server:before{content:"\f233"}.fa-servicestack:before{content:"\f3ec"}.fa-shapes:before{content:"\f61f"}.fa-share:before{content:"\f064"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-share-square:before{content:"\f14d"}.fa-shekel-sign:before{content:"\f20b"}.fa-shield-alt:before{content:"\f3ed"}.fa-ship:before{content:"\f21a"}.fa-shipping-fast:before{content:"\f48b"}.fa-shirtsinbulk:before{content:"\f214"}.fa-shoe-prints:before{content:"\f54b"}.fa-shopify:before{content:"\f957"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-shopping-cart:before{content:"\f07a"}.fa-shopware:before{content:"\f5b5"}.fa-shower:before{content:"\f2cc"}.fa-shuttle-van:before{content:"\f5b6"}.fa-sign:before{content:"\f4d9"}.fa-sign-in-alt:before{content:"\f2f6"}.fa-sign-language:before{content:"\f2a7"}.fa-sign-out-alt:before{content:"\f2f5"}.fa-signal:before{content:"\f012"}.fa-signature:before{content:"\f5b7"}.fa-sim-card:before{content:"\f7c4"}.fa-simplybuilt:before{content:"\f215"}.fa-sistrix:before{content:"\f3ee"}.fa-sitemap:before{content:"\f0e8"}.fa-sith:before{content:"\f512"}.fa-skating:before{content:"\f7c5"}.fa-sketch:before{content:"\f7c6"}.fa-skiing:before{content:"\f7c9"}.fa-skiing-nordic:before{content:"\f7ca"}.fa-skull:before{content:"\f54c"}.fa-skull-crossbones:before{content:"\f714"}.fa-skyatlas:before{content:"\f216"}.fa-skype:before{content:"\f17e"}.fa-slack:before{content:"\f198"}.fa-slack-hash:before{content:"\f3ef"}.fa-slash:before{content:"\f715"}.fa-sleigh:before{content:"\f7cc"}.fa-sliders-h:before{content:"\f1de"}.fa-slideshare:before{content:"\f1e7"}.fa-smile:before{content:"\f118"}.fa-smile-beam:before{content:"\f5b8"}.fa-smile-wink:before{content:"\f4da"}.fa-smog:before{content:"\f75f"}.fa-smoking:before{content:"\f48d"}.fa-smoking-ban:before{content:"\f54d"}.fa-sms:before{content:"\f7cd"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-snowboarding:before{content:"\f7ce"}.fa-snowflake:before{content:"\f2dc"}.fa-snowman:before{content:"\f7d0"}.fa-snowplow:before{content:"\f7d2"}.fa-socks:before{content:"\f696"}.fa-solar-panel:before{content:"\f5ba"}.fa-sort:before{content:"\f0dc"}.fa-sort-alpha-down:before{content:"\f15d"}.fa-sort-alpha-down-alt:before{content:"\f881"}.fa-sort-alpha-up:before{content:"\f15e"}.fa-sort-alpha-up-alt:before{content:"\f882"}.fa-sort-amount-down:before{content:"\f160"}.fa-sort-amount-down-alt:before{content:"\f884"}.fa-sort-amount-up:before{content:"\f161"}.fa-sort-amount-up-alt:before{content:"\f885"}.fa-sort-down:before{content:"\f0dd"}.fa-sort-numeric-down:before{content:"\f162"}.fa-sort-numeric-down-alt:before{content:"\f886"}.fa-sort-numeric-up:before{content:"\f163"}.fa-sort-numeric-up-alt:before{content:"\f887"}.fa-sort-up:before{content:"\f0de"}.fa-soundcloud:before{content:"\f1be"}.fa-sourcetree:before{content:"\f7d3"}.fa-spa:before{content:"\f5bb"}.fa-space-shuttle:before{content:"\f197"}.fa-speakap:before{content:"\f3f3"}.fa-speaker-deck:before{content:"\f83c"}.fa-spell-check:before{content:"\f891"}.fa-spider:before{content:"\f717"}.fa-spinner:before{content:"\f110"}.fa-splotch:before{content:"\f5bc"}.fa-spotify:before{content:"\f1bc"}.fa-spray-can:before{content:"\f5bd"}.fa-square:before{content:"\f0c8"}.fa-square-full:before{content:"\f45c"}.fa-square-root-alt:before{content:"\f698"}.fa-squarespace:before{content:"\f5be"}.fa-stack-exchange:before{content:"\f18d"}.fa-stack-overflow:before{content:"\f16c"}.fa-stackpath:before{content:"\f842"}.fa-stamp:before{content:"\f5bf"}.fa-star:before{content:"\f005"}.fa-star-and-crescent:before{content:"\f699"}.fa-star-half:before{content:"\f089"}.fa-star-half-alt:before{content:"\f5c0"}.fa-star-of-david:before{content:"\f69a"}.fa-star-of-life:before{content:"\f621"}.fa-staylinked:before{content:"\f3f5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-steam-symbol:before{content:"\f3f6"}.fa-step-backward:before{content:"\f048"}.fa-step-forward:before{content:"\f051"}.fa-stethoscope:before{content:"\f0f1"}.fa-sticker-mule:before{content:"\f3f7"}.fa-sticky-note:before{content:"\f249"}.fa-stop:before{content:"\f04d"}.fa-stop-circle:before{content:"\f28d"}.fa-stopwatch:before{content:"\f2f2"}.fa-store:before{content:"\f54e"}.fa-store-alt:before{content:"\f54f"}.fa-strava:before{content:"\f428"}.fa-stream:before{content:"\f550"}.fa-street-view:before{content:"\f21d"}.fa-strikethrough:before{content:"\f0cc"}.fa-stripe:before{content:"\f429"}.fa-stripe-s:before{content:"\f42a"}.fa-stroopwafel:before{content:"\f551"}.fa-studiovinari:before{content:"\f3f8"}.fa-stumbleupon:before{content:"\f1a4"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-subscript:before{content:"\f12c"}.fa-subway:before{content:"\f239"}.fa-suitcase:before{content:"\f0f2"}.fa-suitcase-rolling:before{content:"\f5c1"}.fa-sun:before{content:"\f185"}.fa-superpowers:before{content:"\f2dd"}.fa-superscript:before{content:"\f12b"}.fa-supple:before{content:"\f3f9"}.fa-surprise:before{content:"\f5c2"}.fa-suse:before{content:"\f7d6"}.fa-swatchbook:before{content:"\f5c3"}.fa-swift:before{content:"\f8e1"}.fa-swimmer:before{content:"\f5c4"}.fa-swimming-pool:before{content:"\f5c5"}.fa-symfony:before{content:"\f83d"}.fa-synagogue:before{content:"\f69b"}.fa-sync:before{content:"\f021"}.fa-sync-alt:before{content:"\f2f1"}.fa-syringe:before{content:"\f48e"}.fa-table:before{content:"\f0ce"}.fa-table-tennis:before{content:"\f45d"}.fa-tablet:before{content:"\f10a"}.fa-tablet-alt:before{content:"\f3fa"}.fa-tablets:before{content:"\f490"}.fa-tachometer-alt:before{content:"\f3fd"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-tape:before{content:"\f4db"}.fa-tasks:before{content:"\f0ae"}.fa-taxi:before{content:"\f1ba"}.fa-teamspeak:before{content:"\f4f9"}.fa-teeth:before{content:"\f62e"}.fa-teeth-open:before{content:"\f62f"}.fa-telegram:before{content:"\f2c6"}.fa-telegram-plane:before{content:"\f3fe"}.fa-temperature-high:before{content:"\f769"}.fa-temperature-low:before{content:"\f76b"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-tenge:before{content:"\f7d7"}.fa-terminal:before{content:"\f120"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-th:before{content:"\f00a"}.fa-th-large:before{content:"\f009"}.fa-th-list:before{content:"\f00b"}.fa-the-red-yeti:before{content:"\f69d"}.fa-theater-masks:before{content:"\f630"}.fa-themeco:before{content:"\f5c6"}.fa-themeisle:before{content:"\f2b2"}.fa-thermometer:before{content:"\f491"}.fa-thermometer-empty:before{content:"\f2cb"}.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-think-peaks:before{content:"\f731"}.fa-thumbs-down:before{content:"\f165"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbtack:before{content:"\f08d"}.fa-ticket-alt:before{content:"\f3ff"}.fa-times:before{content:"\f00d"}.fa-times-circle:before{content:"\f057"}.fa-tint:before{content:"\f043"}.fa-tint-slash:before{content:"\f5c7"}.fa-tired:before{content:"\f5c8"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-toilet:before{content:"\f7d8"}.fa-toilet-paper:before{content:"\f71e"}.fa-toolbox:before{content:"\f552"}.fa-tools:before{content:"\f7d9"}.fa-tooth:before{content:"\f5c9"}.fa-torah:before{content:"\f6a0"}.fa-torii-gate:before{content:"\f6a1"}.fa-tractor:before{content:"\f722"}.fa-trade-federation:before{content:"\f513"}.fa-trademark:before{content:"\f25c"}.fa-traffic-light:before{content:"\f637"}.fa-trailer:before{content:"\f941"}.fa-train:before{content:"\f238"}.fa-tram:before{content:"\f7da"}.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-trash:before{content:"\f1f8"}.fa-trash-alt:before{content:"\f2ed"}.fa-trash-restore:before{content:"\f829"}.fa-trash-restore-alt:before{content:"\f82a"}.fa-tree:before{content:"\f1bb"}.fa-trello:before{content:"\f181"}.fa-tripadvisor:before{content:"\f262"}.fa-trophy:before{content:"\f091"}.fa-truck:before{content:"\f0d1"}.fa-truck-loading:before{content:"\f4de"}.fa-truck-monster:before{content:"\f63b"}.fa-truck-moving:before{content:"\f4df"}.fa-truck-pickup:before{content:"\f63c"}.fa-tshirt:before{content:"\f553"}.fa-tty:before{content:"\f1e4"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-tv:before{content:"\f26c"}.fa-twitch:before{content:"\f1e8"}.fa-twitter:before{content:"\f099"}.fa-twitter-square:before{content:"\f081"}.fa-typo3:before{content:"\f42b"}.fa-uber:before{content:"\f402"}.fa-ubuntu:before{content:"\f7df"}.fa-uikit:before{content:"\f403"}.fa-umbraco:before{content:"\f8e8"}.fa-umbrella:before{content:"\f0e9"}.fa-umbrella-beach:before{content:"\f5ca"}.fa-underline:before{content:"\f0cd"}.fa-undo:before{content:"\f0e2"}.fa-undo-alt:before{content:"\f2ea"}.fa-uniregistry:before{content:"\f404"}.fa-unity:before{content:"\f949"}.fa-universal-access:before{content:"\f29a"}.fa-university:before{content:"\f19c"}.fa-unlink:before{content:"\f127"}.fa-unlock:before{content:"\f09c"}.fa-unlock-alt:before{content:"\f13e"}.fa-untappd:before{content:"\f405"}.fa-upload:before{content:"\f093"}.fa-ups:before{content:"\f7e0"}.fa-usb:before{content:"\f287"}.fa-user:before{content:"\f007"}.fa-user-alt:before{content:"\f406"}.fa-user-alt-slash:before{content:"\f4fa"}.fa-user-astronaut:before{content:"\f4fb"}.fa-user-check:before{content:"\f4fc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-clock:before{content:"\f4fd"}.fa-user-cog:before{content:"\f4fe"}.fa-user-edit:before{content:"\f4ff"}.fa-user-friends:before{content:"\f500"}.fa-user-graduate:before{content:"\f501"}.fa-user-injured:before{content:"\f728"}.fa-user-lock:before{content:"\f502"}.fa-user-md:before{content:"\f0f0"}.fa-user-minus:before{content:"\f503"}.fa-user-ninja:before{content:"\f504"}.fa-user-nurse:before{content:"\f82f"}.fa-user-plus:before{content:"\f234"}.fa-user-secret:before{content:"\f21b"}.fa-user-shield:before{content:"\f505"}.fa-user-slash:before{content:"\f506"}.fa-user-tag:before{content:"\f507"}.fa-user-tie:before{content:"\f508"}.fa-user-times:before{content:"\f235"}.fa-users:before{content:"\f0c0"}.fa-users-cog:before{content:"\f509"}.fa-usps:before{content:"\f7e1"}.fa-ussunnah:before{content:"\f407"}.fa-utensil-spoon:before{content:"\f2e5"}.fa-utensils:before{content:"\f2e7"}.fa-vaadin:before{content:"\f408"}.fa-vector-square:before{content:"\f5cb"}.fa-venus:before{content:"\f221"}.fa-venus-double:before{content:"\f226"}.fa-venus-mars:before{content:"\f228"}.fa-viacoin:before{content:"\f237"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-vial:before{content:"\f492"}.fa-vials:before{content:"\f493"}.fa-viber:before{content:"\f409"}.fa-video:before{content:"\f03d"}.fa-video-slash:before{content:"\f4e2"}.fa-vihara:before{content:"\f6a7"}.fa-vimeo:before{content:"\f40a"}.fa-vimeo-square:before{content:"\f194"}.fa-vimeo-v:before{content:"\f27d"}.fa-vine:before{content:"\f1ca"}.fa-vk:before{content:"\f189"}.fa-vnv:before{content:"\f40b"}.fa-voicemail:before{content:"\f897"}.fa-volleyball-ball:before{content:"\f45f"}.fa-volume-down:before{content:"\f027"}.fa-volume-mute:before{content:"\f6a9"}.fa-volume-off:before{content:"\f026"}.fa-volume-up:before{content:"\f028"}.fa-vote-yea:before{content:"\f772"}.fa-vr-cardboard:before{content:"\f729"}.fa-vuejs:before{content:"\f41f"}.fa-walking:before{content:"\f554"}.fa-wallet:before{content:"\f555"}.fa-warehouse:before{content:"\f494"}.fa-water:before{content:"\f773"}.fa-wave-square:before{content:"\f83e"}.fa-waze:before{content:"\f83f"}.fa-weebly:before{content:"\f5cc"}.fa-weibo:before{content:"\f18a"}.fa-weight:before{content:"\f496"}.fa-weight-hanging:before{content:"\f5cd"}.fa-weixin:before{content:"\f1d7"}.fa-whatsapp:before{content:"\f232"}.fa-whatsapp-square:before{content:"\f40c"}.fa-wheelchair:before{content:"\f193"}.fa-whmcs:before{content:"\f40d"}.fa-wifi:before{content:"\f1eb"}.fa-wikipedia-w:before{content:"\f266"}.fa-wind:before{content:"\f72e"}.fa-window-close:before{content:"\f410"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-windows:before{content:"\f17a"}.fa-wine-bottle:before{content:"\f72f"}.fa-wine-glass:before{content:"\f4e3"}.fa-wine-glass-alt:before{content:"\f5ce"}.fa-wix:before{content:"\f5cf"}.fa-wizards-of-the-coast:before{content:"\f730"}.fa-wolf-pack-battalion:before{content:"\f514"}.fa-won-sign:before{content:"\f159"}.fa-wordpress:before{content:"\f19a"}.fa-wordpress-simple:before{content:"\f411"}.fa-wpbeginner:before{content:"\f297"}.fa-wpexplorer:before{content:"\f2de"}.fa-wpforms:before{content:"\f298"}.fa-wpressr:before{content:"\f3e4"}.fa-wrench:before{content:"\f0ad"}.fa-x-ray:before{content:"\f497"}.fa-xbox:before{content:"\f412"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-y-combinator:before{content:"\f23b"}.fa-yahoo:before{content:"\f19e"}.fa-yammer:before{content:"\f840"}.fa-yandex:before{content:"\f413"}.fa-yandex-international:before{content:"\f414"}.fa-yarn:before{content:"\f7e3"}.fa-yelp:before{content:"\f1e9"}.fa-yen-sign:before{content:"\f157"}.fa-yin-yang:before{content:"\f6ad"}.fa-yoast:before{content:"\f2b1"}.fa-youtube:before{content:"\f167"}.fa-youtube-square:before{content:"\f431"}.fa-zhihu:before{content:"\f63f"}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto} \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/regular.css b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/regular.css new file mode 100755 index 0000000..7e70f66 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/regular.css @@ -0,0 +1,15 @@ +/*! + * Font Awesome Free 5.12.1 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +@font-face { + font-family: 'Font Awesome 5 Free'; + font-style: normal; + font-weight: 400; + font-display: auto; + src: url("../webfonts/fa-regular-400.eot"); + src: url("../webfonts/fa-regular-400.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.woff") format("woff"), url("../webfonts/fa-regular-400.ttf") format("truetype"), url("../webfonts/fa-regular-400.svg#fontawesome") format("svg"); } + +.far { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/regular.min.css b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/regular.min.css new file mode 100755 index 0000000..0d04bb8 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/regular.min.css @@ -0,0 +1,5 @@ +/*! + * Font Awesome Free 5.12.1 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:400;font-display:auto;src:url(../webfonts/fa-regular-400.eot);src:url(../webfonts/fa-regular-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.woff) format("woff"),url(../webfonts/fa-regular-400.ttf) format("truetype"),url(../webfonts/fa-regular-400.svg#fontawesome) format("svg")}.far{font-family:"Font Awesome 5 Free";font-weight:400} \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/solid.css b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/solid.css new file mode 100755 index 0000000..6ff136a --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/solid.css @@ -0,0 +1,16 @@ +/*! + * Font Awesome Free 5.12.1 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +@font-face { + font-family: 'Font Awesome 5 Free'; + font-style: normal; + font-weight: 900; + font-display: auto; + src: url("../webfonts/fa-solid-900.eot"); + src: url("../webfonts/fa-solid-900.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.woff") format("woff"), url("../webfonts/fa-solid-900.ttf") format("truetype"), url("../webfonts/fa-solid-900.svg#fontawesome") format("svg"); } + +.fa, +.fas { + font-family: 'Font Awesome 5 Free'; + font-weight: 900; } diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/solid.min.css b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/solid.min.css new file mode 100755 index 0000000..d80a5ca --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/solid.min.css @@ -0,0 +1,5 @@ +/*! + * Font Awesome Free 5.12.1 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:900;font-display:auto;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa,.fas{font-family:"Font Awesome 5 Free";font-weight:900} \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/svg-with-js.css b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/svg-with-js.css new file mode 100755 index 0000000..9a7be4a --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/svg-with-js.css @@ -0,0 +1,371 @@ +/*! + * Font Awesome Free 5.12.1 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +svg:not(:root).svg-inline--fa { + overflow: visible; } + +.svg-inline--fa { + display: inline-block; + font-size: inherit; + height: 1em; + overflow: visible; + vertical-align: -.125em; } + .svg-inline--fa.fa-lg { + vertical-align: -.225em; } + .svg-inline--fa.fa-w-1 { + width: 0.0625em; } + .svg-inline--fa.fa-w-2 { + width: 0.125em; } + .svg-inline--fa.fa-w-3 { + width: 0.1875em; } + .svg-inline--fa.fa-w-4 { + width: 0.25em; } + .svg-inline--fa.fa-w-5 { + width: 0.3125em; } + .svg-inline--fa.fa-w-6 { + width: 0.375em; } + .svg-inline--fa.fa-w-7 { + width: 0.4375em; } + .svg-inline--fa.fa-w-8 { + width: 0.5em; } + .svg-inline--fa.fa-w-9 { + width: 0.5625em; } + .svg-inline--fa.fa-w-10 { + width: 0.625em; } + .svg-inline--fa.fa-w-11 { + width: 0.6875em; } + .svg-inline--fa.fa-w-12 { + width: 0.75em; } + .svg-inline--fa.fa-w-13 { + width: 0.8125em; } + .svg-inline--fa.fa-w-14 { + width: 0.875em; } + .svg-inline--fa.fa-w-15 { + width: 0.9375em; } + .svg-inline--fa.fa-w-16 { + width: 1em; } + .svg-inline--fa.fa-w-17 { + width: 1.0625em; } + .svg-inline--fa.fa-w-18 { + width: 1.125em; } + .svg-inline--fa.fa-w-19 { + width: 1.1875em; } + .svg-inline--fa.fa-w-20 { + width: 1.25em; } + .svg-inline--fa.fa-pull-left { + margin-right: .3em; + width: auto; } + .svg-inline--fa.fa-pull-right { + margin-left: .3em; + width: auto; } + .svg-inline--fa.fa-border { + height: 1.5em; } + .svg-inline--fa.fa-li { + width: 2em; } + .svg-inline--fa.fa-fw { + width: 1.25em; } + +.fa-layers svg.svg-inline--fa { + bottom: 0; + left: 0; + margin: auto; + position: absolute; + right: 0; + top: 0; } + +.fa-layers { + display: inline-block; + height: 1em; + position: relative; + text-align: center; + vertical-align: -.125em; + width: 1em; } + .fa-layers svg.svg-inline--fa { + -webkit-transform-origin: center center; + transform-origin: center center; } + +.fa-layers-text, .fa-layers-counter { + display: inline-block; + position: absolute; + text-align: center; } + +.fa-layers-text { + left: 50%; + top: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + -webkit-transform-origin: center center; + transform-origin: center center; } + +.fa-layers-counter { + background-color: #ff253a; + border-radius: 1em; + -webkit-box-sizing: border-box; + box-sizing: border-box; + color: #fff; + height: 1.5em; + line-height: 1; + max-width: 5em; + min-width: 1.5em; + overflow: hidden; + padding: .25em; + right: 0; + text-overflow: ellipsis; + top: 0; + -webkit-transform: scale(0.25); + transform: scale(0.25); + -webkit-transform-origin: top right; + transform-origin: top right; } + +.fa-layers-bottom-right { + bottom: 0; + right: 0; + top: auto; + -webkit-transform: scale(0.25); + transform: scale(0.25); + -webkit-transform-origin: bottom right; + transform-origin: bottom right; } + +.fa-layers-bottom-left { + bottom: 0; + left: 0; + right: auto; + top: auto; + -webkit-transform: scale(0.25); + transform: scale(0.25); + -webkit-transform-origin: bottom left; + transform-origin: bottom left; } + +.fa-layers-top-right { + right: 0; + top: 0; + -webkit-transform: scale(0.25); + transform: scale(0.25); + -webkit-transform-origin: top right; + transform-origin: top right; } + +.fa-layers-top-left { + left: 0; + right: auto; + top: 0; + -webkit-transform: scale(0.25); + transform: scale(0.25); + -webkit-transform-origin: top left; + transform-origin: top left; } + +.fa-lg { + font-size: 1.33333em; + line-height: 0.75em; + vertical-align: -.0667em; } + +.fa-xs { + font-size: .75em; } + +.fa-sm { + font-size: .875em; } + +.fa-1x { + font-size: 1em; } + +.fa-2x { + font-size: 2em; } + +.fa-3x { + font-size: 3em; } + +.fa-4x { + font-size: 4em; } + +.fa-5x { + font-size: 5em; } + +.fa-6x { + font-size: 6em; } + +.fa-7x { + font-size: 7em; } + +.fa-8x { + font-size: 8em; } + +.fa-9x { + font-size: 9em; } + +.fa-10x { + font-size: 10em; } + +.fa-fw { + text-align: center; + width: 1.25em; } + +.fa-ul { + list-style-type: none; + margin-left: 2.5em; + padding-left: 0; } + .fa-ul > li { + position: relative; } + +.fa-li { + left: -2em; + position: absolute; + text-align: center; + width: 2em; + line-height: inherit; } + +.fa-border { + border: solid 0.08em #eee; + border-radius: .1em; + padding: .2em .25em .15em; } + +.fa-pull-left { + float: left; } + +.fa-pull-right { + float: right; } + +.fa.fa-pull-left, +.fas.fa-pull-left, +.far.fa-pull-left, +.fal.fa-pull-left, +.fab.fa-pull-left { + margin-right: .3em; } + +.fa.fa-pull-right, +.fas.fa-pull-right, +.far.fa-pull-right, +.fal.fa-pull-right, +.fab.fa-pull-right { + margin-left: .3em; } + +.fa-spin { + -webkit-animation: fa-spin 2s infinite linear; + animation: fa-spin 2s infinite linear; } + +.fa-pulse { + -webkit-animation: fa-spin 1s infinite steps(8); + animation: fa-spin 1s infinite steps(8); } + +@-webkit-keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); } } + +@keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); } } + +.fa-rotate-90 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)"; + -webkit-transform: rotate(90deg); + transform: rotate(90deg); } + +.fa-rotate-180 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)"; + -webkit-transform: rotate(180deg); + transform: rotate(180deg); } + +.fa-rotate-270 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)"; + -webkit-transform: rotate(270deg); + transform: rotate(270deg); } + +.fa-flip-horizontal { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)"; + -webkit-transform: scale(-1, 1); + transform: scale(-1, 1); } + +.fa-flip-vertical { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; + -webkit-transform: scale(1, -1); + transform: scale(1, -1); } + +.fa-flip-both, .fa-flip-horizontal.fa-flip-vertical { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; + -webkit-transform: scale(-1, -1); + transform: scale(-1, -1); } + +:root .fa-rotate-90, +:root .fa-rotate-180, +:root .fa-rotate-270, +:root .fa-flip-horizontal, +:root .fa-flip-vertical, +:root .fa-flip-both { + -webkit-filter: none; + filter: none; } + +.fa-stack { + display: inline-block; + height: 2em; + position: relative; + width: 2.5em; } + +.fa-stack-1x, +.fa-stack-2x { + bottom: 0; + left: 0; + margin: auto; + position: absolute; + right: 0; + top: 0; } + +.svg-inline--fa.fa-stack-1x { + height: 1em; + width: 1.25em; } + +.svg-inline--fa.fa-stack-2x { + height: 2em; + width: 2.5em; } + +.fa-inverse { + color: #fff; } + +.sr-only { + border: 0; + clip: rect(0, 0, 0, 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; } + +.sr-only-focusable:active, .sr-only-focusable:focus { + clip: auto; + height: auto; + margin: 0; + overflow: visible; + position: static; + width: auto; } + +.svg-inline--fa .fa-primary { + fill: var(--fa-primary-color, currentColor); + opacity: 1; + opacity: var(--fa-primary-opacity, 1); } + +.svg-inline--fa .fa-secondary { + fill: var(--fa-secondary-color, currentColor); + opacity: 0.4; + opacity: var(--fa-secondary-opacity, 0.4); } + +.svg-inline--fa.fa-swap-opacity .fa-primary { + opacity: 0.4; + opacity: var(--fa-secondary-opacity, 0.4); } + +.svg-inline--fa.fa-swap-opacity .fa-secondary { + opacity: 1; + opacity: var(--fa-primary-opacity, 1); } + +.svg-inline--fa mask .fa-primary, +.svg-inline--fa mask .fa-secondary { + fill: black; } + +.fad.fa-inverse { + color: #fff; } diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/svg-with-js.min.css b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/svg-with-js.min.css new file mode 100755 index 0000000..5e158fa --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/svg-with-js.min.css @@ -0,0 +1,5 @@ +/*! + * Font Awesome Free 5.12.1 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +.svg-inline--fa,svg:not(:root).svg-inline--fa{overflow:visible}.svg-inline--fa{display:inline-block;font-size:inherit;height:1em;vertical-align:-.125em}.svg-inline--fa.fa-lg{vertical-align:-.225em}.svg-inline--fa.fa-w-1{width:.0625em}.svg-inline--fa.fa-w-2{width:.125em}.svg-inline--fa.fa-w-3{width:.1875em}.svg-inline--fa.fa-w-4{width:.25em}.svg-inline--fa.fa-w-5{width:.3125em}.svg-inline--fa.fa-w-6{width:.375em}.svg-inline--fa.fa-w-7{width:.4375em}.svg-inline--fa.fa-w-8{width:.5em}.svg-inline--fa.fa-w-9{width:.5625em}.svg-inline--fa.fa-w-10{width:.625em}.svg-inline--fa.fa-w-11{width:.6875em}.svg-inline--fa.fa-w-12{width:.75em}.svg-inline--fa.fa-w-13{width:.8125em}.svg-inline--fa.fa-w-14{width:.875em}.svg-inline--fa.fa-w-15{width:.9375em}.svg-inline--fa.fa-w-16{width:1em}.svg-inline--fa.fa-w-17{width:1.0625em}.svg-inline--fa.fa-w-18{width:1.125em}.svg-inline--fa.fa-w-19{width:1.1875em}.svg-inline--fa.fa-w-20{width:1.25em}.svg-inline--fa.fa-pull-left{margin-right:.3em;width:auto}.svg-inline--fa.fa-pull-right{margin-left:.3em;width:auto}.svg-inline--fa.fa-border{height:1.5em}.svg-inline--fa.fa-li{width:2em}.svg-inline--fa.fa-fw{width:1.25em}.fa-layers svg.svg-inline--fa{bottom:0;left:0;margin:auto;position:absolute;right:0;top:0}.fa-layers{display:inline-block;height:1em;position:relative;text-align:center;vertical-align:-.125em;width:1em}.fa-layers svg.svg-inline--fa{-webkit-transform-origin:center center;transform-origin:center center}.fa-layers-counter,.fa-layers-text{display:inline-block;position:absolute;text-align:center}.fa-layers-text{left:50%;top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);-webkit-transform-origin:center center;transform-origin:center center}.fa-layers-counter{background-color:#ff253a;border-radius:1em;-webkit-box-sizing:border-box;box-sizing:border-box;color:#fff;height:1.5em;line-height:1;max-width:5em;min-width:1.5em;overflow:hidden;padding:.25em;right:0;text-overflow:ellipsis;top:0;-webkit-transform:scale(.25);transform:scale(.25);-webkit-transform-origin:top right;transform-origin:top right}.fa-layers-bottom-right{bottom:0;right:0;top:auto;-webkit-transform:scale(.25);transform:scale(.25);-webkit-transform-origin:bottom right;transform-origin:bottom right}.fa-layers-bottom-left{bottom:0;left:0;right:auto;top:auto;-webkit-transform:scale(.25);transform:scale(.25);-webkit-transform-origin:bottom left;transform-origin:bottom left}.fa-layers-top-right{right:0;top:0;-webkit-transform:scale(.25);transform:scale(.25);-webkit-transform-origin:top right;transform-origin:top right}.fa-layers-top-left{left:0;right:auto;top:0;-webkit-transform:scale(.25);transform:scale(.25);-webkit-transform-origin:top left;transform-origin:top left}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:.08em solid #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fab.fa-pull-left,.fal.fa-pull-left,.far.fa-pull-left,.fas.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fab.fa-pull-right,.fal.fa-pull-right,.far.fa-pull-right,.fas.fa-pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-webkit-transform:scaleY(-1);transform:scaleY(-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical,.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-webkit-transform:scale(-1);transform:scale(-1)}:root .fa-flip-both,:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{-webkit-filter:none;filter:none}.fa-stack{display:inline-block;height:2em;position:relative;width:2.5em}.fa-stack-1x,.fa-stack-2x{bottom:0;left:0;margin:auto;position:absolute;right:0;top:0}.svg-inline--fa.fa-stack-1x{height:1em;width:1.25em}.svg-inline--fa.fa-stack-2x{height:2em;width:2.5em}.fa-inverse{color:#fff}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.svg-inline--fa .fa-primary{fill:var(--fa-primary-color,currentColor);opacity:1;opacity:var(--fa-primary-opacity,1)}.svg-inline--fa .fa-secondary{fill:var(--fa-secondary-color,currentColor)}.svg-inline--fa .fa-secondary,.svg-inline--fa.fa-swap-opacity .fa-primary{opacity:.4;opacity:var(--fa-secondary-opacity,.4)}.svg-inline--fa.fa-swap-opacity .fa-secondary{opacity:1;opacity:var(--fa-primary-opacity,1)}.svg-inline--fa mask .fa-primary,.svg-inline--fa mask .fa-secondary{fill:#000}.fad.fa-inverse{color:#fff} \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/v4-shims.css b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/v4-shims.css new file mode 100755 index 0000000..9e07742 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/v4-shims.css @@ -0,0 +1,2172 @@ +/*! + * Font Awesome Free 5.12.1 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +.fa.fa-glass:before { + content: "\f000"; } + +.fa.fa-meetup { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-star-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-star-o:before { + content: "\f005"; } + +.fa.fa-remove:before { + content: "\f00d"; } + +.fa.fa-close:before { + content: "\f00d"; } + +.fa.fa-gear:before { + content: "\f013"; } + +.fa.fa-trash-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-trash-o:before { + content: "\f2ed"; } + +.fa.fa-file-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-o:before { + content: "\f15b"; } + +.fa.fa-clock-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-clock-o:before { + content: "\f017"; } + +.fa.fa-arrow-circle-o-down { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-arrow-circle-o-down:before { + content: "\f358"; } + +.fa.fa-arrow-circle-o-up { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-arrow-circle-o-up:before { + content: "\f35b"; } + +.fa.fa-play-circle-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-play-circle-o:before { + content: "\f144"; } + +.fa.fa-repeat:before { + content: "\f01e"; } + +.fa.fa-rotate-right:before { + content: "\f01e"; } + +.fa.fa-refresh:before { + content: "\f021"; } + +.fa.fa-list-alt { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-dedent:before { + content: "\f03b"; } + +.fa.fa-video-camera:before { + content: "\f03d"; } + +.fa.fa-picture-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-picture-o:before { + content: "\f03e"; } + +.fa.fa-photo { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-photo:before { + content: "\f03e"; } + +.fa.fa-image { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-image:before { + content: "\f03e"; } + +.fa.fa-pencil:before { + content: "\f303"; } + +.fa.fa-map-marker:before { + content: "\f3c5"; } + +.fa.fa-pencil-square-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-pencil-square-o:before { + content: "\f044"; } + +.fa.fa-share-square-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-share-square-o:before { + content: "\f14d"; } + +.fa.fa-check-square-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-check-square-o:before { + content: "\f14a"; } + +.fa.fa-arrows:before { + content: "\f0b2"; } + +.fa.fa-times-circle-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-times-circle-o:before { + content: "\f057"; } + +.fa.fa-check-circle-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-check-circle-o:before { + content: "\f058"; } + +.fa.fa-mail-forward:before { + content: "\f064"; } + +.fa.fa-expand:before { + content: "\f424"; } + +.fa.fa-compress:before { + content: "\f422"; } + +.fa.fa-eye { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-eye-slash { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-warning:before { + content: "\f071"; } + +.fa.fa-calendar:before { + content: "\f073"; } + +.fa.fa-arrows-v:before { + content: "\f338"; } + +.fa.fa-arrows-h:before { + content: "\f337"; } + +.fa.fa-bar-chart { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-bar-chart:before { + content: "\f080"; } + +.fa.fa-bar-chart-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-bar-chart-o:before { + content: "\f080"; } + +.fa.fa-twitter-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-facebook-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-gears:before { + content: "\f085"; } + +.fa.fa-thumbs-o-up { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-thumbs-o-up:before { + content: "\f164"; } + +.fa.fa-thumbs-o-down { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-thumbs-o-down:before { + content: "\f165"; } + +.fa.fa-heart-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-heart-o:before { + content: "\f004"; } + +.fa.fa-sign-out:before { + content: "\f2f5"; } + +.fa.fa-linkedin-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-linkedin-square:before { + content: "\f08c"; } + +.fa.fa-thumb-tack:before { + content: "\f08d"; } + +.fa.fa-external-link:before { + content: "\f35d"; } + +.fa.fa-sign-in:before { + content: "\f2f6"; } + +.fa.fa-github-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-lemon-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-lemon-o:before { + content: "\f094"; } + +.fa.fa-square-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-square-o:before { + content: "\f0c8"; } + +.fa.fa-bookmark-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-bookmark-o:before { + content: "\f02e"; } + +.fa.fa-twitter { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-facebook { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-facebook:before { + content: "\f39e"; } + +.fa.fa-facebook-f { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-facebook-f:before { + content: "\f39e"; } + +.fa.fa-github { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-credit-card { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-feed:before { + content: "\f09e"; } + +.fa.fa-hdd-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hdd-o:before { + content: "\f0a0"; } + +.fa.fa-hand-o-right { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hand-o-right:before { + content: "\f0a4"; } + +.fa.fa-hand-o-left { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hand-o-left:before { + content: "\f0a5"; } + +.fa.fa-hand-o-up { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hand-o-up:before { + content: "\f0a6"; } + +.fa.fa-hand-o-down { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hand-o-down:before { + content: "\f0a7"; } + +.fa.fa-arrows-alt:before { + content: "\f31e"; } + +.fa.fa-group:before { + content: "\f0c0"; } + +.fa.fa-chain:before { + content: "\f0c1"; } + +.fa.fa-scissors:before { + content: "\f0c4"; } + +.fa.fa-files-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-files-o:before { + content: "\f0c5"; } + +.fa.fa-floppy-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-floppy-o:before { + content: "\f0c7"; } + +.fa.fa-navicon:before { + content: "\f0c9"; } + +.fa.fa-reorder:before { + content: "\f0c9"; } + +.fa.fa-pinterest { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-pinterest-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-google-plus-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-google-plus { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-google-plus:before { + content: "\f0d5"; } + +.fa.fa-money { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-money:before { + content: "\f3d1"; } + +.fa.fa-unsorted:before { + content: "\f0dc"; } + +.fa.fa-sort-desc:before { + content: "\f0dd"; } + +.fa.fa-sort-asc:before { + content: "\f0de"; } + +.fa.fa-linkedin { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-linkedin:before { + content: "\f0e1"; } + +.fa.fa-rotate-left:before { + content: "\f0e2"; } + +.fa.fa-legal:before { + content: "\f0e3"; } + +.fa.fa-tachometer:before { + content: "\f3fd"; } + +.fa.fa-dashboard:before { + content: "\f3fd"; } + +.fa.fa-comment-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-comment-o:before { + content: "\f075"; } + +.fa.fa-comments-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-comments-o:before { + content: "\f086"; } + +.fa.fa-flash:before { + content: "\f0e7"; } + +.fa.fa-clipboard { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-paste { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-paste:before { + content: "\f328"; } + +.fa.fa-lightbulb-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-lightbulb-o:before { + content: "\f0eb"; } + +.fa.fa-exchange:before { + content: "\f362"; } + +.fa.fa-cloud-download:before { + content: "\f381"; } + +.fa.fa-cloud-upload:before { + content: "\f382"; } + +.fa.fa-bell-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-bell-o:before { + content: "\f0f3"; } + +.fa.fa-cutlery:before { + content: "\f2e7"; } + +.fa.fa-file-text-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-text-o:before { + content: "\f15c"; } + +.fa.fa-building-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-building-o:before { + content: "\f1ad"; } + +.fa.fa-hospital-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hospital-o:before { + content: "\f0f8"; } + +.fa.fa-tablet:before { + content: "\f3fa"; } + +.fa.fa-mobile:before { + content: "\f3cd"; } + +.fa.fa-mobile-phone:before { + content: "\f3cd"; } + +.fa.fa-circle-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-circle-o:before { + content: "\f111"; } + +.fa.fa-mail-reply:before { + content: "\f3e5"; } + +.fa.fa-github-alt { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-folder-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-folder-o:before { + content: "\f07b"; } + +.fa.fa-folder-open-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-folder-open-o:before { + content: "\f07c"; } + +.fa.fa-smile-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-smile-o:before { + content: "\f118"; } + +.fa.fa-frown-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-frown-o:before { + content: "\f119"; } + +.fa.fa-meh-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-meh-o:before { + content: "\f11a"; } + +.fa.fa-keyboard-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-keyboard-o:before { + content: "\f11c"; } + +.fa.fa-flag-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-flag-o:before { + content: "\f024"; } + +.fa.fa-mail-reply-all:before { + content: "\f122"; } + +.fa.fa-star-half-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-star-half-o:before { + content: "\f089"; } + +.fa.fa-star-half-empty { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-star-half-empty:before { + content: "\f089"; } + +.fa.fa-star-half-full { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-star-half-full:before { + content: "\f089"; } + +.fa.fa-code-fork:before { + content: "\f126"; } + +.fa.fa-chain-broken:before { + content: "\f127"; } + +.fa.fa-shield:before { + content: "\f3ed"; } + +.fa.fa-calendar-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-calendar-o:before { + content: "\f133"; } + +.fa.fa-maxcdn { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-html5 { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-css3 { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-ticket:before { + content: "\f3ff"; } + +.fa.fa-minus-square-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-minus-square-o:before { + content: "\f146"; } + +.fa.fa-level-up:before { + content: "\f3bf"; } + +.fa.fa-level-down:before { + content: "\f3be"; } + +.fa.fa-pencil-square:before { + content: "\f14b"; } + +.fa.fa-external-link-square:before { + content: "\f360"; } + +.fa.fa-compass { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-caret-square-o-down { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-caret-square-o-down:before { + content: "\f150"; } + +.fa.fa-toggle-down { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-toggle-down:before { + content: "\f150"; } + +.fa.fa-caret-square-o-up { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-caret-square-o-up:before { + content: "\f151"; } + +.fa.fa-toggle-up { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-toggle-up:before { + content: "\f151"; } + +.fa.fa-caret-square-o-right { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-caret-square-o-right:before { + content: "\f152"; } + +.fa.fa-toggle-right { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-toggle-right:before { + content: "\f152"; } + +.fa.fa-eur:before { + content: "\f153"; } + +.fa.fa-euro:before { + content: "\f153"; } + +.fa.fa-gbp:before { + content: "\f154"; } + +.fa.fa-usd:before { + content: "\f155"; } + +.fa.fa-dollar:before { + content: "\f155"; } + +.fa.fa-inr:before { + content: "\f156"; } + +.fa.fa-rupee:before { + content: "\f156"; } + +.fa.fa-jpy:before { + content: "\f157"; } + +.fa.fa-cny:before { + content: "\f157"; } + +.fa.fa-rmb:before { + content: "\f157"; } + +.fa.fa-yen:before { + content: "\f157"; } + +.fa.fa-rub:before { + content: "\f158"; } + +.fa.fa-ruble:before { + content: "\f158"; } + +.fa.fa-rouble:before { + content: "\f158"; } + +.fa.fa-krw:before { + content: "\f159"; } + +.fa.fa-won:before { + content: "\f159"; } + +.fa.fa-btc { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-bitcoin { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-bitcoin:before { + content: "\f15a"; } + +.fa.fa-file-text:before { + content: "\f15c"; } + +.fa.fa-sort-alpha-asc:before { + content: "\f15d"; } + +.fa.fa-sort-alpha-desc:before { + content: "\f881"; } + +.fa.fa-sort-amount-asc:before { + content: "\f160"; } + +.fa.fa-sort-amount-desc:before { + content: "\f884"; } + +.fa.fa-sort-numeric-asc:before { + content: "\f162"; } + +.fa.fa-sort-numeric-desc:before { + content: "\f886"; } + +.fa.fa-youtube-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-youtube { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-xing { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-xing-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-youtube-play { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-youtube-play:before { + content: "\f167"; } + +.fa.fa-dropbox { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-stack-overflow { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-instagram { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-flickr { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-adn { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-bitbucket { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-bitbucket-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-bitbucket-square:before { + content: "\f171"; } + +.fa.fa-tumblr { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-tumblr-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-long-arrow-down:before { + content: "\f309"; } + +.fa.fa-long-arrow-up:before { + content: "\f30c"; } + +.fa.fa-long-arrow-left:before { + content: "\f30a"; } + +.fa.fa-long-arrow-right:before { + content: "\f30b"; } + +.fa.fa-apple { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-windows { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-android { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-linux { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-dribbble { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-skype { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-foursquare { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-trello { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-gratipay { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-gittip { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-gittip:before { + content: "\f184"; } + +.fa.fa-sun-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-sun-o:before { + content: "\f185"; } + +.fa.fa-moon-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-moon-o:before { + content: "\f186"; } + +.fa.fa-vk { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-weibo { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-renren { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-pagelines { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-stack-exchange { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-arrow-circle-o-right { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-arrow-circle-o-right:before { + content: "\f35a"; } + +.fa.fa-arrow-circle-o-left { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-arrow-circle-o-left:before { + content: "\f359"; } + +.fa.fa-caret-square-o-left { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-caret-square-o-left:before { + content: "\f191"; } + +.fa.fa-toggle-left { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-toggle-left:before { + content: "\f191"; } + +.fa.fa-dot-circle-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-dot-circle-o:before { + content: "\f192"; } + +.fa.fa-vimeo-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-try:before { + content: "\f195"; } + +.fa.fa-turkish-lira:before { + content: "\f195"; } + +.fa.fa-plus-square-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-plus-square-o:before { + content: "\f0fe"; } + +.fa.fa-slack { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-wordpress { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-openid { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-institution:before { + content: "\f19c"; } + +.fa.fa-bank:before { + content: "\f19c"; } + +.fa.fa-mortar-board:before { + content: "\f19d"; } + +.fa.fa-yahoo { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-google { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-reddit { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-reddit-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-stumbleupon-circle { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-stumbleupon { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-delicious { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-digg { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-pied-piper-pp { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-pied-piper-alt { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-drupal { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-joomla { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-spoon:before { + content: "\f2e5"; } + +.fa.fa-behance { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-behance-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-steam { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-steam-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-automobile:before { + content: "\f1b9"; } + +.fa.fa-envelope-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-envelope-o:before { + content: "\f0e0"; } + +.fa.fa-spotify { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-deviantart { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-soundcloud { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-file-pdf-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-pdf-o:before { + content: "\f1c1"; } + +.fa.fa-file-word-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-word-o:before { + content: "\f1c2"; } + +.fa.fa-file-excel-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-excel-o:before { + content: "\f1c3"; } + +.fa.fa-file-powerpoint-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-powerpoint-o:before { + content: "\f1c4"; } + +.fa.fa-file-image-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-image-o:before { + content: "\f1c5"; } + +.fa.fa-file-photo-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-photo-o:before { + content: "\f1c5"; } + +.fa.fa-file-picture-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-picture-o:before { + content: "\f1c5"; } + +.fa.fa-file-archive-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-archive-o:before { + content: "\f1c6"; } + +.fa.fa-file-zip-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-zip-o:before { + content: "\f1c6"; } + +.fa.fa-file-audio-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-audio-o:before { + content: "\f1c7"; } + +.fa.fa-file-sound-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-sound-o:before { + content: "\f1c7"; } + +.fa.fa-file-video-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-video-o:before { + content: "\f1c8"; } + +.fa.fa-file-movie-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-movie-o:before { + content: "\f1c8"; } + +.fa.fa-file-code-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-file-code-o:before { + content: "\f1c9"; } + +.fa.fa-vine { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-codepen { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-jsfiddle { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-life-ring { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-life-bouy { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-life-bouy:before { + content: "\f1cd"; } + +.fa.fa-life-buoy { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-life-buoy:before { + content: "\f1cd"; } + +.fa.fa-life-saver { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-life-saver:before { + content: "\f1cd"; } + +.fa.fa-support { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-support:before { + content: "\f1cd"; } + +.fa.fa-circle-o-notch:before { + content: "\f1ce"; } + +.fa.fa-rebel { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-ra { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-ra:before { + content: "\f1d0"; } + +.fa.fa-resistance { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-resistance:before { + content: "\f1d0"; } + +.fa.fa-empire { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-ge { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-ge:before { + content: "\f1d1"; } + +.fa.fa-git-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-git { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-hacker-news { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-y-combinator-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-y-combinator-square:before { + content: "\f1d4"; } + +.fa.fa-yc-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-yc-square:before { + content: "\f1d4"; } + +.fa.fa-tencent-weibo { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-qq { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-weixin { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-wechat { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-wechat:before { + content: "\f1d7"; } + +.fa.fa-send:before { + content: "\f1d8"; } + +.fa.fa-paper-plane-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-paper-plane-o:before { + content: "\f1d8"; } + +.fa.fa-send-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-send-o:before { + content: "\f1d8"; } + +.fa.fa-circle-thin { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-circle-thin:before { + content: "\f111"; } + +.fa.fa-header:before { + content: "\f1dc"; } + +.fa.fa-sliders:before { + content: "\f1de"; } + +.fa.fa-futbol-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-futbol-o:before { + content: "\f1e3"; } + +.fa.fa-soccer-ball-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-soccer-ball-o:before { + content: "\f1e3"; } + +.fa.fa-slideshare { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-twitch { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-yelp { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-newspaper-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-newspaper-o:before { + content: "\f1ea"; } + +.fa.fa-paypal { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-google-wallet { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-cc-visa { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-cc-mastercard { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-cc-discover { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-cc-amex { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-cc-paypal { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-cc-stripe { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-bell-slash-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-bell-slash-o:before { + content: "\f1f6"; } + +.fa.fa-trash:before { + content: "\f2ed"; } + +.fa.fa-copyright { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-eyedropper:before { + content: "\f1fb"; } + +.fa.fa-area-chart:before { + content: "\f1fe"; } + +.fa.fa-pie-chart:before { + content: "\f200"; } + +.fa.fa-line-chart:before { + content: "\f201"; } + +.fa.fa-lastfm { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-lastfm-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-ioxhost { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-angellist { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-cc { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-cc:before { + content: "\f20a"; } + +.fa.fa-ils:before { + content: "\f20b"; } + +.fa.fa-shekel:before { + content: "\f20b"; } + +.fa.fa-sheqel:before { + content: "\f20b"; } + +.fa.fa-meanpath { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-meanpath:before { + content: "\f2b4"; } + +.fa.fa-buysellads { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-connectdevelop { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-dashcube { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-forumbee { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-leanpub { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-sellsy { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-shirtsinbulk { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-simplybuilt { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-skyatlas { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-diamond { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-diamond:before { + content: "\f3a5"; } + +.fa.fa-intersex:before { + content: "\f224"; } + +.fa.fa-facebook-official { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-facebook-official:before { + content: "\f09a"; } + +.fa.fa-pinterest-p { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-whatsapp { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-hotel:before { + content: "\f236"; } + +.fa.fa-viacoin { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-medium { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-y-combinator { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-yc { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-yc:before { + content: "\f23b"; } + +.fa.fa-optin-monster { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-opencart { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-expeditedssl { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-battery-4:before { + content: "\f240"; } + +.fa.fa-battery:before { + content: "\f240"; } + +.fa.fa-battery-3:before { + content: "\f241"; } + +.fa.fa-battery-2:before { + content: "\f242"; } + +.fa.fa-battery-1:before { + content: "\f243"; } + +.fa.fa-battery-0:before { + content: "\f244"; } + +.fa.fa-object-group { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-object-ungroup { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-sticky-note-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-sticky-note-o:before { + content: "\f249"; } + +.fa.fa-cc-jcb { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-cc-diners-club { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-clone { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hourglass-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hourglass-o:before { + content: "\f254"; } + +.fa.fa-hourglass-1:before { + content: "\f251"; } + +.fa.fa-hourglass-2:before { + content: "\f252"; } + +.fa.fa-hourglass-3:before { + content: "\f253"; } + +.fa.fa-hand-rock-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hand-rock-o:before { + content: "\f255"; } + +.fa.fa-hand-grab-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hand-grab-o:before { + content: "\f255"; } + +.fa.fa-hand-paper-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hand-paper-o:before { + content: "\f256"; } + +.fa.fa-hand-stop-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hand-stop-o:before { + content: "\f256"; } + +.fa.fa-hand-scissors-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hand-scissors-o:before { + content: "\f257"; } + +.fa.fa-hand-lizard-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hand-lizard-o:before { + content: "\f258"; } + +.fa.fa-hand-spock-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hand-spock-o:before { + content: "\f259"; } + +.fa.fa-hand-pointer-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hand-pointer-o:before { + content: "\f25a"; } + +.fa.fa-hand-peace-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-hand-peace-o:before { + content: "\f25b"; } + +.fa.fa-registered { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-creative-commons { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-gg { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-gg-circle { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-tripadvisor { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-odnoklassniki { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-odnoklassniki-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-get-pocket { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-wikipedia-w { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-safari { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-chrome { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-firefox { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-opera { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-internet-explorer { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-television:before { + content: "\f26c"; } + +.fa.fa-contao { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-500px { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-amazon { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-calendar-plus-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-calendar-plus-o:before { + content: "\f271"; } + +.fa.fa-calendar-minus-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-calendar-minus-o:before { + content: "\f272"; } + +.fa.fa-calendar-times-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-calendar-times-o:before { + content: "\f273"; } + +.fa.fa-calendar-check-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-calendar-check-o:before { + content: "\f274"; } + +.fa.fa-map-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-map-o:before { + content: "\f279"; } + +.fa.fa-commenting:before { + content: "\f4ad"; } + +.fa.fa-commenting-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-commenting-o:before { + content: "\f4ad"; } + +.fa.fa-houzz { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-vimeo { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-vimeo:before { + content: "\f27d"; } + +.fa.fa-black-tie { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-fonticons { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-reddit-alien { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-edge { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-credit-card-alt:before { + content: "\f09d"; } + +.fa.fa-codiepie { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-modx { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-fort-awesome { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-usb { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-product-hunt { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-mixcloud { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-scribd { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-pause-circle-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-pause-circle-o:before { + content: "\f28b"; } + +.fa.fa-stop-circle-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-stop-circle-o:before { + content: "\f28d"; } + +.fa.fa-bluetooth { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-bluetooth-b { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-gitlab { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-wpbeginner { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-wpforms { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-envira { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-wheelchair-alt { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-wheelchair-alt:before { + content: "\f368"; } + +.fa.fa-question-circle-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-question-circle-o:before { + content: "\f059"; } + +.fa.fa-volume-control-phone:before { + content: "\f2a0"; } + +.fa.fa-asl-interpreting:before { + content: "\f2a3"; } + +.fa.fa-deafness:before { + content: "\f2a4"; } + +.fa.fa-hard-of-hearing:before { + content: "\f2a4"; } + +.fa.fa-glide { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-glide-g { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-signing:before { + content: "\f2a7"; } + +.fa.fa-viadeo { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-viadeo-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-snapchat { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-snapchat-ghost { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-snapchat-square { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-pied-piper { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-first-order { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-yoast { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-themeisle { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-google-plus-official { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-google-plus-official:before { + content: "\f2b3"; } + +.fa.fa-google-plus-circle { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-google-plus-circle:before { + content: "\f2b3"; } + +.fa.fa-font-awesome { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-fa { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-fa:before { + content: "\f2b4"; } + +.fa.fa-handshake-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-handshake-o:before { + content: "\f2b5"; } + +.fa.fa-envelope-open-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-envelope-open-o:before { + content: "\f2b6"; } + +.fa.fa-linode { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-address-book-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-address-book-o:before { + content: "\f2b9"; } + +.fa.fa-vcard:before { + content: "\f2bb"; } + +.fa.fa-address-card-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-address-card-o:before { + content: "\f2bb"; } + +.fa.fa-vcard-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-vcard-o:before { + content: "\f2bb"; } + +.fa.fa-user-circle-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-user-circle-o:before { + content: "\f2bd"; } + +.fa.fa-user-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-user-o:before { + content: "\f007"; } + +.fa.fa-id-badge { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-drivers-license:before { + content: "\f2c2"; } + +.fa.fa-id-card-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-id-card-o:before { + content: "\f2c2"; } + +.fa.fa-drivers-license-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-drivers-license-o:before { + content: "\f2c2"; } + +.fa.fa-quora { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-free-code-camp { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-telegram { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-thermometer-4:before { + content: "\f2c7"; } + +.fa.fa-thermometer:before { + content: "\f2c7"; } + +.fa.fa-thermometer-3:before { + content: "\f2c8"; } + +.fa.fa-thermometer-2:before { + content: "\f2c9"; } + +.fa.fa-thermometer-1:before { + content: "\f2ca"; } + +.fa.fa-thermometer-0:before { + content: "\f2cb"; } + +.fa.fa-bathtub:before { + content: "\f2cd"; } + +.fa.fa-s15:before { + content: "\f2cd"; } + +.fa.fa-window-maximize { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-window-restore { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-times-rectangle:before { + content: "\f410"; } + +.fa.fa-window-close-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-window-close-o:before { + content: "\f410"; } + +.fa.fa-times-rectangle-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-times-rectangle-o:before { + content: "\f410"; } + +.fa.fa-bandcamp { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-grav { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-etsy { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-imdb { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-ravelry { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-eercast { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-eercast:before { + content: "\f2da"; } + +.fa.fa-snowflake-o { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; } + +.fa.fa-snowflake-o:before { + content: "\f2dc"; } + +.fa.fa-superpowers { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-wpexplorer { + font-family: 'Font Awesome 5 Brands'; + font-weight: 400; } + +.fa.fa-cab:before { + content: "\f1ba"; } diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/v4-shims.min.css b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/v4-shims.min.css new file mode 100755 index 0000000..7942cea --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/css/v4-shims.min.css @@ -0,0 +1,5 @@ +/*! + * Font Awesome Free 5.12.1 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +.fa.fa-glass:before{content:"\f000"}.fa.fa-meetup{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-star-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-star-o:before{content:"\f005"}.fa.fa-close:before,.fa.fa-remove:before{content:"\f00d"}.fa.fa-gear:before{content:"\f013"}.fa.fa-trash-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-trash-o:before{content:"\f2ed"}.fa.fa-file-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-o:before{content:"\f15b"}.fa.fa-clock-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-clock-o:before{content:"\f017"}.fa.fa-arrow-circle-o-down{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-arrow-circle-o-down:before{content:"\f358"}.fa.fa-arrow-circle-o-up{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-arrow-circle-o-up:before{content:"\f35b"}.fa.fa-play-circle-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-play-circle-o:before{content:"\f144"}.fa.fa-repeat:before,.fa.fa-rotate-right:before{content:"\f01e"}.fa.fa-refresh:before{content:"\f021"}.fa.fa-list-alt{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-dedent:before{content:"\f03b"}.fa.fa-video-camera:before{content:"\f03d"}.fa.fa-picture-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-picture-o:before{content:"\f03e"}.fa.fa-photo{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-photo:before{content:"\f03e"}.fa.fa-image{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-image:before{content:"\f03e"}.fa.fa-pencil:before{content:"\f303"}.fa.fa-map-marker:before{content:"\f3c5"}.fa.fa-pencil-square-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-pencil-square-o:before{content:"\f044"}.fa.fa-share-square-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-share-square-o:before{content:"\f14d"}.fa.fa-check-square-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-check-square-o:before{content:"\f14a"}.fa.fa-arrows:before{content:"\f0b2"}.fa.fa-times-circle-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-times-circle-o:before{content:"\f057"}.fa.fa-check-circle-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-check-circle-o:before{content:"\f058"}.fa.fa-mail-forward:before{content:"\f064"}.fa.fa-expand:before{content:"\f424"}.fa.fa-compress:before{content:"\f422"}.fa.fa-eye,.fa.fa-eye-slash{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-warning:before{content:"\f071"}.fa.fa-calendar:before{content:"\f073"}.fa.fa-arrows-v:before{content:"\f338"}.fa.fa-arrows-h:before{content:"\f337"}.fa.fa-bar-chart{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-bar-chart:before{content:"\f080"}.fa.fa-bar-chart-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-bar-chart-o:before{content:"\f080"}.fa.fa-facebook-square,.fa.fa-twitter-square{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-gears:before{content:"\f085"}.fa.fa-thumbs-o-up{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-thumbs-o-up:before{content:"\f164"}.fa.fa-thumbs-o-down{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-thumbs-o-down:before{content:"\f165"}.fa.fa-heart-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-heart-o:before{content:"\f004"}.fa.fa-sign-out:before{content:"\f2f5"}.fa.fa-linkedin-square{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-linkedin-square:before{content:"\f08c"}.fa.fa-thumb-tack:before{content:"\f08d"}.fa.fa-external-link:before{content:"\f35d"}.fa.fa-sign-in:before{content:"\f2f6"}.fa.fa-github-square{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-lemon-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-lemon-o:before{content:"\f094"}.fa.fa-square-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-square-o:before{content:"\f0c8"}.fa.fa-bookmark-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-bookmark-o:before{content:"\f02e"}.fa.fa-facebook,.fa.fa-twitter{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-facebook:before{content:"\f39e"}.fa.fa-facebook-f{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-facebook-f:before{content:"\f39e"}.fa.fa-github{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-credit-card{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-feed:before{content:"\f09e"}.fa.fa-hdd-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hdd-o:before{content:"\f0a0"}.fa.fa-hand-o-right{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hand-o-right:before{content:"\f0a4"}.fa.fa-hand-o-left{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hand-o-left:before{content:"\f0a5"}.fa.fa-hand-o-up{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hand-o-up:before{content:"\f0a6"}.fa.fa-hand-o-down{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hand-o-down:before{content:"\f0a7"}.fa.fa-arrows-alt:before{content:"\f31e"}.fa.fa-group:before{content:"\f0c0"}.fa.fa-chain:before{content:"\f0c1"}.fa.fa-scissors:before{content:"\f0c4"}.fa.fa-files-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-files-o:before{content:"\f0c5"}.fa.fa-floppy-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-floppy-o:before{content:"\f0c7"}.fa.fa-navicon:before,.fa.fa-reorder:before{content:"\f0c9"}.fa.fa-google-plus,.fa.fa-google-plus-square,.fa.fa-pinterest,.fa.fa-pinterest-square{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-google-plus:before{content:"\f0d5"}.fa.fa-money{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-money:before{content:"\f3d1"}.fa.fa-unsorted:before{content:"\f0dc"}.fa.fa-sort-desc:before{content:"\f0dd"}.fa.fa-sort-asc:before{content:"\f0de"}.fa.fa-linkedin{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-linkedin:before{content:"\f0e1"}.fa.fa-rotate-left:before{content:"\f0e2"}.fa.fa-legal:before{content:"\f0e3"}.fa.fa-dashboard:before,.fa.fa-tachometer:before{content:"\f3fd"}.fa.fa-comment-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-comment-o:before{content:"\f075"}.fa.fa-comments-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-comments-o:before{content:"\f086"}.fa.fa-flash:before{content:"\f0e7"}.fa.fa-clipboard,.fa.fa-paste{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-paste:before{content:"\f328"}.fa.fa-lightbulb-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-lightbulb-o:before{content:"\f0eb"}.fa.fa-exchange:before{content:"\f362"}.fa.fa-cloud-download:before{content:"\f381"}.fa.fa-cloud-upload:before{content:"\f382"}.fa.fa-bell-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-bell-o:before{content:"\f0f3"}.fa.fa-cutlery:before{content:"\f2e7"}.fa.fa-file-text-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-text-o:before{content:"\f15c"}.fa.fa-building-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-building-o:before{content:"\f1ad"}.fa.fa-hospital-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hospital-o:before{content:"\f0f8"}.fa.fa-tablet:before{content:"\f3fa"}.fa.fa-mobile-phone:before,.fa.fa-mobile:before{content:"\f3cd"}.fa.fa-circle-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-circle-o:before{content:"\f111"}.fa.fa-mail-reply:before{content:"\f3e5"}.fa.fa-github-alt{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-folder-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-folder-o:before{content:"\f07b"}.fa.fa-folder-open-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-folder-open-o:before{content:"\f07c"}.fa.fa-smile-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-smile-o:before{content:"\f118"}.fa.fa-frown-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-frown-o:before{content:"\f119"}.fa.fa-meh-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-meh-o:before{content:"\f11a"}.fa.fa-keyboard-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-keyboard-o:before{content:"\f11c"}.fa.fa-flag-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-flag-o:before{content:"\f024"}.fa.fa-mail-reply-all:before{content:"\f122"}.fa.fa-star-half-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-star-half-o:before{content:"\f089"}.fa.fa-star-half-empty{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-star-half-empty:before{content:"\f089"}.fa.fa-star-half-full{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-star-half-full:before{content:"\f089"}.fa.fa-code-fork:before{content:"\f126"}.fa.fa-chain-broken:before{content:"\f127"}.fa.fa-shield:before{content:"\f3ed"}.fa.fa-calendar-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-calendar-o:before{content:"\f133"}.fa.fa-css3,.fa.fa-html5,.fa.fa-maxcdn{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-ticket:before{content:"\f3ff"}.fa.fa-minus-square-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-minus-square-o:before{content:"\f146"}.fa.fa-level-up:before{content:"\f3bf"}.fa.fa-level-down:before{content:"\f3be"}.fa.fa-pencil-square:before{content:"\f14b"}.fa.fa-external-link-square:before{content:"\f360"}.fa.fa-compass{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-caret-square-o-down{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-caret-square-o-down:before{content:"\f150"}.fa.fa-toggle-down{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-toggle-down:before{content:"\f150"}.fa.fa-caret-square-o-up{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-caret-square-o-up:before{content:"\f151"}.fa.fa-toggle-up{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-toggle-up:before{content:"\f151"}.fa.fa-caret-square-o-right{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-caret-square-o-right:before{content:"\f152"}.fa.fa-toggle-right{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-toggle-right:before{content:"\f152"}.fa.fa-eur:before,.fa.fa-euro:before{content:"\f153"}.fa.fa-gbp:before{content:"\f154"}.fa.fa-dollar:before,.fa.fa-usd:before{content:"\f155"}.fa.fa-inr:before,.fa.fa-rupee:before{content:"\f156"}.fa.fa-cny:before,.fa.fa-jpy:before,.fa.fa-rmb:before,.fa.fa-yen:before{content:"\f157"}.fa.fa-rouble:before,.fa.fa-rub:before,.fa.fa-ruble:before{content:"\f158"}.fa.fa-krw:before,.fa.fa-won:before{content:"\f159"}.fa.fa-bitcoin,.fa.fa-btc{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-bitcoin:before{content:"\f15a"}.fa.fa-file-text:before{content:"\f15c"}.fa.fa-sort-alpha-asc:before{content:"\f15d"}.fa.fa-sort-alpha-desc:before{content:"\f881"}.fa.fa-sort-amount-asc:before{content:"\f160"}.fa.fa-sort-amount-desc:before{content:"\f884"}.fa.fa-sort-numeric-asc:before{content:"\f162"}.fa.fa-sort-numeric-desc:before{content:"\f886"}.fa.fa-xing,.fa.fa-xing-square,.fa.fa-youtube,.fa.fa-youtube-play,.fa.fa-youtube-square{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-youtube-play:before{content:"\f167"}.fa.fa-adn,.fa.fa-bitbucket,.fa.fa-bitbucket-square,.fa.fa-dropbox,.fa.fa-flickr,.fa.fa-instagram,.fa.fa-stack-overflow{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-bitbucket-square:before{content:"\f171"}.fa.fa-tumblr,.fa.fa-tumblr-square{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-long-arrow-down:before{content:"\f309"}.fa.fa-long-arrow-up:before{content:"\f30c"}.fa.fa-long-arrow-left:before{content:"\f30a"}.fa.fa-long-arrow-right:before{content:"\f30b"}.fa.fa-android,.fa.fa-apple,.fa.fa-dribbble,.fa.fa-foursquare,.fa.fa-gittip,.fa.fa-gratipay,.fa.fa-linux,.fa.fa-skype,.fa.fa-trello,.fa.fa-windows{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-gittip:before{content:"\f184"}.fa.fa-sun-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-sun-o:before{content:"\f185"}.fa.fa-moon-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-moon-o:before{content:"\f186"}.fa.fa-pagelines,.fa.fa-renren,.fa.fa-stack-exchange,.fa.fa-vk,.fa.fa-weibo{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-arrow-circle-o-right{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-arrow-circle-o-right:before{content:"\f35a"}.fa.fa-arrow-circle-o-left{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-arrow-circle-o-left:before{content:"\f359"}.fa.fa-caret-square-o-left{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-caret-square-o-left:before{content:"\f191"}.fa.fa-toggle-left{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-toggle-left:before{content:"\f191"}.fa.fa-dot-circle-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-dot-circle-o:before{content:"\f192"}.fa.fa-vimeo-square{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-try:before,.fa.fa-turkish-lira:before{content:"\f195"}.fa.fa-plus-square-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-plus-square-o:before{content:"\f0fe"}.fa.fa-openid,.fa.fa-slack,.fa.fa-wordpress{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-bank:before,.fa.fa-institution:before{content:"\f19c"}.fa.fa-mortar-board:before{content:"\f19d"}.fa.fa-delicious,.fa.fa-digg,.fa.fa-drupal,.fa.fa-google,.fa.fa-joomla,.fa.fa-pied-piper-alt,.fa.fa-pied-piper-pp,.fa.fa-reddit,.fa.fa-reddit-square,.fa.fa-stumbleupon,.fa.fa-stumbleupon-circle,.fa.fa-yahoo{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-spoon:before{content:"\f2e5"}.fa.fa-behance,.fa.fa-behance-square,.fa.fa-steam,.fa.fa-steam-square{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-automobile:before{content:"\f1b9"}.fa.fa-envelope-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-envelope-o:before{content:"\f0e0"}.fa.fa-deviantart,.fa.fa-soundcloud,.fa.fa-spotify{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-file-pdf-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-pdf-o:before{content:"\f1c1"}.fa.fa-file-word-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-word-o:before{content:"\f1c2"}.fa.fa-file-excel-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-excel-o:before{content:"\f1c3"}.fa.fa-file-powerpoint-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-powerpoint-o:before{content:"\f1c4"}.fa.fa-file-image-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-image-o:before{content:"\f1c5"}.fa.fa-file-photo-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-photo-o:before{content:"\f1c5"}.fa.fa-file-picture-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-picture-o:before{content:"\f1c5"}.fa.fa-file-archive-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-archive-o:before{content:"\f1c6"}.fa.fa-file-zip-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-zip-o:before{content:"\f1c6"}.fa.fa-file-audio-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-audio-o:before{content:"\f1c7"}.fa.fa-file-sound-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-sound-o:before{content:"\f1c7"}.fa.fa-file-video-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-video-o:before{content:"\f1c8"}.fa.fa-file-movie-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-movie-o:before{content:"\f1c8"}.fa.fa-file-code-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-file-code-o:before{content:"\f1c9"}.fa.fa-codepen,.fa.fa-jsfiddle,.fa.fa-vine{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-life-bouy,.fa.fa-life-ring{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-life-bouy:before{content:"\f1cd"}.fa.fa-life-buoy{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-life-buoy:before{content:"\f1cd"}.fa.fa-life-saver{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-life-saver:before{content:"\f1cd"}.fa.fa-support{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-support:before{content:"\f1cd"}.fa.fa-circle-o-notch:before{content:"\f1ce"}.fa.fa-ra,.fa.fa-rebel{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-ra:before{content:"\f1d0"}.fa.fa-resistance{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-resistance:before{content:"\f1d0"}.fa.fa-empire,.fa.fa-ge{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-ge:before{content:"\f1d1"}.fa.fa-git,.fa.fa-git-square,.fa.fa-hacker-news,.fa.fa-y-combinator-square{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-y-combinator-square:before{content:"\f1d4"}.fa.fa-yc-square{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-yc-square:before{content:"\f1d4"}.fa.fa-qq,.fa.fa-tencent-weibo,.fa.fa-wechat,.fa.fa-weixin{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-wechat:before{content:"\f1d7"}.fa.fa-send:before{content:"\f1d8"}.fa.fa-paper-plane-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-paper-plane-o:before{content:"\f1d8"}.fa.fa-send-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-send-o:before{content:"\f1d8"}.fa.fa-circle-thin{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-circle-thin:before{content:"\f111"}.fa.fa-header:before{content:"\f1dc"}.fa.fa-sliders:before{content:"\f1de"}.fa.fa-futbol-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-futbol-o:before{content:"\f1e3"}.fa.fa-soccer-ball-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-soccer-ball-o:before{content:"\f1e3"}.fa.fa-slideshare,.fa.fa-twitch,.fa.fa-yelp{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-newspaper-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-newspaper-o:before{content:"\f1ea"}.fa.fa-cc-amex,.fa.fa-cc-discover,.fa.fa-cc-mastercard,.fa.fa-cc-paypal,.fa.fa-cc-stripe,.fa.fa-cc-visa,.fa.fa-google-wallet,.fa.fa-paypal{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-bell-slash-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-bell-slash-o:before{content:"\f1f6"}.fa.fa-trash:before{content:"\f2ed"}.fa.fa-copyright{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-eyedropper:before{content:"\f1fb"}.fa.fa-area-chart:before{content:"\f1fe"}.fa.fa-pie-chart:before{content:"\f200"}.fa.fa-line-chart:before{content:"\f201"}.fa.fa-angellist,.fa.fa-ioxhost,.fa.fa-lastfm,.fa.fa-lastfm-square{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-cc{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-cc:before{content:"\f20a"}.fa.fa-ils:before,.fa.fa-shekel:before,.fa.fa-sheqel:before{content:"\f20b"}.fa.fa-meanpath{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-meanpath:before{content:"\f2b4"}.fa.fa-buysellads,.fa.fa-connectdevelop,.fa.fa-dashcube,.fa.fa-forumbee,.fa.fa-leanpub,.fa.fa-sellsy,.fa.fa-shirtsinbulk,.fa.fa-simplybuilt,.fa.fa-skyatlas{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-diamond{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-diamond:before{content:"\f3a5"}.fa.fa-intersex:before{content:"\f224"}.fa.fa-facebook-official{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-facebook-official:before{content:"\f09a"}.fa.fa-pinterest-p,.fa.fa-whatsapp{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-hotel:before{content:"\f236"}.fa.fa-medium,.fa.fa-viacoin,.fa.fa-y-combinator,.fa.fa-yc{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-yc:before{content:"\f23b"}.fa.fa-expeditedssl,.fa.fa-opencart,.fa.fa-optin-monster{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-battery-4:before,.fa.fa-battery:before{content:"\f240"}.fa.fa-battery-3:before{content:"\f241"}.fa.fa-battery-2:before{content:"\f242"}.fa.fa-battery-1:before{content:"\f243"}.fa.fa-battery-0:before{content:"\f244"}.fa.fa-object-group,.fa.fa-object-ungroup,.fa.fa-sticky-note-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-sticky-note-o:before{content:"\f249"}.fa.fa-cc-diners-club,.fa.fa-cc-jcb{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-clone,.fa.fa-hourglass-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hourglass-o:before{content:"\f254"}.fa.fa-hourglass-1:before{content:"\f251"}.fa.fa-hourglass-2:before{content:"\f252"}.fa.fa-hourglass-3:before{content:"\f253"}.fa.fa-hand-rock-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hand-rock-o:before{content:"\f255"}.fa.fa-hand-grab-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hand-grab-o:before{content:"\f255"}.fa.fa-hand-paper-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hand-paper-o:before{content:"\f256"}.fa.fa-hand-stop-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hand-stop-o:before{content:"\f256"}.fa.fa-hand-scissors-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hand-scissors-o:before{content:"\f257"}.fa.fa-hand-lizard-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hand-lizard-o:before{content:"\f258"}.fa.fa-hand-spock-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hand-spock-o:before{content:"\f259"}.fa.fa-hand-pointer-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hand-pointer-o:before{content:"\f25a"}.fa.fa-hand-peace-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-hand-peace-o:before{content:"\f25b"}.fa.fa-registered{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-chrome,.fa.fa-creative-commons,.fa.fa-firefox,.fa.fa-get-pocket,.fa.fa-gg,.fa.fa-gg-circle,.fa.fa-internet-explorer,.fa.fa-odnoklassniki,.fa.fa-odnoklassniki-square,.fa.fa-opera,.fa.fa-safari,.fa.fa-tripadvisor,.fa.fa-wikipedia-w{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-television:before{content:"\f26c"}.fa.fa-500px,.fa.fa-amazon,.fa.fa-contao{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-calendar-plus-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-calendar-plus-o:before{content:"\f271"}.fa.fa-calendar-minus-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-calendar-minus-o:before{content:"\f272"}.fa.fa-calendar-times-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-calendar-times-o:before{content:"\f273"}.fa.fa-calendar-check-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-calendar-check-o:before{content:"\f274"}.fa.fa-map-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-map-o:before{content:"\f279"}.fa.fa-commenting:before{content:"\f4ad"}.fa.fa-commenting-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-commenting-o:before{content:"\f4ad"}.fa.fa-houzz,.fa.fa-vimeo{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-vimeo:before{content:"\f27d"}.fa.fa-black-tie,.fa.fa-edge,.fa.fa-fonticons,.fa.fa-reddit-alien{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-credit-card-alt:before{content:"\f09d"}.fa.fa-codiepie,.fa.fa-fort-awesome,.fa.fa-mixcloud,.fa.fa-modx,.fa.fa-product-hunt,.fa.fa-scribd,.fa.fa-usb{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-pause-circle-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-pause-circle-o:before{content:"\f28b"}.fa.fa-stop-circle-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-stop-circle-o:before{content:"\f28d"}.fa.fa-bluetooth,.fa.fa-bluetooth-b,.fa.fa-envira,.fa.fa-gitlab,.fa.fa-wheelchair-alt,.fa.fa-wpbeginner,.fa.fa-wpforms{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-wheelchair-alt:before{content:"\f368"}.fa.fa-question-circle-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-question-circle-o:before{content:"\f059"}.fa.fa-volume-control-phone:before{content:"\f2a0"}.fa.fa-asl-interpreting:before{content:"\f2a3"}.fa.fa-deafness:before,.fa.fa-hard-of-hearing:before{content:"\f2a4"}.fa.fa-glide,.fa.fa-glide-g{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-signing:before{content:"\f2a7"}.fa.fa-first-order,.fa.fa-google-plus-official,.fa.fa-pied-piper,.fa.fa-snapchat,.fa.fa-snapchat-ghost,.fa.fa-snapchat-square,.fa.fa-themeisle,.fa.fa-viadeo,.fa.fa-viadeo-square,.fa.fa-yoast{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-google-plus-official:before{content:"\f2b3"}.fa.fa-google-plus-circle{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-google-plus-circle:before{content:"\f2b3"}.fa.fa-fa,.fa.fa-font-awesome{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-fa:before{content:"\f2b4"}.fa.fa-handshake-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-handshake-o:before{content:"\f2b5"}.fa.fa-envelope-open-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-envelope-open-o:before{content:"\f2b6"}.fa.fa-linode{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-address-book-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-address-book-o:before{content:"\f2b9"}.fa.fa-vcard:before{content:"\f2bb"}.fa.fa-address-card-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-address-card-o:before{content:"\f2bb"}.fa.fa-vcard-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-vcard-o:before{content:"\f2bb"}.fa.fa-user-circle-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-user-circle-o:before{content:"\f2bd"}.fa.fa-user-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-user-o:before{content:"\f007"}.fa.fa-id-badge{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-drivers-license:before{content:"\f2c2"}.fa.fa-id-card-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-id-card-o:before{content:"\f2c2"}.fa.fa-drivers-license-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-drivers-license-o:before{content:"\f2c2"}.fa.fa-free-code-camp,.fa.fa-quora,.fa.fa-telegram{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-thermometer-4:before,.fa.fa-thermometer:before{content:"\f2c7"}.fa.fa-thermometer-3:before{content:"\f2c8"}.fa.fa-thermometer-2:before{content:"\f2c9"}.fa.fa-thermometer-1:before{content:"\f2ca"}.fa.fa-thermometer-0:before{content:"\f2cb"}.fa.fa-bathtub:before,.fa.fa-s15:before{content:"\f2cd"}.fa.fa-window-maximize,.fa.fa-window-restore{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-times-rectangle:before{content:"\f410"}.fa.fa-window-close-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-window-close-o:before{content:"\f410"}.fa.fa-times-rectangle-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-times-rectangle-o:before{content:"\f410"}.fa.fa-bandcamp,.fa.fa-eercast,.fa.fa-etsy,.fa.fa-grav,.fa.fa-imdb,.fa.fa-ravelry{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-eercast:before{content:"\f2da"}.fa.fa-snowflake-o{font-family:"Font Awesome 5 Free";font-weight:400}.fa.fa-snowflake-o:before{content:"\f2dc"}.fa.fa-superpowers,.fa.fa-wpexplorer{font-family:"Font Awesome 5 Brands";font-weight:400}.fa.fa-cab:before{content:"\f1ba"} \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-brands-400.eot b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-brands-400.eot new file mode 100755 index 0000000..e4ccce2 Binary files /dev/null and b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-brands-400.eot differ diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-brands-400.svg b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-brands-400.svg new file mode 100755 index 0000000..eb0f26f --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-brands-400.svg @@ -0,0 +1,3570 @@ + + + + + +Created by FontForge 20190801 at Tue Feb 4 18:05:39 2020 + By Robert Madole +Copyright (c) Font Awesome + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-brands-400.ttf b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-brands-400.ttf new file mode 100755 index 0000000..08622a3 Binary files /dev/null and b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-brands-400.ttf differ diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-brands-400.woff b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-brands-400.woff new file mode 100755 index 0000000..a43870c Binary files /dev/null and b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-brands-400.woff differ diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-brands-400.woff2 b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-brands-400.woff2 new file mode 100755 index 0000000..3c5189d Binary files /dev/null and b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-brands-400.woff2 differ diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-regular-400.eot b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-regular-400.eot new file mode 100755 index 0000000..dbc06a4 Binary files /dev/null and b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-regular-400.eot differ diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-regular-400.svg b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-regular-400.svg new file mode 100755 index 0000000..273a984 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-regular-400.svg @@ -0,0 +1,803 @@ + + + + + +Created by FontForge 20190801 at Tue Feb 4 18:05:39 2020 + By Robert Madole +Copyright (c) Font Awesome + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-regular-400.ttf b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-regular-400.ttf new file mode 100755 index 0000000..4b6fdef Binary files /dev/null and b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-regular-400.ttf differ diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-regular-400.woff b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-regular-400.woff new file mode 100755 index 0000000..f17953a Binary files /dev/null and b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-regular-400.woff differ diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-regular-400.woff2 b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-regular-400.woff2 new file mode 100755 index 0000000..1f796c7 Binary files /dev/null and b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-regular-400.woff2 differ diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-solid-900.eot b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-solid-900.eot new file mode 100755 index 0000000..550f8f0 Binary files /dev/null and b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-solid-900.eot differ diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-solid-900.svg b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-solid-900.svg new file mode 100755 index 0000000..6933b2b --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-solid-900.svg @@ -0,0 +1,4700 @@ + + + + + +Created by FontForge 20190801 at Tue Feb 4 18:05:39 2020 + By Robert Madole +Copyright (c) Font Awesome + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-solid-900.ttf b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-solid-900.ttf new file mode 100755 index 0000000..9dd8c7f Binary files /dev/null and b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-solid-900.ttf differ diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-solid-900.woff b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-solid-900.woff new file mode 100755 index 0000000..3c9ef93 Binary files /dev/null and b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-solid-900.woff differ diff --git a/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-solid-900.woff2 b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-solid-900.woff2 new file mode 100755 index 0000000..ba7507b Binary files /dev/null and b/deploy/grafana-map-plugin/dist/vendor/fontawesome-free/webfonts/fa-solid-900.woff2 differ diff --git a/deploy/grafana-map-plugin/dist/vendor/leaflet-sleep/Leaflet.Sleep.js b/deploy/grafana-map-plugin/dist/vendor/leaflet-sleep/Leaflet.Sleep.js new file mode 100755 index 0000000..5178fd7 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/leaflet-sleep/Leaflet.Sleep.js @@ -0,0 +1,235 @@ +/* + * Leaflet.Sleep + */ + +/* + * Default Button (touch devices only) + */ + +L.Control.SleepMapControl = L.Control.extend({ + + initialize: function(opts){ + L.setOptions(this,opts); + }, + + options: { + position: 'topright', + prompt: 'disable map', + styles: { + 'backgroundColor': 'white', + 'padding': '5px', + 'border': '2px solid gray' + } + }, + + buildContainer: function(){ + var self = this; + var container = L.DomUtil.create('p', 'sleep-button'); + var boundEvent = this._nonBoundEvent.bind(this); + container.appendChild( document.createTextNode( this.options.prompt )); + L.DomEvent.addListener(container, 'click', boundEvent); + L.DomEvent.addListener(container, 'touchstart', boundEvent); + + Object.keys(this.options.styles).map(function(key) { + container.style[key] = self.options.styles[key]; + }); + + return (this._container = container); + }, + + onAdd: function () { + return this._container || this.buildContainer(); + }, + + _nonBoundEvent: function(e) { + L.DomEvent.stop(e); + if (this._map) this._map.sleep._sleepMap(); + return false; + } + +}); + +L.Control.sleepMapControl = function(){ + return new L.Control.SleepMapControl(); +}; + + +/* + * The Sleep Handler + */ + +L.Map.mergeOptions({ + sleep: true, + sleepTime: 750, + wakeTime: 750, + wakeMessageTouch: 'Touch to Wake', + sleepNote: true, + hoverToWake: true, + sleepOpacity:.7, + sleepButton: L.Control.sleepMapControl +}); + +L.Map.Sleep = L.Handler.extend({ + + addHooks: function () { + var self = this; + this.sleepNote = L.DomUtil.create('p', 'sleep-note', this._map._container); + this._enterTimeout = null; + this._exitTimeout = null; + + /* + * If the device has only a touchscreen we will never get + * a mouseout event, so we add an extra button to put the map + * back to sleep manually. + * + * a custom control/button can be provided by the user + * with the map's `sleepButton` option + */ + this._sleepButton = this._map.options.sleepButton(); + + if (this._map.tap) { + this._map.addControl(this._sleepButton); + } + + var mapStyle = this._map._container.style; + mapStyle.WebkitTransition += 'opacity .5s'; + mapStyle.MozTransition += 'opacity .5s'; + + this._setSleepNoteStyle(); + this._sleepMap(); + }, + + removeHooks: function () { + if (!this._map.scrollWheelZoom.enabled()){ + this._map.scrollWheelZoom.enable(); + } + L.DomUtil.setOpacity( this._map._container, 1); + L.DomUtil.setOpacity( this.sleepNote, 0); + this._removeSleepingListeners(); + this._removeAwakeListeners(); + }, + + _setSleepNoteStyle: function() { + var noteString = ''; + var style = this.sleepNote.style; + + if(this._map.tap) { + noteString = this._map.options.wakeMessageTouch; + } else if (this._map.options.wakeMessage) { + noteString = this._map.options.wakeMessage; + } else if (this._map.options.hoverToWake) { + noteString = 'click or hover to wake'; + } else { + noteString = 'click to wake'; + } + + if( this._map.options.sleepNote ){ + this.sleepNote.appendChild(document.createTextNode( noteString )); + style.pointerEvents = 'none'; + style.maxWidth = '150px'; + style.transitionDuration = '.2s'; + style.zIndex = 5000; + style.opacity = '.6'; + style.margin = 'auto'; + style.textAlign = 'center'; + style.borderRadius = '4px'; + style.top = '50%'; + style.position = 'relative'; + style.padding = '5px'; + style.border = 'solid 2px black'; + style.background = 'white'; + + if(this._map.options.sleepNoteStyle) { + var noteStyleOverrides = this._map.options.sleepNoteStyle; + Object.keys(noteStyleOverrides).map(function(key) { + style[key] = noteStyleOverrides[key]; + }); + } + } + }, + + _wakeMap: function (e) { + this._stopWaiting(); + this._map.scrollWheelZoom.enable(); + if (this._map.tap) { + this._map.touchZoom.enable(); + this._map.dragging.enable(); + this._map.tap.enable(); + this._map.addControl(this._sleepButton); + } + L.DomUtil.setOpacity( this._map._container, 1); + this.sleepNote.style.opacity = 0; + this._addAwakeListeners(); + }, + + _sleepMap: function () { + this._stopWaiting(); + this._map.scrollWheelZoom.disable(); + + if (this._map.tap) { + this._map.touchZoom.disable(); + this._map.dragging.disable(); + this._map.tap.disable(); + this._map.removeControl(this._sleepButton); + } + + L.DomUtil.setOpacity( this._map._container, this._map.options.sleepOpacity); + this.sleepNote.style.opacity = .4; + this._addSleepingListeners(); + }, + + _wakePending: function () { + this._map.once('mousedown', this._wakeMap, this); + if (this._map.options.hoverToWake){ + var self = this; + this._map.once('mouseout', this._sleepMap, this); + self._enterTimeout = setTimeout(function(){ + self._map.off('mouseout', self._sleepMap, self); + self._wakeMap(); + } , self._map.options.wakeTime); + } + }, + + _sleepPending: function () { + var self = this; + self._map.once('mouseover', self._wakeMap, self); + self._exitTimeout = setTimeout(function(){ + self._map.off('mouseover', self._wakeMap, self); + self._sleepMap(); + } , self._map.options.sleepTime); + }, + + _addSleepingListeners: function(){ + this._map.once('mouseover', this._wakePending, this); + this._map.tap && + this._map.once('click', this._wakeMap, this); + }, + + _addAwakeListeners: function(){ + this._map.once('mouseout', this._sleepPending, this); + }, + + _removeSleepingListeners: function(){ + this._map.options.hoverToWake && + this._map.off('mouseover', this._wakePending, this); + this._map.off('mousedown', this._wakeMap, this); + this._map.tap && + this._map.off('click', this._wakeMap, this); + }, + + _removeAwakeListeners: function(){ + this._map.off('mouseout', this._sleepPending, this); + }, + + _stopWaiting: function () { + this._removeSleepingListeners(); + this._removeAwakeListeners(); + var self = this; + if(this._enterTimeout) clearTimeout(self._enterTimeout); + if(this._exitTimeout) clearTimeout(self._exitTimeout); + this._enterTimeout = null; + this._exitTimeout = null; + } +}); + +L.Map.addInitHook('addHandler', 'sleep', L.Map.Sleep); diff --git a/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/images/markers-matte.png b/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/images/markers-matte.png new file mode 100755 index 0000000..1782586 Binary files /dev/null and b/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/images/markers-matte.png differ diff --git a/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/images/markers-matte@2x.png b/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/images/markers-matte@2x.png new file mode 100755 index 0000000..c981244 Binary files /dev/null and b/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/images/markers-matte@2x.png differ diff --git a/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/images/markers-plain.png b/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/images/markers-plain.png new file mode 100755 index 0000000..763f358 Binary files /dev/null and b/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/images/markers-plain.png differ diff --git a/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/images/markers-shadow.png b/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/images/markers-shadow.png new file mode 100755 index 0000000..33cf955 Binary files /dev/null and b/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/images/markers-shadow.png differ diff --git a/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/images/markers-shadow@2x.png b/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/images/markers-shadow@2x.png new file mode 100755 index 0000000..1116503 Binary files /dev/null and b/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/images/markers-shadow@2x.png differ diff --git a/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/images/markers-soft.png b/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/images/markers-soft.png new file mode 100755 index 0000000..acc8315 Binary files /dev/null and b/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/images/markers-soft.png differ diff --git a/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/images/markers-soft@2x.png b/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/images/markers-soft@2x.png new file mode 100755 index 0000000..b3acfbf Binary files /dev/null and b/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/images/markers-soft@2x.png differ diff --git a/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/leaflet.awesome-markers.css b/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/leaflet.awesome-markers.css new file mode 100755 index 0000000..c2ae6c6 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/leaflet.awesome-markers.css @@ -0,0 +1,128 @@ +/* +Author: L. Voogdt +License: MIT +Version: 1.0 +*/ + +/* Marker setup */ +.awesome-marker { + background: url('images/markers-soft.png') no-repeat 0 0; + width: 35px; + height: 46px; + position:absolute; + left:0; + top:0; + display: block; + text-align: center; +} + +.awesome-marker-shadow { + background: url('images/markers-shadow.png') no-repeat 0 0; + width: 36px; + height: 16px; +} + +/* Retina displays */ +@media (min--moz-device-pixel-ratio: 1.5),(-o-min-device-pixel-ratio: 3/2), +(-webkit-min-device-pixel-ratio: 1.5),(min-device-pixel-ratio: 1.5),(min-resolution: 1.5dppx) { + .awesome-marker { + background-image: url('images/markers-soft@2x.png'); + background-size: 720px 92px; + } + .awesome-marker-shadow { + background-image: url('images/markers-shadow@2x.png'); + background-size: 35px 16px; + } +} + +.awesome-marker i { + color: #333; + margin-top: 10px; + display: inline-block; + font-size: 14px; +} + +.awesome-marker .icon-white { + color: #fff; +} + +/* Colors */ +.awesome-marker-icon-red { + background-position: 0 0; +} + +.awesome-marker-icon-darkred { + background-position: -180px 0; +} + +.awesome-marker-icon-lightred { + background-position: -360px 0; +} + +.awesome-marker-icon-orange { + background-position: -36px 0; +} + +.awesome-marker-icon-beige { + background-position: -396px 0; +} + +.awesome-marker-icon-green { + background-position: -72px 0; +} + +.awesome-marker-icon-darkgreen { + background-position: -252px 0; +} + +.awesome-marker-icon-lightgreen { + background-position: -432px 0; +} + +.awesome-marker-icon-blue { + background-position: -108px 0; +} + +.awesome-marker-icon-darkblue { + background-position: -216px 0; +} + +.awesome-marker-icon-lightblue { + background-position: -468px 0; +} + +.awesome-marker-icon-purple { + background-position: -144px 0; +} + +.awesome-marker-icon-darkpurple { + background-position: -288px 0; +} + +.awesome-marker-icon-pink { + background-position: -504px 0; +} + +.awesome-marker-icon-cadetblue { + background-position: -324px 0; +} + +.awesome-marker-icon-white { + background-position: -574px 0; +} + +.awesome-marker-icon-gray { + background-position: -648px 0; +} + +.awesome-marker-icon-lightgray { + background-position: -612px 0; +} + +.awesome-marker-icon-black { + background-position: -682px 0; +} + +.awesome-marker-square { + background-position-y: -46px; +} diff --git a/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/leaflet.awesome-markers.js b/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/leaflet.awesome-markers.js new file mode 100755 index 0000000..7505b6f --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/leaflet.awesome-markers.js @@ -0,0 +1,125 @@ +/* + Leaflet.AwesomeMarkers, a plugin that adds colorful iconic markers for Leaflet, based on the Font Awesome icons + (c) 2012-2013, Lennard Voogdt + + http://leafletjs.com + https://github.com/lvoogdt +*/ + +/*global L*/ + +(function (window, document, undefined) { + "use strict"; + /* + * Leaflet.AwesomeMarkers assumes that you have already included the Leaflet library. + */ + + L.AwesomeMarkers = {}; + + L.AwesomeMarkers.version = '2.0.1'; + + L.AwesomeMarkers.Icon = L.Icon.extend({ + options: { + iconSize: [35, 45], + iconAnchor: [17, 42], + popupAnchor: [1, -32], + shadowAnchor: [10, 12], + shadowSize: [36, 16], + className: 'awesome-marker', + prefix: 'glyphicon', + spinClass: 'fa-spin', + extraClasses: '', + icon: 'home', + markerColor: 'blue', + iconColor: 'white' + }, + + initialize: function (options) { + options = L.Util.setOptions(this, options); + }, + + createIcon: function () { + var div = document.createElement('div'), + options = this.options; + + if (options.icon) { + div.innerHTML = this._createInner(); + } + + if (options.bgPos) { + div.style.backgroundPosition = + (-options.bgPos.x) + 'px ' + (-options.bgPos.y) + 'px'; + } + + this._setIconStyles(div, 'icon-' + options.markerColor); + return div; + }, + + _createInner: function() { + var iconClass, iconSpinClass = "", iconColorClass = "", iconColorStyle = "", options = this.options; + + if(options.icon.slice(0,options.prefix.length+1) === options.prefix + "-") { + iconClass = options.icon; + } else { + iconClass = options.prefix + "-" + options.icon; + } + + if(options.spin && typeof options.spinClass === "string") { + iconSpinClass = options.spinClass; + } + + if(options.iconColor) { + if(options.iconColor === 'white' || options.iconColor === 'black') { + iconColorClass = "icon-" + options.iconColor; + } else { + iconColorStyle = "style='color: " + options.iconColor + "' "; + } + } + + return ""; + }, + + _setIconStyles: function (img, name) { + var options = this.options, + size = L.point(options[name === 'shadow' ? 'shadowSize' : 'iconSize']), + anchor; + + if (name === 'shadow') { + anchor = L.point(options.shadowAnchor || options.iconAnchor); + } else { + anchor = L.point(options.iconAnchor); + } + + if (!anchor && size) { + anchor = size.divideBy(2, true); + } + + img.className = 'awesome-marker-' + name + ' ' + options.className; + + if (anchor) { + img.style.marginLeft = (-anchor.x) + 'px'; + img.style.marginTop = (-anchor.y) + 'px'; + } + + if (size) { + img.style.width = size.x + 'px'; + img.style.height = size.y + 'px'; + } + }, + + createShadow: function () { + var div = document.createElement('div'); + + this._setIconStyles(div, 'shadow'); + return div; + } + }); + + L.AwesomeMarkers.icon = function (options) { + return new L.AwesomeMarkers.Icon(options); + }; + +}(this, document)); + + + diff --git a/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/leaflet.awesome-markers.min.js b/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/leaflet.awesome-markers.min.js new file mode 100755 index 0000000..376e57e --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/leaflet.awesome-markers/leaflet.awesome-markers.min.js @@ -0,0 +1,7 @@ +/* + Leaflet.AwesomeMarkers, a plugin that adds colorful iconic markers for Leaflet, based on the Font Awesome icons + (c) 2012-2013, Lennard Voogdt + + http://leafletjs.com + https://github.com/lvoogdt +*//*global L*/(function(e,t,n){"use strict";L.AwesomeMarkers={};L.AwesomeMarkers.version="2.0.1";L.AwesomeMarkers.Icon=L.Icon.extend({options:{iconSize:[35,45],iconAnchor:[17,42],popupAnchor:[1,-32],shadowAnchor:[10,12],shadowSize:[36,16],className:"awesome-marker",prefix:"glyphicon",spinClass:"fa-spin",icon:"home",markerColor:"blue",iconColor:"white"},initialize:function(e){e=L.Util.setOptions(this,e)},createIcon:function(){var e=t.createElement("div"),n=this.options;n.icon&&(e.innerHTML=this._createInner());n.bgPos&&(e.style.backgroundPosition=-n.bgPos.x+"px "+ -n.bgPos.y+"px");this._setIconStyles(e,"icon-"+n.markerColor);return e},_createInner:function(){var e,t="",n="",r="",i=this.options;i.icon.slice(0,i.prefix.length+1)===i.prefix+"-"?e=i.icon:e=i.prefix+"-"+i.icon;i.spin&&typeof i.spinClass=="string"&&(t=i.spinClass);i.iconColor&&(i.iconColor==="white"||i.iconColor==="black"?n="icon-"+i.iconColor:r="style='color: "+i.iconColor+"' ");return""},_setIconStyles:function(e,t){var n=this.options,r=L.point(n[t==="shadow"?"shadowSize":"iconSize"]),i;t==="shadow"?i=L.point(n.shadowAnchor||n.iconAnchor):i=L.point(n.iconAnchor);!i&&r&&(i=r.divideBy(2,!0));e.className="awesome-marker-"+t+" "+n.className;if(i){e.style.marginLeft=-i.x+"px";e.style.marginTop=-i.y+"px"}if(r){e.style.width=r.x+"px";e.style.height=r.y+"px"}},createShadow:function(){var e=t.createElement("div");this._setIconStyles(e,"shadow");return e}});L.AwesomeMarkers.icon=function(e){return new L.AwesomeMarkers.Icon(e)}})(this,document); diff --git a/deploy/grafana-map-plugin/dist/vendor/leaflet.markercluster/MarkerCluster.Default.css b/deploy/grafana-map-plugin/dist/vendor/leaflet.markercluster/MarkerCluster.Default.css new file mode 100755 index 0000000..da330ca --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/leaflet.markercluster/MarkerCluster.Default.css @@ -0,0 +1,60 @@ +.marker-cluster-small { + background-color: rgba(181, 226, 140, 0.6); + } +.marker-cluster-small div { + background-color: rgba(110, 204, 57, 0.6); + } + +.marker-cluster-medium { + background-color: rgba(241, 211, 87, 0.6); + } +.marker-cluster-medium div { + background-color: rgba(240, 194, 12, 0.6); + } + +.marker-cluster-large { + background-color: rgba(253, 156, 115, 0.6); + } +.marker-cluster-large div { + background-color: rgba(241, 128, 23, 0.6); + } + + /* IE 6-8 fallback colors */ +.leaflet-oldie .marker-cluster-small { + background-color: rgb(181, 226, 140); + } +.leaflet-oldie .marker-cluster-small div { + background-color: rgb(110, 204, 57); + } + +.leaflet-oldie .marker-cluster-medium { + background-color: rgb(241, 211, 87); + } +.leaflet-oldie .marker-cluster-medium div { + background-color: rgb(240, 194, 12); + } + +.leaflet-oldie .marker-cluster-large { + background-color: rgb(253, 156, 115); + } +.leaflet-oldie .marker-cluster-large div { + background-color: rgb(241, 128, 23); +} + +.marker-cluster { + background-clip: padding-box; + border-radius: 20px; + } +.marker-cluster div { + width: 30px; + height: 30px; + margin-left: 5px; + margin-top: 5px; + + text-align: center; + border-radius: 15px; + font: 12px "Helvetica Neue", Arial, Helvetica, sans-serif; + } +.marker-cluster span { + line-height: 30px; + } \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/vendor/leaflet.markercluster/MarkerCluster.css b/deploy/grafana-map-plugin/dist/vendor/leaflet.markercluster/MarkerCluster.css new file mode 100755 index 0000000..7ac0182 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/leaflet.markercluster/MarkerCluster.css @@ -0,0 +1,14 @@ +.leaflet-cluster-anim .leaflet-marker-icon, .leaflet-cluster-anim .leaflet-marker-shadow { + -webkit-transition: -webkit-transform 0.3s ease-out, opacity 0.3s ease-in; + -moz-transition: -moz-transform 0.3s ease-out, opacity 0.3s ease-in; + -o-transition: -o-transform 0.3s ease-out, opacity 0.3s ease-in; + transition: transform 0.3s ease-out, opacity 0.3s ease-in; +} + +.leaflet-cluster-spider-leg { + /* stroke-dashoffset (duration and function) should match with leaflet-marker-icon transform in order to track it exactly */ + -webkit-transition: -webkit-stroke-dashoffset 0.3s ease-out, -webkit-stroke-opacity 0.3s ease-in; + -moz-transition: -moz-stroke-dashoffset 0.3s ease-out, -moz-stroke-opacity 0.3s ease-in; + -o-transition: -o-stroke-dashoffset 0.3s ease-out, -o-stroke-opacity 0.3s ease-in; + transition: stroke-dashoffset 0.3s ease-out, stroke-opacity 0.3s ease-in; +} diff --git a/deploy/grafana-map-plugin/dist/vendor/leaflet.markercluster/WhereAreTheJavascriptFiles.txt b/deploy/grafana-map-plugin/dist/vendor/leaflet.markercluster/WhereAreTheJavascriptFiles.txt new file mode 100755 index 0000000..7145445 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/leaflet.markercluster/WhereAreTheJavascriptFiles.txt @@ -0,0 +1,5 @@ +We don't ship the .js files in the git master branch. +They are only present in version tags and in npm. + +See how to get the JS files here: https://github.com/Leaflet/Leaflet.markercluster#using-the-plugin +Or how to build them: https://github.com/Leaflet/Leaflet.markercluster#building-testing-and-linting-scripts diff --git a/deploy/grafana-map-plugin/dist/vendor/leaflet.markercluster/leaflet.markercluster-src.js b/deploy/grafana-map-plugin/dist/vendor/leaflet.markercluster/leaflet.markercluster-src.js new file mode 100755 index 0000000..055d6f9 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/leaflet.markercluster/leaflet.markercluster-src.js @@ -0,0 +1,2690 @@ +/* + * Leaflet.markercluster 1.4.1+master.94f9815, + * Provides Beautiful Animated Marker Clustering functionality for Leaflet, a JS library for interactive maps. + * https://github.com/Leaflet/Leaflet.markercluster + * (c) 2012-2017, Dave Leaver, smartrak + */ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.Leaflet = global.Leaflet || {}, global.Leaflet.markercluster = global.Leaflet.markercluster || {}))); +}(this, (function (exports) { 'use strict'; + +/* + * L.MarkerClusterGroup extends L.FeatureGroup by clustering the markers contained within + */ + +var MarkerClusterGroup = L.MarkerClusterGroup = L.FeatureGroup.extend({ + + options: { + maxClusterRadius: 80, //A cluster will cover at most this many pixels from its center + iconCreateFunction: null, + clusterPane: L.Marker.prototype.options.pane, + + spiderfyOnMaxZoom: true, + showCoverageOnHover: true, + zoomToBoundsOnClick: true, + singleMarkerMode: false, + + disableClusteringAtZoom: null, + + // Setting this to false prevents the removal of any clusters outside of the viewpoint, which + // is the default behaviour for performance reasons. + removeOutsideVisibleBounds: true, + + // Set to false to disable all animations (zoom and spiderfy). + // If false, option animateAddingMarkers below has no effect. + // If L.DomUtil.TRANSITION is falsy, this option has no effect. + animate: true, + + //Whether to animate adding markers after adding the MarkerClusterGroup to the map + // If you are adding individual markers set to true, if adding bulk markers leave false for massive performance gains. + animateAddingMarkers: false, + + //Increase to increase the distance away that spiderfied markers appear from the center + spiderfyDistanceMultiplier: 1, + + // Make it possible to specify a polyline options on a spider leg + spiderLegPolylineOptions: { weight: 1.5, color: '#222', opacity: 0.5 }, + + // When bulk adding layers, adds markers in chunks. Means addLayers may not add all the layers in the call, others will be loaded during setTimeouts + chunkedLoading: false, + chunkInterval: 200, // process markers for a maximum of ~ n milliseconds (then trigger the chunkProgress callback) + chunkDelay: 50, // at the end of each interval, give n milliseconds back to system/browser + chunkProgress: null, // progress callback: function(processed, total, elapsed) (e.g. for a progress indicator) + + //Options to pass to the L.Polygon constructor + polygonOptions: {} + }, + + initialize: function (options) { + L.Util.setOptions(this, options); + if (!this.options.iconCreateFunction) { + this.options.iconCreateFunction = this._defaultIconCreateFunction; + } + + this._featureGroup = L.featureGroup(); + this._featureGroup.addEventParent(this); + + this._nonPointGroup = L.featureGroup(); + this._nonPointGroup.addEventParent(this); + + this._inZoomAnimation = 0; + this._needsClustering = []; + this._needsRemoving = []; //Markers removed while we aren't on the map need to be kept track of + //The bounds of the currently shown area (from _getExpandedVisibleBounds) Updated on zoom/move + this._currentShownBounds = null; + + this._queue = []; + + this._childMarkerEventHandlers = { + 'dragstart': this._childMarkerDragStart, + 'move': this._childMarkerMoved, + 'dragend': this._childMarkerDragEnd, + }; + + // Hook the appropriate animation methods. + var animate = L.DomUtil.TRANSITION && this.options.animate; + L.extend(this, animate ? this._withAnimation : this._noAnimation); + // Remember which MarkerCluster class to instantiate (animated or not). + this._markerCluster = animate ? L.MarkerCluster : L.MarkerClusterNonAnimated; + }, + + addLayer: function (layer) { + + if (layer instanceof L.LayerGroup) { + return this.addLayers([layer]); + } + + //Don't cluster non point data + if (!layer.getLatLng) { + this._nonPointGroup.addLayer(layer); + this.fire('layeradd', { layer: layer }); + return this; + } + + if (!this._map) { + this._needsClustering.push(layer); + this.fire('layeradd', { layer: layer }); + return this; + } + + if (this.hasLayer(layer)) { + return this; + } + + + //If we have already clustered we'll need to add this one to a cluster + + if (this._unspiderfy) { + this._unspiderfy(); + } + + this._addLayer(layer, this._maxZoom); + this.fire('layeradd', { layer: layer }); + + // Refresh bounds and weighted positions. + this._topClusterLevel._recalculateBounds(); + + this._refreshClustersIcons(); + + //Work out what is visible + var visibleLayer = layer, + currentZoom = this._zoom; + if (layer.__parent) { + while (visibleLayer.__parent._zoom >= currentZoom) { + visibleLayer = visibleLayer.__parent; + } + } + + if (this._currentShownBounds.contains(visibleLayer.getLatLng())) { + if (this.options.animateAddingMarkers) { + this._animationAddLayer(layer, visibleLayer); + } else { + this._animationAddLayerNonAnimated(layer, visibleLayer); + } + } + return this; + }, + + removeLayer: function (layer) { + + if (layer instanceof L.LayerGroup) { + return this.removeLayers([layer]); + } + + //Non point layers + if (!layer.getLatLng) { + this._nonPointGroup.removeLayer(layer); + this.fire('layerremove', { layer: layer }); + return this; + } + + if (!this._map) { + if (!this._arraySplice(this._needsClustering, layer) && this.hasLayer(layer)) { + this._needsRemoving.push({ layer: layer, latlng: layer._latlng }); + } + this.fire('layerremove', { layer: layer }); + return this; + } + + if (!layer.__parent) { + return this; + } + + if (this._unspiderfy) { + this._unspiderfy(); + this._unspiderfyLayer(layer); + } + + //Remove the marker from clusters + this._removeLayer(layer, true); + this.fire('layerremove', { layer: layer }); + + // Refresh bounds and weighted positions. + this._topClusterLevel._recalculateBounds(); + + this._refreshClustersIcons(); + + layer.off(this._childMarkerEventHandlers, this); + + if (this._featureGroup.hasLayer(layer)) { + this._featureGroup.removeLayer(layer); + if (layer.clusterShow) { + layer.clusterShow(); + } + } + + return this; + }, + + //Takes an array of markers and adds them in bulk + addLayers: function (layersArray, skipLayerAddEvent) { + if (!L.Util.isArray(layersArray)) { + return this.addLayer(layersArray); + } + + var fg = this._featureGroup, + npg = this._nonPointGroup, + chunked = this.options.chunkedLoading, + chunkInterval = this.options.chunkInterval, + chunkProgress = this.options.chunkProgress, + l = layersArray.length, + offset = 0, + originalArray = true, + m; + + if (this._map) { + var started = (new Date()).getTime(); + var process = L.bind(function () { + var start = (new Date()).getTime(); + for (; offset < l; offset++) { + if (chunked && offset % 200 === 0) { + // every couple hundred markers, instrument the time elapsed since processing started: + var elapsed = (new Date()).getTime() - start; + if (elapsed > chunkInterval) { + break; // been working too hard, time to take a break :-) + } + } + + m = layersArray[offset]; + + // Group of layers, append children to layersArray and skip. + // Side effects: + // - Total increases, so chunkProgress ratio jumps backward. + // - Groups are not included in this group, only their non-group child layers (hasLayer). + // Changing array length while looping does not affect performance in current browsers: + // http://jsperf.com/for-loop-changing-length/6 + if (m instanceof L.LayerGroup) { + if (originalArray) { + layersArray = layersArray.slice(); + originalArray = false; + } + this._extractNonGroupLayers(m, layersArray); + l = layersArray.length; + continue; + } + + //Not point data, can't be clustered + if (!m.getLatLng) { + npg.addLayer(m); + if (!skipLayerAddEvent) { + this.fire('layeradd', { layer: m }); + } + continue; + } + + if (this.hasLayer(m)) { + continue; + } + + this._addLayer(m, this._maxZoom); + if (!skipLayerAddEvent) { + this.fire('layeradd', { layer: m }); + } + + //If we just made a cluster of size 2 then we need to remove the other marker from the map (if it is) or we never will + if (m.__parent) { + if (m.__parent.getChildCount() === 2) { + var markers = m.__parent.getAllChildMarkers(), + otherMarker = markers[0] === m ? markers[1] : markers[0]; + fg.removeLayer(otherMarker); + } + } + } + + if (chunkProgress) { + // report progress and time elapsed: + chunkProgress(offset, l, (new Date()).getTime() - started); + } + + // Completed processing all markers. + if (offset === l) { + + // Refresh bounds and weighted positions. + this._topClusterLevel._recalculateBounds(); + + this._refreshClustersIcons(); + + this._topClusterLevel._recursivelyAddChildrenToMap(null, this._zoom, this._currentShownBounds); + } else { + setTimeout(process, this.options.chunkDelay); + } + }, this); + + process(); + } else { + var needsClustering = this._needsClustering; + + for (; offset < l; offset++) { + m = layersArray[offset]; + + // Group of layers, append children to layersArray and skip. + if (m instanceof L.LayerGroup) { + if (originalArray) { + layersArray = layersArray.slice(); + originalArray = false; + } + this._extractNonGroupLayers(m, layersArray); + l = layersArray.length; + continue; + } + + //Not point data, can't be clustered + if (!m.getLatLng) { + npg.addLayer(m); + continue; + } + + if (this.hasLayer(m)) { + continue; + } + + needsClustering.push(m); + } + } + return this; + }, + + //Takes an array of markers and removes them in bulk + removeLayers: function (layersArray) { + var i, m, + l = layersArray.length, + fg = this._featureGroup, + npg = this._nonPointGroup, + originalArray = true; + + if (!this._map) { + for (i = 0; i < l; i++) { + m = layersArray[i]; + + // Group of layers, append children to layersArray and skip. + if (m instanceof L.LayerGroup) { + if (originalArray) { + layersArray = layersArray.slice(); + originalArray = false; + } + this._extractNonGroupLayers(m, layersArray); + l = layersArray.length; + continue; + } + + this._arraySplice(this._needsClustering, m); + npg.removeLayer(m); + if (this.hasLayer(m)) { + this._needsRemoving.push({ layer: m, latlng: m._latlng }); + } + this.fire('layerremove', { layer: m }); + } + return this; + } + + if (this._unspiderfy) { + this._unspiderfy(); + + // Work on a copy of the array, so that next loop is not affected. + var layersArray2 = layersArray.slice(), + l2 = l; + for (i = 0; i < l2; i++) { + m = layersArray2[i]; + + // Group of layers, append children to layersArray and skip. + if (m instanceof L.LayerGroup) { + this._extractNonGroupLayers(m, layersArray2); + l2 = layersArray2.length; + continue; + } + + this._unspiderfyLayer(m); + } + } + + for (i = 0; i < l; i++) { + m = layersArray[i]; + + // Group of layers, append children to layersArray and skip. + if (m instanceof L.LayerGroup) { + if (originalArray) { + layersArray = layersArray.slice(); + originalArray = false; + } + this._extractNonGroupLayers(m, layersArray); + l = layersArray.length; + continue; + } + + if (!m.__parent) { + npg.removeLayer(m); + this.fire('layerremove', { layer: m }); + continue; + } + + this._removeLayer(m, true, true); + this.fire('layerremove', { layer: m }); + + if (fg.hasLayer(m)) { + fg.removeLayer(m); + if (m.clusterShow) { + m.clusterShow(); + } + } + } + + // Refresh bounds and weighted positions. + this._topClusterLevel._recalculateBounds(); + + this._refreshClustersIcons(); + + //Fix up the clusters and markers on the map + this._topClusterLevel._recursivelyAddChildrenToMap(null, this._zoom, this._currentShownBounds); + + return this; + }, + + //Removes all layers from the MarkerClusterGroup + clearLayers: function () { + //Need our own special implementation as the LayerGroup one doesn't work for us + + //If we aren't on the map (yet), blow away the markers we know of + if (!this._map) { + this._needsClustering = []; + this._needsRemoving = []; + delete this._gridClusters; + delete this._gridUnclustered; + } + + if (this._noanimationUnspiderfy) { + this._noanimationUnspiderfy(); + } + + //Remove all the visible layers + this._featureGroup.clearLayers(); + this._nonPointGroup.clearLayers(); + + this.eachLayer(function (marker) { + marker.off(this._childMarkerEventHandlers, this); + delete marker.__parent; + }, this); + + if (this._map) { + //Reset _topClusterLevel and the DistanceGrids + this._generateInitialClusters(); + } + + return this; + }, + + //Override FeatureGroup.getBounds as it doesn't work + getBounds: function () { + var bounds = new L.LatLngBounds(); + + if (this._topClusterLevel) { + bounds.extend(this._topClusterLevel._bounds); + } + + for (var i = this._needsClustering.length - 1; i >= 0; i--) { + bounds.extend(this._needsClustering[i].getLatLng()); + } + + bounds.extend(this._nonPointGroup.getBounds()); + + return bounds; + }, + + //Overrides LayerGroup.eachLayer + eachLayer: function (method, context) { + var markers = this._needsClustering.slice(), + needsRemoving = this._needsRemoving, + thisNeedsRemoving, i, j; + + if (this._topClusterLevel) { + this._topClusterLevel.getAllChildMarkers(markers); + } + + for (i = markers.length - 1; i >= 0; i--) { + thisNeedsRemoving = true; + + for (j = needsRemoving.length - 1; j >= 0; j--) { + if (needsRemoving[j].layer === markers[i]) { + thisNeedsRemoving = false; + break; + } + } + + if (thisNeedsRemoving) { + method.call(context, markers[i]); + } + } + + this._nonPointGroup.eachLayer(method, context); + }, + + //Overrides LayerGroup.getLayers + getLayers: function () { + var layers = []; + this.eachLayer(function (l) { + layers.push(l); + }); + return layers; + }, + + //Overrides LayerGroup.getLayer, WARNING: Really bad performance + getLayer: function (id) { + var result = null; + + id = parseInt(id, 10); + + this.eachLayer(function (l) { + if (L.stamp(l) === id) { + result = l; + } + }); + + return result; + }, + + //Returns true if the given layer is in this MarkerClusterGroup + hasLayer: function (layer) { + if (!layer) { + return false; + } + + var i, anArray = this._needsClustering; + + for (i = anArray.length - 1; i >= 0; i--) { + if (anArray[i] === layer) { + return true; + } + } + + anArray = this._needsRemoving; + for (i = anArray.length - 1; i >= 0; i--) { + if (anArray[i].layer === layer) { + return false; + } + } + + return !!(layer.__parent && layer.__parent._group === this) || this._nonPointGroup.hasLayer(layer); + }, + + //Zoom down to show the given layer (spiderfying if necessary) then calls the callback + zoomToShowLayer: function (layer, callback) { + + if (typeof callback !== 'function') { + callback = function () {}; + } + + var showMarker = function () { + if ((layer._icon || layer.__parent._icon) && !this._inZoomAnimation) { + this._map.off('moveend', showMarker, this); + this.off('animationend', showMarker, this); + + if (layer._icon) { + callback(); + } else if (layer.__parent._icon) { + this.once('spiderfied', callback, this); + layer.__parent.spiderfy(); + } + } + }; + + if (layer._icon && this._map.getBounds().contains(layer.getLatLng())) { + //Layer is visible ond on screen, immediate return + callback(); + } else if (layer.__parent._zoom < Math.round(this._map._zoom)) { + //Layer should be visible at this zoom level. It must not be on screen so just pan over to it + this._map.on('moveend', showMarker, this); + this._map.panTo(layer.getLatLng()); + } else { + this._map.on('moveend', showMarker, this); + this.on('animationend', showMarker, this); + layer.__parent.zoomToBounds(); + } + }, + + //Overrides FeatureGroup.onAdd + onAdd: function (map) { + this._map = map; + var i, l, layer; + + if (!isFinite(this._map.getMaxZoom())) { + throw "Map has no maxZoom specified"; + } + + this._featureGroup.addTo(map); + this._nonPointGroup.addTo(map); + + if (!this._gridClusters) { + this._generateInitialClusters(); + } + + this._maxLat = map.options.crs.projection.MAX_LATITUDE; + + //Restore all the positions as they are in the MCG before removing them + for (i = 0, l = this._needsRemoving.length; i < l; i++) { + layer = this._needsRemoving[i]; + layer.newlatlng = layer.layer._latlng; + layer.layer._latlng = layer.latlng; + } + //Remove them, then restore their new positions + for (i = 0, l = this._needsRemoving.length; i < l; i++) { + layer = this._needsRemoving[i]; + this._removeLayer(layer.layer, true); + layer.layer._latlng = layer.newlatlng; + } + this._needsRemoving = []; + + //Remember the current zoom level and bounds + this._zoom = Math.round(this._map._zoom); + this._currentShownBounds = this._getExpandedVisibleBounds(); + + this._map.on('zoomend', this._zoomEnd, this); + this._map.on('moveend', this._moveEnd, this); + + if (this._spiderfierOnAdd) { //TODO FIXME: Not sure how to have spiderfier add something on here nicely + this._spiderfierOnAdd(); + } + + this._bindEvents(); + + //Actually add our markers to the map: + l = this._needsClustering; + this._needsClustering = []; + this.addLayers(l, true); + }, + + //Overrides FeatureGroup.onRemove + onRemove: function (map) { + map.off('zoomend', this._zoomEnd, this); + map.off('moveend', this._moveEnd, this); + + this._unbindEvents(); + + //In case we are in a cluster animation + this._map._mapPane.className = this._map._mapPane.className.replace(' leaflet-cluster-anim', ''); + + if (this._spiderfierOnRemove) { //TODO FIXME: Not sure how to have spiderfier add something on here nicely + this._spiderfierOnRemove(); + } + + delete this._maxLat; + + //Clean up all the layers we added to the map + this._hideCoverage(); + this._featureGroup.remove(); + this._nonPointGroup.remove(); + + this._featureGroup.clearLayers(); + + this._map = null; + }, + + getVisibleParent: function (marker) { + var vMarker = marker; + while (vMarker && !vMarker._icon) { + vMarker = vMarker.__parent; + } + return vMarker || null; + }, + + //Remove the given object from the given array + _arraySplice: function (anArray, obj) { + for (var i = anArray.length - 1; i >= 0; i--) { + if (anArray[i] === obj) { + anArray.splice(i, 1); + return true; + } + } + }, + + /** + * Removes a marker from all _gridUnclustered zoom levels, starting at the supplied zoom. + * @param marker to be removed from _gridUnclustered. + * @param z integer bottom start zoom level (included) + * @private + */ + _removeFromGridUnclustered: function (marker, z) { + var map = this._map, + gridUnclustered = this._gridUnclustered, + minZoom = Math.floor(this._map.getMinZoom()); + + for (; z >= minZoom; z--) { + if (!gridUnclustered[z].removeObject(marker, map.project(marker.getLatLng(), z))) { + break; + } + } + }, + + _childMarkerDragStart: function (e) { + e.target.__dragStart = e.target._latlng; + }, + + _childMarkerMoved: function (e) { + if (!this._ignoreMove && !e.target.__dragStart) { + var isPopupOpen = e.target._popup && e.target._popup.isOpen(); + + this._moveChild(e.target, e.oldLatLng, e.latlng); + + if (isPopupOpen) { + e.target.openPopup(); + } + } + }, + + _moveChild: function (layer, from, to) { + layer._latlng = from; + this.removeLayer(layer); + + layer._latlng = to; + this.addLayer(layer); + }, + + _childMarkerDragEnd: function (e) { + var dragStart = e.target.__dragStart; + delete e.target.__dragStart; + if (dragStart) { + this._moveChild(e.target, dragStart, e.target._latlng); + } + }, + + + //Internal function for removing a marker from everything. + //dontUpdateMap: set to true if you will handle updating the map manually (for bulk functions) + _removeLayer: function (marker, removeFromDistanceGrid, dontUpdateMap) { + var gridClusters = this._gridClusters, + gridUnclustered = this._gridUnclustered, + fg = this._featureGroup, + map = this._map, + minZoom = Math.floor(this._map.getMinZoom()); + + //Remove the marker from distance clusters it might be in + if (removeFromDistanceGrid) { + this._removeFromGridUnclustered(marker, this._maxZoom); + } + + //Work our way up the clusters removing them as we go if required + var cluster = marker.__parent, + markers = cluster._markers, + otherMarker; + + //Remove the marker from the immediate parents marker list + this._arraySplice(markers, marker); + + while (cluster) { + cluster._childCount--; + cluster._boundsNeedUpdate = true; + + if (cluster._zoom < minZoom) { + //Top level, do nothing + break; + } else if (removeFromDistanceGrid && cluster._childCount <= 1) { //Cluster no longer required + //We need to push the other marker up to the parent + otherMarker = cluster._markers[0] === marker ? cluster._markers[1] : cluster._markers[0]; + + //Update distance grid + gridClusters[cluster._zoom].removeObject(cluster, map.project(cluster._cLatLng, cluster._zoom)); + gridUnclustered[cluster._zoom].addObject(otherMarker, map.project(otherMarker.getLatLng(), cluster._zoom)); + + //Move otherMarker up to parent + this._arraySplice(cluster.__parent._childClusters, cluster); + cluster.__parent._markers.push(otherMarker); + otherMarker.__parent = cluster.__parent; + + if (cluster._icon) { + //Cluster is currently on the map, need to put the marker on the map instead + fg.removeLayer(cluster); + if (!dontUpdateMap) { + fg.addLayer(otherMarker); + } + } + } else { + cluster._iconNeedsUpdate = true; + } + + cluster = cluster.__parent; + } + + delete marker.__parent; + }, + + _isOrIsParent: function (el, oel) { + while (oel) { + if (el === oel) { + return true; + } + oel = oel.parentNode; + } + return false; + }, + + //Override L.Evented.fire + fire: function (type, data, propagate) { + if (data && data.layer instanceof L.MarkerCluster) { + //Prevent multiple clustermouseover/off events if the icon is made up of stacked divs (Doesn't work in ie <= 8, no relatedTarget) + if (data.originalEvent && this._isOrIsParent(data.layer._icon, data.originalEvent.relatedTarget)) { + return; + } + type = 'cluster' + type; + } + + L.FeatureGroup.prototype.fire.call(this, type, data, propagate); + }, + + //Override L.Evented.listens + listens: function (type, propagate) { + return L.FeatureGroup.prototype.listens.call(this, type, propagate) || L.FeatureGroup.prototype.listens.call(this, 'cluster' + type, propagate); + }, + + //Default functionality + _defaultIconCreateFunction: function (cluster) { + var childCount = cluster.getChildCount(); + + var c = ' marker-cluster-'; + if (childCount < 10) { + c += 'small'; + } else if (childCount < 100) { + c += 'medium'; + } else { + c += 'large'; + } + + return new L.DivIcon({ html: '
' + childCount + '
', className: 'marker-cluster' + c, iconSize: new L.Point(40, 40) }); + }, + + _bindEvents: function () { + var map = this._map, + spiderfyOnMaxZoom = this.options.spiderfyOnMaxZoom, + showCoverageOnHover = this.options.showCoverageOnHover, + zoomToBoundsOnClick = this.options.zoomToBoundsOnClick; + + //Zoom on cluster click or spiderfy if we are at the lowest level + if (spiderfyOnMaxZoom || zoomToBoundsOnClick) { + this.on('clusterclick', this._zoomOrSpiderfy, this); + } + + //Show convex hull (boundary) polygon on mouse over + if (showCoverageOnHover) { + this.on('clustermouseover', this._showCoverage, this); + this.on('clustermouseout', this._hideCoverage, this); + map.on('zoomend', this._hideCoverage, this); + } + }, + + _zoomOrSpiderfy: function (e) { + var cluster = e.layer, + bottomCluster = cluster; + + while (bottomCluster._childClusters.length === 1) { + bottomCluster = bottomCluster._childClusters[0]; + } + + if (bottomCluster._zoom === this._maxZoom && + bottomCluster._childCount === cluster._childCount && + this.options.spiderfyOnMaxZoom) { + + // All child markers are contained in a single cluster from this._maxZoom to this cluster. + cluster.spiderfy(); + } else if (this.options.zoomToBoundsOnClick) { + cluster.zoomToBounds(); + } + + // Focus the map again for keyboard users. + if (e.originalEvent && e.originalEvent.keyCode === 13) { + this._map._container.focus(); + } + }, + + _showCoverage: function (e) { + var map = this._map; + if (this._inZoomAnimation) { + return; + } + if (this._shownPolygon) { + map.removeLayer(this._shownPolygon); + } + if (e.layer.getChildCount() > 2 && e.layer !== this._spiderfied) { + this._shownPolygon = new L.Polygon(e.layer.getConvexHull(), this.options.polygonOptions); + map.addLayer(this._shownPolygon); + } + }, + + _hideCoverage: function () { + if (this._shownPolygon) { + this._map.removeLayer(this._shownPolygon); + this._shownPolygon = null; + } + }, + + _unbindEvents: function () { + var spiderfyOnMaxZoom = this.options.spiderfyOnMaxZoom, + showCoverageOnHover = this.options.showCoverageOnHover, + zoomToBoundsOnClick = this.options.zoomToBoundsOnClick, + map = this._map; + + if (spiderfyOnMaxZoom || zoomToBoundsOnClick) { + this.off('clusterclick', this._zoomOrSpiderfy, this); + } + if (showCoverageOnHover) { + this.off('clustermouseover', this._showCoverage, this); + this.off('clustermouseout', this._hideCoverage, this); + map.off('zoomend', this._hideCoverage, this); + } + }, + + _zoomEnd: function () { + if (!this._map) { //May have been removed from the map by a zoomEnd handler + return; + } + this._mergeSplitClusters(); + + this._zoom = Math.round(this._map._zoom); + this._currentShownBounds = this._getExpandedVisibleBounds(); + }, + + _moveEnd: function () { + if (this._inZoomAnimation) { + return; + } + + var newBounds = this._getExpandedVisibleBounds(); + + this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, Math.floor(this._map.getMinZoom()), this._zoom, newBounds); + this._topClusterLevel._recursivelyAddChildrenToMap(null, Math.round(this._map._zoom), newBounds); + + this._currentShownBounds = newBounds; + return; + }, + + _generateInitialClusters: function () { + var maxZoom = Math.ceil(this._map.getMaxZoom()), + minZoom = Math.floor(this._map.getMinZoom()), + radius = this.options.maxClusterRadius, + radiusFn = radius; + + //If we just set maxClusterRadius to a single number, we need to create + //a simple function to return that number. Otherwise, we just have to + //use the function we've passed in. + if (typeof radius !== "function") { + radiusFn = function () { return radius; }; + } + + if (this.options.disableClusteringAtZoom !== null) { + maxZoom = this.options.disableClusteringAtZoom - 1; + } + this._maxZoom = maxZoom; + this._gridClusters = {}; + this._gridUnclustered = {}; + + //Set up DistanceGrids for each zoom + for (var zoom = maxZoom; zoom >= minZoom; zoom--) { + this._gridClusters[zoom] = new L.DistanceGrid(radiusFn(zoom)); + this._gridUnclustered[zoom] = new L.DistanceGrid(radiusFn(zoom)); + } + + // Instantiate the appropriate L.MarkerCluster class (animated or not). + this._topClusterLevel = new this._markerCluster(this, minZoom - 1); + }, + + //Zoom: Zoom to start adding at (Pass this._maxZoom to start at the bottom) + _addLayer: function (layer, zoom) { + var gridClusters = this._gridClusters, + gridUnclustered = this._gridUnclustered, + minZoom = Math.floor(this._map.getMinZoom()), + markerPoint, z; + + if (this.options.singleMarkerMode) { + this._overrideMarkerIcon(layer); + } + + layer.on(this._childMarkerEventHandlers, this); + + //Find the lowest zoom level to slot this one in + for (; zoom >= minZoom; zoom--) { + markerPoint = this._map.project(layer.getLatLng(), zoom); // calculate pixel position + + //Try find a cluster close by + var closest = gridClusters[zoom].getNearObject(markerPoint); + if (closest) { + closest._addChild(layer); + layer.__parent = closest; + return; + } + + //Try find a marker close by to form a new cluster with + closest = gridUnclustered[zoom].getNearObject(markerPoint); + if (closest) { + var parent = closest.__parent; + if (parent) { + this._removeLayer(closest, false); + } + + //Create new cluster with these 2 in it + + var newCluster = new this._markerCluster(this, zoom, closest, layer); + gridClusters[zoom].addObject(newCluster, this._map.project(newCluster._cLatLng, zoom)); + closest.__parent = newCluster; + layer.__parent = newCluster; + + //First create any new intermediate parent clusters that don't exist + var lastParent = newCluster; + for (z = zoom - 1; z > parent._zoom; z--) { + lastParent = new this._markerCluster(this, z, lastParent); + gridClusters[z].addObject(lastParent, this._map.project(closest.getLatLng(), z)); + } + parent._addChild(lastParent); + + //Remove closest from this zoom level and any above that it is in, replace with newCluster + this._removeFromGridUnclustered(closest, zoom); + + return; + } + + //Didn't manage to cluster in at this zoom, record us as a marker here and continue upwards + gridUnclustered[zoom].addObject(layer, markerPoint); + } + + //Didn't get in anything, add us to the top + this._topClusterLevel._addChild(layer); + layer.__parent = this._topClusterLevel; + return; + }, + + /** + * Refreshes the icon of all "dirty" visible clusters. + * Non-visible "dirty" clusters will be updated when they are added to the map. + * @private + */ + _refreshClustersIcons: function () { + this._featureGroup.eachLayer(function (c) { + if (c instanceof L.MarkerCluster && c._iconNeedsUpdate) { + c._updateIcon(); + } + }); + }, + + //Enqueue code to fire after the marker expand/contract has happened + _enqueue: function (fn) { + this._queue.push(fn); + if (!this._queueTimeout) { + this._queueTimeout = setTimeout(L.bind(this._processQueue, this), 300); + } + }, + _processQueue: function () { + for (var i = 0; i < this._queue.length; i++) { + this._queue[i].call(this); + } + this._queue.length = 0; + clearTimeout(this._queueTimeout); + this._queueTimeout = null; + }, + + //Merge and split any existing clusters that are too big or small + _mergeSplitClusters: function () { + var mapZoom = Math.round(this._map._zoom); + + //In case we are starting to split before the animation finished + this._processQueue(); + + if (this._zoom < mapZoom && this._currentShownBounds.intersects(this._getExpandedVisibleBounds())) { //Zoom in, split + this._animationStart(); + //Remove clusters now off screen + this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, Math.floor(this._map.getMinZoom()), this._zoom, this._getExpandedVisibleBounds()); + + this._animationZoomIn(this._zoom, mapZoom); + + } else if (this._zoom > mapZoom) { //Zoom out, merge + this._animationStart(); + + this._animationZoomOut(this._zoom, mapZoom); + } else { + this._moveEnd(); + } + }, + + //Gets the maps visible bounds expanded in each direction by the size of the screen (so the user cannot see an area we do not cover in one pan) + _getExpandedVisibleBounds: function () { + if (!this.options.removeOutsideVisibleBounds) { + return this._mapBoundsInfinite; + } else if (L.Browser.mobile) { + return this._checkBoundsMaxLat(this._map.getBounds()); + } + + return this._checkBoundsMaxLat(this._map.getBounds().pad(1)); // Padding expands the bounds by its own dimensions but scaled with the given factor. + }, + + /** + * Expands the latitude to Infinity (or -Infinity) if the input bounds reach the map projection maximum defined latitude + * (in the case of Web/Spherical Mercator, it is 85.0511287798 / see https://en.wikipedia.org/wiki/Web_Mercator#Formulas). + * Otherwise, the removeOutsideVisibleBounds option will remove markers beyond that limit, whereas the same markers without + * this option (or outside MCG) will have their position floored (ceiled) by the projection and rendered at that limit, + * making the user think that MCG "eats" them and never displays them again. + * @param bounds L.LatLngBounds + * @returns {L.LatLngBounds} + * @private + */ + _checkBoundsMaxLat: function (bounds) { + var maxLat = this._maxLat; + + if (maxLat !== undefined) { + if (bounds.getNorth() >= maxLat) { + bounds._northEast.lat = Infinity; + } + if (bounds.getSouth() <= -maxLat) { + bounds._southWest.lat = -Infinity; + } + } + + return bounds; + }, + + //Shared animation code + _animationAddLayerNonAnimated: function (layer, newCluster) { + if (newCluster === layer) { + this._featureGroup.addLayer(layer); + } else if (newCluster._childCount === 2) { + newCluster._addToMap(); + + var markers = newCluster.getAllChildMarkers(); + this._featureGroup.removeLayer(markers[0]); + this._featureGroup.removeLayer(markers[1]); + } else { + newCluster._updateIcon(); + } + }, + + /** + * Extracts individual (i.e. non-group) layers from a Layer Group. + * @param group to extract layers from. + * @param output {Array} in which to store the extracted layers. + * @returns {*|Array} + * @private + */ + _extractNonGroupLayers: function (group, output) { + var layers = group.getLayers(), + i = 0, + layer; + + output = output || []; + + for (; i < layers.length; i++) { + layer = layers[i]; + + if (layer instanceof L.LayerGroup) { + this._extractNonGroupLayers(layer, output); + continue; + } + + output.push(layer); + } + + return output; + }, + + /** + * Implements the singleMarkerMode option. + * @param layer Marker to re-style using the Clusters iconCreateFunction. + * @returns {L.Icon} The newly created icon. + * @private + */ + _overrideMarkerIcon: function (layer) { + var icon = layer.options.icon = this.options.iconCreateFunction({ + getChildCount: function () { + return 1; + }, + getAllChildMarkers: function () { + return [layer]; + } + }); + + return icon; + } +}); + +// Constant bounds used in case option "removeOutsideVisibleBounds" is set to false. +L.MarkerClusterGroup.include({ + _mapBoundsInfinite: new L.LatLngBounds(new L.LatLng(-Infinity, -Infinity), new L.LatLng(Infinity, Infinity)) +}); + +L.MarkerClusterGroup.include({ + _noAnimation: { + //Non Animated versions of everything + _animationStart: function () { + //Do nothing... + }, + _animationZoomIn: function (previousZoomLevel, newZoomLevel) { + this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, Math.floor(this._map.getMinZoom()), previousZoomLevel); + this._topClusterLevel._recursivelyAddChildrenToMap(null, newZoomLevel, this._getExpandedVisibleBounds()); + + //We didn't actually animate, but we use this event to mean "clustering animations have finished" + this.fire('animationend'); + }, + _animationZoomOut: function (previousZoomLevel, newZoomLevel) { + this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, Math.floor(this._map.getMinZoom()), previousZoomLevel); + this._topClusterLevel._recursivelyAddChildrenToMap(null, newZoomLevel, this._getExpandedVisibleBounds()); + + //We didn't actually animate, but we use this event to mean "clustering animations have finished" + this.fire('animationend'); + }, + _animationAddLayer: function (layer, newCluster) { + this._animationAddLayerNonAnimated(layer, newCluster); + } + }, + + _withAnimation: { + //Animated versions here + _animationStart: function () { + this._map._mapPane.className += ' leaflet-cluster-anim'; + this._inZoomAnimation++; + }, + + _animationZoomIn: function (previousZoomLevel, newZoomLevel) { + var bounds = this._getExpandedVisibleBounds(), + fg = this._featureGroup, + minZoom = Math.floor(this._map.getMinZoom()), + i; + + this._ignoreMove = true; + + //Add all children of current clusters to map and remove those clusters from map + this._topClusterLevel._recursively(bounds, previousZoomLevel, minZoom, function (c) { + var startPos = c._latlng, + markers = c._markers, + m; + + if (!bounds.contains(startPos)) { + startPos = null; + } + + if (c._isSingleParent() && previousZoomLevel + 1 === newZoomLevel) { //Immediately add the new child and remove us + fg.removeLayer(c); + c._recursivelyAddChildrenToMap(null, newZoomLevel, bounds); + } else { + //Fade out old cluster + c.clusterHide(); + c._recursivelyAddChildrenToMap(startPos, newZoomLevel, bounds); + } + + //Remove all markers that aren't visible any more + //TODO: Do we actually need to do this on the higher levels too? + for (i = markers.length - 1; i >= 0; i--) { + m = markers[i]; + if (!bounds.contains(m._latlng)) { + fg.removeLayer(m); + } + } + + }); + + this._forceLayout(); + + //Update opacities + this._topClusterLevel._recursivelyBecomeVisible(bounds, newZoomLevel); + //TODO Maybe? Update markers in _recursivelyBecomeVisible + fg.eachLayer(function (n) { + if (!(n instanceof L.MarkerCluster) && n._icon) { + n.clusterShow(); + } + }); + + //update the positions of the just added clusters/markers + this._topClusterLevel._recursively(bounds, previousZoomLevel, newZoomLevel, function (c) { + c._recursivelyRestoreChildPositions(newZoomLevel); + }); + + this._ignoreMove = false; + + //Remove the old clusters and close the zoom animation + this._enqueue(function () { + //update the positions of the just added clusters/markers + this._topClusterLevel._recursively(bounds, previousZoomLevel, minZoom, function (c) { + fg.removeLayer(c); + c.clusterShow(); + }); + + this._animationEnd(); + }); + }, + + _animationZoomOut: function (previousZoomLevel, newZoomLevel) { + this._animationZoomOutSingle(this._topClusterLevel, previousZoomLevel - 1, newZoomLevel); + + //Need to add markers for those that weren't on the map before but are now + this._topClusterLevel._recursivelyAddChildrenToMap(null, newZoomLevel, this._getExpandedVisibleBounds()); + //Remove markers that were on the map before but won't be now + this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, Math.floor(this._map.getMinZoom()), previousZoomLevel, this._getExpandedVisibleBounds()); + }, + + _animationAddLayer: function (layer, newCluster) { + var me = this, + fg = this._featureGroup; + + fg.addLayer(layer); + if (newCluster !== layer) { + if (newCluster._childCount > 2) { //Was already a cluster + + newCluster._updateIcon(); + this._forceLayout(); + this._animationStart(); + + layer._setPos(this._map.latLngToLayerPoint(newCluster.getLatLng())); + layer.clusterHide(); + + this._enqueue(function () { + fg.removeLayer(layer); + layer.clusterShow(); + + me._animationEnd(); + }); + + } else { //Just became a cluster + this._forceLayout(); + + me._animationStart(); + me._animationZoomOutSingle(newCluster, this._map.getMaxZoom(), this._zoom); + } + } + } + }, + + // Private methods for animated versions. + _animationZoomOutSingle: function (cluster, previousZoomLevel, newZoomLevel) { + var bounds = this._getExpandedVisibleBounds(), + minZoom = Math.floor(this._map.getMinZoom()); + + //Animate all of the markers in the clusters to move to their cluster center point + cluster._recursivelyAnimateChildrenInAndAddSelfToMap(bounds, minZoom, previousZoomLevel + 1, newZoomLevel); + + var me = this; + + //Update the opacity (If we immediately set it they won't animate) + this._forceLayout(); + cluster._recursivelyBecomeVisible(bounds, newZoomLevel); + + //TODO: Maybe use the transition timing stuff to make this more reliable + //When the animations are done, tidy up + this._enqueue(function () { + + //This cluster stopped being a cluster before the timeout fired + if (cluster._childCount === 1) { + var m = cluster._markers[0]; + //If we were in a cluster animation at the time then the opacity and position of our child could be wrong now, so fix it + this._ignoreMove = true; + m.setLatLng(m.getLatLng()); + this._ignoreMove = false; + if (m.clusterShow) { + m.clusterShow(); + } + } else { + cluster._recursively(bounds, newZoomLevel, minZoom, function (c) { + c._recursivelyRemoveChildrenFromMap(bounds, minZoom, previousZoomLevel + 1); + }); + } + me._animationEnd(); + }); + }, + + _animationEnd: function () { + if (this._map) { + this._map._mapPane.className = this._map._mapPane.className.replace(' leaflet-cluster-anim', ''); + } + this._inZoomAnimation--; + this.fire('animationend'); + }, + + //Force a browser layout of stuff in the map + // Should apply the current opacity and location to all elements so we can update them again for an animation + _forceLayout: function () { + //In my testing this works, infact offsetWidth of any element seems to work. + //Could loop all this._layers and do this for each _icon if it stops working + + L.Util.falseFn(document.body.offsetWidth); + } +}); + +L.markerClusterGroup = function (options) { + return new L.MarkerClusterGroup(options); +}; + +var MarkerCluster = L.MarkerCluster = L.Marker.extend({ + options: L.Icon.prototype.options, + + initialize: function (group, zoom, a, b) { + + L.Marker.prototype.initialize.call(this, a ? (a._cLatLng || a.getLatLng()) : new L.LatLng(0, 0), + { icon: this, pane: group.options.clusterPane }); + + this._group = group; + this._zoom = zoom; + + this._markers = []; + this._childClusters = []; + this._childCount = 0; + this._iconNeedsUpdate = true; + this._boundsNeedUpdate = true; + + this._bounds = new L.LatLngBounds(); + + if (a) { + this._addChild(a); + } + if (b) { + this._addChild(b); + } + }, + + //Recursively retrieve all child markers of this cluster + getAllChildMarkers: function (storageArray, ignoreDraggedMarker) { + storageArray = storageArray || []; + + for (var i = this._childClusters.length - 1; i >= 0; i--) { + this._childClusters[i].getAllChildMarkers(storageArray); + } + + for (var j = this._markers.length - 1; j >= 0; j--) { + if (ignoreDraggedMarker && this._markers[j].__dragStart) { + continue; + } + storageArray.push(this._markers[j]); + } + + return storageArray; + }, + + //Returns the count of how many child markers we have + getChildCount: function () { + return this._childCount; + }, + + //Zoom to the minimum of showing all of the child markers, or the extents of this cluster + zoomToBounds: function (fitBoundsOptions) { + var childClusters = this._childClusters.slice(), + map = this._group._map, + boundsZoom = map.getBoundsZoom(this._bounds), + zoom = this._zoom + 1, + mapZoom = map.getZoom(), + i; + + //calculate how far we need to zoom down to see all of the markers + while (childClusters.length > 0 && boundsZoom > zoom) { + zoom++; + var newClusters = []; + for (i = 0; i < childClusters.length; i++) { + newClusters = newClusters.concat(childClusters[i]._childClusters); + } + childClusters = newClusters; + } + + if (boundsZoom > zoom) { + this._group._map.setView(this._latlng, zoom); + } else if (boundsZoom <= mapZoom) { //If fitBounds wouldn't zoom us down, zoom us down instead + this._group._map.setView(this._latlng, mapZoom + 1); + } else { + this._group._map.fitBounds(this._bounds, fitBoundsOptions); + } + }, + + getBounds: function () { + var bounds = new L.LatLngBounds(); + bounds.extend(this._bounds); + return bounds; + }, + + _updateIcon: function () { + this._iconNeedsUpdate = true; + if (this._icon) { + this.setIcon(this); + } + }, + + //Cludge for Icon, we pretend to be an icon for performance + createIcon: function () { + if (this._iconNeedsUpdate) { + this._iconObj = this._group.options.iconCreateFunction(this); + this._iconNeedsUpdate = false; + } + return this._iconObj.createIcon(); + }, + createShadow: function () { + return this._iconObj.createShadow(); + }, + + + _addChild: function (new1, isNotificationFromChild) { + + this._iconNeedsUpdate = true; + + this._boundsNeedUpdate = true; + this._setClusterCenter(new1); + + if (new1 instanceof L.MarkerCluster) { + if (!isNotificationFromChild) { + this._childClusters.push(new1); + new1.__parent = this; + } + this._childCount += new1._childCount; + } else { + if (!isNotificationFromChild) { + this._markers.push(new1); + } + this._childCount++; + } + + if (this.__parent) { + this.__parent._addChild(new1, true); + } + }, + + /** + * Makes sure the cluster center is set. If not, uses the child center if it is a cluster, or the marker position. + * @param child L.MarkerCluster|L.Marker that will be used as cluster center if not defined yet. + * @private + */ + _setClusterCenter: function (child) { + if (!this._cLatLng) { + // when clustering, take position of the first point as the cluster center + this._cLatLng = child._cLatLng || child._latlng; + } + }, + + /** + * Assigns impossible bounding values so that the next extend entirely determines the new bounds. + * This method avoids having to trash the previous L.LatLngBounds object and to create a new one, which is much slower for this class. + * As long as the bounds are not extended, most other methods would probably fail, as they would with bounds initialized but not extended. + * @private + */ + _resetBounds: function () { + var bounds = this._bounds; + + if (bounds._southWest) { + bounds._southWest.lat = Infinity; + bounds._southWest.lng = Infinity; + } + if (bounds._northEast) { + bounds._northEast.lat = -Infinity; + bounds._northEast.lng = -Infinity; + } + }, + + _recalculateBounds: function () { + var markers = this._markers, + childClusters = this._childClusters, + latSum = 0, + lngSum = 0, + totalCount = this._childCount, + i, child, childLatLng, childCount; + + // Case where all markers are removed from the map and we are left with just an empty _topClusterLevel. + if (totalCount === 0) { + return; + } + + // Reset rather than creating a new object, for performance. + this._resetBounds(); + + // Child markers. + for (i = 0; i < markers.length; i++) { + childLatLng = markers[i]._latlng; + + this._bounds.extend(childLatLng); + + latSum += childLatLng.lat; + lngSum += childLatLng.lng; + } + + // Child clusters. + for (i = 0; i < childClusters.length; i++) { + child = childClusters[i]; + + // Re-compute child bounds and weighted position first if necessary. + if (child._boundsNeedUpdate) { + child._recalculateBounds(); + } + + this._bounds.extend(child._bounds); + + childLatLng = child._wLatLng; + childCount = child._childCount; + + latSum += childLatLng.lat * childCount; + lngSum += childLatLng.lng * childCount; + } + + this._latlng = this._wLatLng = new L.LatLng(latSum / totalCount, lngSum / totalCount); + + // Reset dirty flag. + this._boundsNeedUpdate = false; + }, + + //Set our markers position as given and add it to the map + _addToMap: function (startPos) { + if (startPos) { + this._backupLatlng = this._latlng; + this.setLatLng(startPos); + } + this._group._featureGroup.addLayer(this); + }, + + _recursivelyAnimateChildrenIn: function (bounds, center, maxZoom) { + this._recursively(bounds, this._group._map.getMinZoom(), maxZoom - 1, + function (c) { + var markers = c._markers, + i, m; + for (i = markers.length - 1; i >= 0; i--) { + m = markers[i]; + + //Only do it if the icon is still on the map + if (m._icon) { + m._setPos(center); + m.clusterHide(); + } + } + }, + function (c) { + var childClusters = c._childClusters, + j, cm; + for (j = childClusters.length - 1; j >= 0; j--) { + cm = childClusters[j]; + if (cm._icon) { + cm._setPos(center); + cm.clusterHide(); + } + } + } + ); + }, + + _recursivelyAnimateChildrenInAndAddSelfToMap: function (bounds, mapMinZoom, previousZoomLevel, newZoomLevel) { + this._recursively(bounds, newZoomLevel, mapMinZoom, + function (c) { + c._recursivelyAnimateChildrenIn(bounds, c._group._map.latLngToLayerPoint(c.getLatLng()).round(), previousZoomLevel); + + //TODO: depthToAnimateIn affects _isSingleParent, if there is a multizoom we may/may not be. + //As a hack we only do a animation free zoom on a single level zoom, if someone does multiple levels then we always animate + if (c._isSingleParent() && previousZoomLevel - 1 === newZoomLevel) { + c.clusterShow(); + c._recursivelyRemoveChildrenFromMap(bounds, mapMinZoom, previousZoomLevel); //Immediately remove our children as we are replacing them. TODO previousBounds not bounds + } else { + c.clusterHide(); + } + + c._addToMap(); + } + ); + }, + + _recursivelyBecomeVisible: function (bounds, zoomLevel) { + this._recursively(bounds, this._group._map.getMinZoom(), zoomLevel, null, function (c) { + c.clusterShow(); + }); + }, + + _recursivelyAddChildrenToMap: function (startPos, zoomLevel, bounds) { + this._recursively(bounds, this._group._map.getMinZoom() - 1, zoomLevel, + function (c) { + if (zoomLevel === c._zoom) { + return; + } + + //Add our child markers at startPos (so they can be animated out) + for (var i = c._markers.length - 1; i >= 0; i--) { + var nm = c._markers[i]; + + if (!bounds.contains(nm._latlng)) { + continue; + } + + if (startPos) { + nm._backupLatlng = nm.getLatLng(); + + nm.setLatLng(startPos); + if (nm.clusterHide) { + nm.clusterHide(); + } + } + + c._group._featureGroup.addLayer(nm); + } + }, + function (c) { + c._addToMap(startPos); + } + ); + }, + + _recursivelyRestoreChildPositions: function (zoomLevel) { + //Fix positions of child markers + for (var i = this._markers.length - 1; i >= 0; i--) { + var nm = this._markers[i]; + if (nm._backupLatlng) { + nm.setLatLng(nm._backupLatlng); + delete nm._backupLatlng; + } + } + + if (zoomLevel - 1 === this._zoom) { + //Reposition child clusters + for (var j = this._childClusters.length - 1; j >= 0; j--) { + this._childClusters[j]._restorePosition(); + } + } else { + for (var k = this._childClusters.length - 1; k >= 0; k--) { + this._childClusters[k]._recursivelyRestoreChildPositions(zoomLevel); + } + } + }, + + _restorePosition: function () { + if (this._backupLatlng) { + this.setLatLng(this._backupLatlng); + delete this._backupLatlng; + } + }, + + //exceptBounds: If set, don't remove any markers/clusters in it + _recursivelyRemoveChildrenFromMap: function (previousBounds, mapMinZoom, zoomLevel, exceptBounds) { + var m, i; + this._recursively(previousBounds, mapMinZoom - 1, zoomLevel - 1, + function (c) { + //Remove markers at every level + for (i = c._markers.length - 1; i >= 0; i--) { + m = c._markers[i]; + if (!exceptBounds || !exceptBounds.contains(m._latlng)) { + c._group._featureGroup.removeLayer(m); + if (m.clusterShow) { + m.clusterShow(); + } + } + } + }, + function (c) { + //Remove child clusters at just the bottom level + for (i = c._childClusters.length - 1; i >= 0; i--) { + m = c._childClusters[i]; + if (!exceptBounds || !exceptBounds.contains(m._latlng)) { + c._group._featureGroup.removeLayer(m); + if (m.clusterShow) { + m.clusterShow(); + } + } + } + } + ); + }, + + //Run the given functions recursively to this and child clusters + // boundsToApplyTo: a L.LatLngBounds representing the bounds of what clusters to recurse in to + // zoomLevelToStart: zoom level to start running functions (inclusive) + // zoomLevelToStop: zoom level to stop running functions (inclusive) + // runAtEveryLevel: function that takes an L.MarkerCluster as an argument that should be applied on every level + // runAtBottomLevel: function that takes an L.MarkerCluster as an argument that should be applied at only the bottom level + _recursively: function (boundsToApplyTo, zoomLevelToStart, zoomLevelToStop, runAtEveryLevel, runAtBottomLevel) { + var childClusters = this._childClusters, + zoom = this._zoom, + i, c; + + if (zoomLevelToStart <= zoom) { + if (runAtEveryLevel) { + runAtEveryLevel(this); + } + if (runAtBottomLevel && zoom === zoomLevelToStop) { + runAtBottomLevel(this); + } + } + + if (zoom < zoomLevelToStart || zoom < zoomLevelToStop) { + for (i = childClusters.length - 1; i >= 0; i--) { + c = childClusters[i]; + if (c._boundsNeedUpdate) { + c._recalculateBounds(); + } + if (boundsToApplyTo.intersects(c._bounds)) { + c._recursively(boundsToApplyTo, zoomLevelToStart, zoomLevelToStop, runAtEveryLevel, runAtBottomLevel); + } + } + } + }, + + //Returns true if we are the parent of only one cluster and that cluster is the same as us + _isSingleParent: function () { + //Don't need to check this._markers as the rest won't work if there are any + return this._childClusters.length > 0 && this._childClusters[0]._childCount === this._childCount; + } +}); + +/* +* Extends L.Marker to include two extra methods: clusterHide and clusterShow. +* +* They work as setOpacity(0) and setOpacity(1) respectively, but +* don't overwrite the options.opacity +* +*/ + +L.Marker.include({ + clusterHide: function () { + var backup = this.options.opacity; + this.setOpacity(0); + this.options.opacity = backup; + return this; + }, + + clusterShow: function () { + return this.setOpacity(this.options.opacity); + } +}); + +L.DistanceGrid = function (cellSize) { + this._cellSize = cellSize; + this._sqCellSize = cellSize * cellSize; + this._grid = {}; + this._objectPoint = { }; +}; + +L.DistanceGrid.prototype = { + + addObject: function (obj, point) { + var x = this._getCoord(point.x), + y = this._getCoord(point.y), + grid = this._grid, + row = grid[y] = grid[y] || {}, + cell = row[x] = row[x] || [], + stamp = L.Util.stamp(obj); + + this._objectPoint[stamp] = point; + + cell.push(obj); + }, + + updateObject: function (obj, point) { + this.removeObject(obj); + this.addObject(obj, point); + }, + + //Returns true if the object was found + removeObject: function (obj, point) { + var x = this._getCoord(point.x), + y = this._getCoord(point.y), + grid = this._grid, + row = grid[y] = grid[y] || {}, + cell = row[x] = row[x] || [], + i, len; + + delete this._objectPoint[L.Util.stamp(obj)]; + + for (i = 0, len = cell.length; i < len; i++) { + if (cell[i] === obj) { + + cell.splice(i, 1); + + if (len === 1) { + delete row[x]; + } + + return true; + } + } + + }, + + eachObject: function (fn, context) { + var i, j, k, len, row, cell, removed, + grid = this._grid; + + for (i in grid) { + row = grid[i]; + + for (j in row) { + cell = row[j]; + + for (k = 0, len = cell.length; k < len; k++) { + removed = fn.call(context, cell[k]); + if (removed) { + k--; + len--; + } + } + } + } + }, + + getNearObject: function (point) { + var x = this._getCoord(point.x), + y = this._getCoord(point.y), + i, j, k, row, cell, len, obj, dist, + objectPoint = this._objectPoint, + closestDistSq = this._sqCellSize, + closest = null; + + for (i = y - 1; i <= y + 1; i++) { + row = this._grid[i]; + if (row) { + + for (j = x - 1; j <= x + 1; j++) { + cell = row[j]; + if (cell) { + + for (k = 0, len = cell.length; k < len; k++) { + obj = cell[k]; + dist = this._sqDist(objectPoint[L.Util.stamp(obj)], point); + if (dist < closestDistSq || + dist <= closestDistSq && closest === null) { + closestDistSq = dist; + closest = obj; + } + } + } + } + } + } + return closest; + }, + + _getCoord: function (x) { + var coord = Math.floor(x / this._cellSize); + return isFinite(coord) ? coord : x; + }, + + _sqDist: function (p, p2) { + var dx = p2.x - p.x, + dy = p2.y - p.y; + return dx * dx + dy * dy; + } +}; + +/* Copyright (c) 2012 the authors listed at the following URL, and/or +the authors of referenced articles or incorporated external code: +http://en.literateprograms.org/Quickhull_(Javascript)?action=history&offset=20120410175256 + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Retrieved from: http://en.literateprograms.org/Quickhull_(Javascript)?oldid=18434 +*/ + +(function () { + L.QuickHull = { + + /* + * @param {Object} cpt a point to be measured from the baseline + * @param {Array} bl the baseline, as represented by a two-element + * array of latlng objects. + * @returns {Number} an approximate distance measure + */ + getDistant: function (cpt, bl) { + var vY = bl[1].lat - bl[0].lat, + vX = bl[0].lng - bl[1].lng; + return (vX * (cpt.lat - bl[0].lat) + vY * (cpt.lng - bl[0].lng)); + }, + + /* + * @param {Array} baseLine a two-element array of latlng objects + * representing the baseline to project from + * @param {Array} latLngs an array of latlng objects + * @returns {Object} the maximum point and all new points to stay + * in consideration for the hull. + */ + findMostDistantPointFromBaseLine: function (baseLine, latLngs) { + var maxD = 0, + maxPt = null, + newPoints = [], + i, pt, d; + + for (i = latLngs.length - 1; i >= 0; i--) { + pt = latLngs[i]; + d = this.getDistant(pt, baseLine); + + if (d > 0) { + newPoints.push(pt); + } else { + continue; + } + + if (d > maxD) { + maxD = d; + maxPt = pt; + } + } + + return { maxPoint: maxPt, newPoints: newPoints }; + }, + + + /* + * Given a baseline, compute the convex hull of latLngs as an array + * of latLngs. + * + * @param {Array} latLngs + * @returns {Array} + */ + buildConvexHull: function (baseLine, latLngs) { + var convexHullBaseLines = [], + t = this.findMostDistantPointFromBaseLine(baseLine, latLngs); + + if (t.maxPoint) { // if there is still a point "outside" the base line + convexHullBaseLines = + convexHullBaseLines.concat( + this.buildConvexHull([baseLine[0], t.maxPoint], t.newPoints) + ); + convexHullBaseLines = + convexHullBaseLines.concat( + this.buildConvexHull([t.maxPoint, baseLine[1]], t.newPoints) + ); + return convexHullBaseLines; + } else { // if there is no more point "outside" the base line, the current base line is part of the convex hull + return [baseLine[0]]; + } + }, + + /* + * Given an array of latlngs, compute a convex hull as an array + * of latlngs + * + * @param {Array} latLngs + * @returns {Array} + */ + getConvexHull: function (latLngs) { + // find first baseline + var maxLat = false, minLat = false, + maxLng = false, minLng = false, + maxLatPt = null, minLatPt = null, + maxLngPt = null, minLngPt = null, + maxPt = null, minPt = null, + i; + + for (i = latLngs.length - 1; i >= 0; i--) { + var pt = latLngs[i]; + if (maxLat === false || pt.lat > maxLat) { + maxLatPt = pt; + maxLat = pt.lat; + } + if (minLat === false || pt.lat < minLat) { + minLatPt = pt; + minLat = pt.lat; + } + if (maxLng === false || pt.lng > maxLng) { + maxLngPt = pt; + maxLng = pt.lng; + } + if (minLng === false || pt.lng < minLng) { + minLngPt = pt; + minLng = pt.lng; + } + } + + if (minLat !== maxLat) { + minPt = minLatPt; + maxPt = maxLatPt; + } else { + minPt = minLngPt; + maxPt = maxLngPt; + } + + var ch = [].concat(this.buildConvexHull([minPt, maxPt], latLngs), + this.buildConvexHull([maxPt, minPt], latLngs)); + return ch; + } + }; +}()); + +L.MarkerCluster.include({ + getConvexHull: function () { + var childMarkers = this.getAllChildMarkers(), + points = [], + p, i; + + for (i = childMarkers.length - 1; i >= 0; i--) { + p = childMarkers[i].getLatLng(); + points.push(p); + } + + return L.QuickHull.getConvexHull(points); + } +}); + +//This code is 100% based on https://github.com/jawj/OverlappingMarkerSpiderfier-Leaflet +//Huge thanks to jawj for implementing it first to make my job easy :-) + +L.MarkerCluster.include({ + + _2PI: Math.PI * 2, + _circleFootSeparation: 25, //related to circumference of circle + _circleStartAngle: 0, + + _spiralFootSeparation: 28, //related to size of spiral (experiment!) + _spiralLengthStart: 11, + _spiralLengthFactor: 5, + + _circleSpiralSwitchover: 9, //show spiral instead of circle from this marker count upwards. + // 0 -> always spiral; Infinity -> always circle + + spiderfy: function () { + if (this._group._spiderfied === this || this._group._inZoomAnimation) { + return; + } + + var childMarkers = this.getAllChildMarkers(null, true), + group = this._group, + map = group._map, + center = map.latLngToLayerPoint(this._latlng), + positions; + + this._group._unspiderfy(); + this._group._spiderfied = this; + + //TODO Maybe: childMarkers order by distance to center + + if (childMarkers.length >= this._circleSpiralSwitchover) { + positions = this._generatePointsSpiral(childMarkers.length, center); + } else { + center.y += 10; // Otherwise circles look wrong => hack for standard blue icon, renders differently for other icons. + positions = this._generatePointsCircle(childMarkers.length, center); + } + + this._animationSpiderfy(childMarkers, positions); + }, + + unspiderfy: function (zoomDetails) { + /// Argument from zoomanim if being called in a zoom animation or null otherwise + if (this._group._inZoomAnimation) { + return; + } + this._animationUnspiderfy(zoomDetails); + + this._group._spiderfied = null; + }, + + _generatePointsCircle: function (count, centerPt) { + var circumference = this._group.options.spiderfyDistanceMultiplier * this._circleFootSeparation * (2 + count), + legLength = circumference / this._2PI, //radius from circumference + angleStep = this._2PI / count, + res = [], + i, angle; + + legLength = Math.max(legLength, 35); // Minimum distance to get outside the cluster icon. + + res.length = count; + + for (i = 0; i < count; i++) { // Clockwise, like spiral. + angle = this._circleStartAngle + i * angleStep; + res[i] = new L.Point(centerPt.x + legLength * Math.cos(angle), centerPt.y + legLength * Math.sin(angle))._round(); + } + + return res; + }, + + _generatePointsSpiral: function (count, centerPt) { + var spiderfyDistanceMultiplier = this._group.options.spiderfyDistanceMultiplier, + legLength = spiderfyDistanceMultiplier * this._spiralLengthStart, + separation = spiderfyDistanceMultiplier * this._spiralFootSeparation, + lengthFactor = spiderfyDistanceMultiplier * this._spiralLengthFactor * this._2PI, + angle = 0, + res = [], + i; + + res.length = count; + + // Higher index, closer position to cluster center. + for (i = count; i >= 0; i--) { + // Skip the first position, so that we are already farther from center and we avoid + // being under the default cluster icon (especially important for Circle Markers). + if (i < count) { + res[i] = new L.Point(centerPt.x + legLength * Math.cos(angle), centerPt.y + legLength * Math.sin(angle))._round(); + } + angle += separation / legLength + i * 0.0005; + legLength += lengthFactor / angle; + } + return res; + }, + + _noanimationUnspiderfy: function () { + var group = this._group, + map = group._map, + fg = group._featureGroup, + childMarkers = this.getAllChildMarkers(null, true), + m, i; + + group._ignoreMove = true; + + this.setOpacity(1); + for (i = childMarkers.length - 1; i >= 0; i--) { + m = childMarkers[i]; + + fg.removeLayer(m); + + if (m._preSpiderfyLatlng) { + m.setLatLng(m._preSpiderfyLatlng); + delete m._preSpiderfyLatlng; + } + if (m.setZIndexOffset) { + m.setZIndexOffset(0); + } + + if (m._spiderLeg) { + map.removeLayer(m._spiderLeg); + delete m._spiderLeg; + } + } + + group.fire('unspiderfied', { + cluster: this, + markers: childMarkers + }); + group._ignoreMove = false; + group._spiderfied = null; + } +}); + +//Non Animated versions of everything +L.MarkerClusterNonAnimated = L.MarkerCluster.extend({ + _animationSpiderfy: function (childMarkers, positions) { + var group = this._group, + map = group._map, + fg = group._featureGroup, + legOptions = this._group.options.spiderLegPolylineOptions, + i, m, leg, newPos; + + group._ignoreMove = true; + + // Traverse in ascending order to make sure that inner circleMarkers are on top of further legs. Normal markers are re-ordered by newPosition. + // The reverse order trick no longer improves performance on modern browsers. + for (i = 0; i < childMarkers.length; i++) { + newPos = map.layerPointToLatLng(positions[i]); + m = childMarkers[i]; + + // Add the leg before the marker, so that in case the latter is a circleMarker, the leg is behind it. + leg = new L.Polyline([this._latlng, newPos], legOptions); + map.addLayer(leg); + m._spiderLeg = leg; + + // Now add the marker. + m._preSpiderfyLatlng = m._latlng; + m.setLatLng(newPos); + if (m.setZIndexOffset) { + m.setZIndexOffset(1000000); //Make these appear on top of EVERYTHING + } + + fg.addLayer(m); + } + this.setOpacity(0.3); + + group._ignoreMove = false; + group.fire('spiderfied', { + cluster: this, + markers: childMarkers + }); + }, + + _animationUnspiderfy: function () { + this._noanimationUnspiderfy(); + } +}); + +//Animated versions here +L.MarkerCluster.include({ + + _animationSpiderfy: function (childMarkers, positions) { + var me = this, + group = this._group, + map = group._map, + fg = group._featureGroup, + thisLayerLatLng = this._latlng, + thisLayerPos = map.latLngToLayerPoint(thisLayerLatLng), + svg = L.Path.SVG, + legOptions = L.extend({}, this._group.options.spiderLegPolylineOptions), // Copy the options so that we can modify them for animation. + finalLegOpacity = legOptions.opacity, + i, m, leg, legPath, legLength, newPos; + + if (finalLegOpacity === undefined) { + finalLegOpacity = L.MarkerClusterGroup.prototype.options.spiderLegPolylineOptions.opacity; + } + + if (svg) { + // If the initial opacity of the spider leg is not 0 then it appears before the animation starts. + legOptions.opacity = 0; + + // Add the class for CSS transitions. + legOptions.className = (legOptions.className || '') + ' leaflet-cluster-spider-leg'; + } else { + // Make sure we have a defined opacity. + legOptions.opacity = finalLegOpacity; + } + + group._ignoreMove = true; + + // Add markers and spider legs to map, hidden at our center point. + // Traverse in ascending order to make sure that inner circleMarkers are on top of further legs. Normal markers are re-ordered by newPosition. + // The reverse order trick no longer improves performance on modern browsers. + for (i = 0; i < childMarkers.length; i++) { + m = childMarkers[i]; + + newPos = map.layerPointToLatLng(positions[i]); + + // Add the leg before the marker, so that in case the latter is a circleMarker, the leg is behind it. + leg = new L.Polyline([thisLayerLatLng, newPos], legOptions); + map.addLayer(leg); + m._spiderLeg = leg; + + // Explanations: https://jakearchibald.com/2013/animated-line-drawing-svg/ + // In our case the transition property is declared in the CSS file. + if (svg) { + legPath = leg._path; + legLength = legPath.getTotalLength() + 0.1; // Need a small extra length to avoid remaining dot in Firefox. + legPath.style.strokeDasharray = legLength; // Just 1 length is enough, it will be duplicated. + legPath.style.strokeDashoffset = legLength; + } + + // If it is a marker, add it now and we'll animate it out + if (m.setZIndexOffset) { + m.setZIndexOffset(1000000); // Make normal markers appear on top of EVERYTHING + } + if (m.clusterHide) { + m.clusterHide(); + } + + // Vectors just get immediately added + fg.addLayer(m); + + if (m._setPos) { + m._setPos(thisLayerPos); + } + } + + group._forceLayout(); + group._animationStart(); + + // Reveal markers and spider legs. + for (i = childMarkers.length - 1; i >= 0; i--) { + newPos = map.layerPointToLatLng(positions[i]); + m = childMarkers[i]; + + //Move marker to new position + m._preSpiderfyLatlng = m._latlng; + m.setLatLng(newPos); + + if (m.clusterShow) { + m.clusterShow(); + } + + // Animate leg (animation is actually delegated to CSS transition). + if (svg) { + leg = m._spiderLeg; + legPath = leg._path; + legPath.style.strokeDashoffset = 0; + //legPath.style.strokeOpacity = finalLegOpacity; + leg.setStyle({opacity: finalLegOpacity}); + } + } + this.setOpacity(0.3); + + group._ignoreMove = false; + + setTimeout(function () { + group._animationEnd(); + group.fire('spiderfied', { + cluster: me, + markers: childMarkers + }); + }, 200); + }, + + _animationUnspiderfy: function (zoomDetails) { + var me = this, + group = this._group, + map = group._map, + fg = group._featureGroup, + thisLayerPos = zoomDetails ? map._latLngToNewLayerPoint(this._latlng, zoomDetails.zoom, zoomDetails.center) : map.latLngToLayerPoint(this._latlng), + childMarkers = this.getAllChildMarkers(null, true), + svg = L.Path.SVG, + m, i, leg, legPath, legLength, nonAnimatable; + + group._ignoreMove = true; + group._animationStart(); + + //Make us visible and bring the child markers back in + this.setOpacity(1); + for (i = childMarkers.length - 1; i >= 0; i--) { + m = childMarkers[i]; + + //Marker was added to us after we were spiderfied + if (!m._preSpiderfyLatlng) { + continue; + } + + //Close any popup on the marker first, otherwise setting the location of the marker will make the map scroll + m.closePopup(); + + //Fix up the location to the real one + m.setLatLng(m._preSpiderfyLatlng); + delete m._preSpiderfyLatlng; + + //Hack override the location to be our center + nonAnimatable = true; + if (m._setPos) { + m._setPos(thisLayerPos); + nonAnimatable = false; + } + if (m.clusterHide) { + m.clusterHide(); + nonAnimatable = false; + } + if (nonAnimatable) { + fg.removeLayer(m); + } + + // Animate the spider leg back in (animation is actually delegated to CSS transition). + if (svg) { + leg = m._spiderLeg; + legPath = leg._path; + legLength = legPath.getTotalLength() + 0.1; + legPath.style.strokeDashoffset = legLength; + leg.setStyle({opacity: 0}); + } + } + + group._ignoreMove = false; + + setTimeout(function () { + //If we have only <= one child left then that marker will be shown on the map so don't remove it! + var stillThereChildCount = 0; + for (i = childMarkers.length - 1; i >= 0; i--) { + m = childMarkers[i]; + if (m._spiderLeg) { + stillThereChildCount++; + } + } + + + for (i = childMarkers.length - 1; i >= 0; i--) { + m = childMarkers[i]; + + if (!m._spiderLeg) { //Has already been unspiderfied + continue; + } + + if (m.clusterShow) { + m.clusterShow(); + } + if (m.setZIndexOffset) { + m.setZIndexOffset(0); + } + + if (stillThereChildCount > 1) { + fg.removeLayer(m); + } + + map.removeLayer(m._spiderLeg); + delete m._spiderLeg; + } + group._animationEnd(); + group.fire('unspiderfied', { + cluster: me, + markers: childMarkers + }); + }, 200); + } +}); + + +L.MarkerClusterGroup.include({ + //The MarkerCluster currently spiderfied (if any) + _spiderfied: null, + + unspiderfy: function () { + this._unspiderfy.apply(this, arguments); + }, + + _spiderfierOnAdd: function () { + this._map.on('click', this._unspiderfyWrapper, this); + + if (this._map.options.zoomAnimation) { + this._map.on('zoomstart', this._unspiderfyZoomStart, this); + } + //Browsers without zoomAnimation or a big zoom don't fire zoomstart + this._map.on('zoomend', this._noanimationUnspiderfy, this); + + if (!L.Browser.touch) { + this._map.getRenderer(this); + //Needs to happen in the pageload, not after, or animations don't work in webkit + // http://stackoverflow.com/questions/8455200/svg-animate-with-dynamically-added-elements + //Disable on touch browsers as the animation messes up on a touch zoom and isn't very noticable + } + }, + + _spiderfierOnRemove: function () { + this._map.off('click', this._unspiderfyWrapper, this); + this._map.off('zoomstart', this._unspiderfyZoomStart, this); + this._map.off('zoomanim', this._unspiderfyZoomAnim, this); + this._map.off('zoomend', this._noanimationUnspiderfy, this); + + //Ensure that markers are back where they should be + // Use no animation to avoid a sticky leaflet-cluster-anim class on mapPane + this._noanimationUnspiderfy(); + }, + + //On zoom start we add a zoomanim handler so that we are guaranteed to be last (after markers are animated) + //This means we can define the animation they do rather than Markers doing an animation to their actual location + _unspiderfyZoomStart: function () { + if (!this._map) { //May have been removed from the map by a zoomEnd handler + return; + } + + this._map.on('zoomanim', this._unspiderfyZoomAnim, this); + }, + + _unspiderfyZoomAnim: function (zoomDetails) { + //Wait until the first zoomanim after the user has finished touch-zooming before running the animation + if (L.DomUtil.hasClass(this._map._mapPane, 'leaflet-touching')) { + return; + } + + this._map.off('zoomanim', this._unspiderfyZoomAnim, this); + this._unspiderfy(zoomDetails); + }, + + _unspiderfyWrapper: function () { + /// _unspiderfy but passes no arguments + this._unspiderfy(); + }, + + _unspiderfy: function (zoomDetails) { + if (this._spiderfied) { + this._spiderfied.unspiderfy(zoomDetails); + } + }, + + _noanimationUnspiderfy: function () { + if (this._spiderfied) { + this._spiderfied._noanimationUnspiderfy(); + } + }, + + //If the given layer is currently being spiderfied then we unspiderfy it so it isn't on the map anymore etc + _unspiderfyLayer: function (layer) { + if (layer._spiderLeg) { + this._featureGroup.removeLayer(layer); + + if (layer.clusterShow) { + layer.clusterShow(); + } + //Position will be fixed up immediately in _animationUnspiderfy + if (layer.setZIndexOffset) { + layer.setZIndexOffset(0); + } + + this._map.removeLayer(layer._spiderLeg); + delete layer._spiderLeg; + } + } +}); + +/** + * Adds 1 public method to MCG and 1 to L.Marker to facilitate changing + * markers' icon options and refreshing their icon and their parent clusters + * accordingly (case where their iconCreateFunction uses data of childMarkers + * to make up the cluster icon). + */ + + +L.MarkerClusterGroup.include({ + /** + * Updates the icon of all clusters which are parents of the given marker(s). + * In singleMarkerMode, also updates the given marker(s) icon. + * @param layers L.MarkerClusterGroup|L.LayerGroup|Array(L.Marker)|Map(L.Marker)| + * L.MarkerCluster|L.Marker (optional) list of markers (or single marker) whose parent + * clusters need to be updated. If not provided, retrieves all child markers of this. + * @returns {L.MarkerClusterGroup} + */ + refreshClusters: function (layers) { + if (!layers) { + layers = this._topClusterLevel.getAllChildMarkers(); + } else if (layers instanceof L.MarkerClusterGroup) { + layers = layers._topClusterLevel.getAllChildMarkers(); + } else if (layers instanceof L.LayerGroup) { + layers = layers._layers; + } else if (layers instanceof L.MarkerCluster) { + layers = layers.getAllChildMarkers(); + } else if (layers instanceof L.Marker) { + layers = [layers]; + } // else: must be an Array(L.Marker)|Map(L.Marker) + this._flagParentsIconsNeedUpdate(layers); + this._refreshClustersIcons(); + + // In case of singleMarkerMode, also re-draw the markers. + if (this.options.singleMarkerMode) { + this._refreshSingleMarkerModeMarkers(layers); + } + + return this; + }, + + /** + * Simply flags all parent clusters of the given markers as having a "dirty" icon. + * @param layers Array(L.Marker)|Map(L.Marker) list of markers. + * @private + */ + _flagParentsIconsNeedUpdate: function (layers) { + var id, parent; + + // Assumes layers is an Array or an Object whose prototype is non-enumerable. + for (id in layers) { + // Flag parent clusters' icon as "dirty", all the way up. + // Dumb process that flags multiple times upper parents, but still + // much more efficient than trying to be smart and make short lists, + // at least in the case of a hierarchy following a power law: + // http://jsperf.com/flag-nodes-in-power-hierarchy/2 + parent = layers[id].__parent; + while (parent) { + parent._iconNeedsUpdate = true; + parent = parent.__parent; + } + } + }, + + /** + * Re-draws the icon of the supplied markers. + * To be used in singleMarkerMode only. + * @param layers Array(L.Marker)|Map(L.Marker) list of markers. + * @private + */ + _refreshSingleMarkerModeMarkers: function (layers) { + var id, layer; + + for (id in layers) { + layer = layers[id]; + + // Make sure we do not override markers that do not belong to THIS group. + if (this.hasLayer(layer)) { + // Need to re-create the icon first, then re-draw the marker. + layer.setIcon(this._overrideMarkerIcon(layer)); + } + } + } +}); + +L.Marker.include({ + /** + * Updates the given options in the marker's icon and refreshes the marker. + * @param options map object of icon options. + * @param directlyRefreshClusters boolean (optional) true to trigger + * MCG.refreshClustersOf() right away with this single marker. + * @returns {L.Marker} + */ + refreshIconOptions: function (options, directlyRefreshClusters) { + var icon = this.options.icon; + + L.setOptions(icon, options); + + this.setIcon(icon); + + // Shortcut to refresh the associated MCG clusters right away. + // To be used when refreshing a single marker. + // Otherwise, better use MCG.refreshClusters() once at the end with + // the list of modified markers. + if (directlyRefreshClusters && this.__parent) { + this.__parent._group.refreshClusters(this); + } + + return this; + } +}); + +exports.MarkerClusterGroup = MarkerClusterGroup; +exports.MarkerCluster = MarkerCluster; + +}))); +//# sourceMappingURL=leaflet.markercluster-src.js.map diff --git a/deploy/grafana-map-plugin/dist/vendor/leaflet.markercluster/leaflet.markercluster-src.js.map b/deploy/grafana-map-plugin/dist/vendor/leaflet.markercluster/leaflet.markercluster-src.js.map new file mode 100755 index 0000000..30220ae --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/leaflet.markercluster/leaflet.markercluster-src.js.map @@ -0,0 +1 @@ +{"version":3,"file":"leaflet.markercluster-src.js","sources":["../src/MarkerClusterGroup.js","../src/MarkerCluster.js","../src/MarkerOpacity.js","../src/DistanceGrid.js","../src/MarkerCluster.QuickHull.js","../src/MarkerCluster.Spiderfier.js","../src/MarkerClusterGroup.Refresh.js"],"sourcesContent":["/*\r\n * L.MarkerClusterGroup extends L.FeatureGroup by clustering the markers contained within\r\n */\r\n\r\nexport var MarkerClusterGroup = L.MarkerClusterGroup = L.FeatureGroup.extend({\r\n\r\n\toptions: {\r\n\t\tmaxClusterRadius: 80, //A cluster will cover at most this many pixels from its center\r\n\t\ticonCreateFunction: null,\r\n\t\tclusterPane: L.Marker.prototype.options.pane,\r\n\r\n\t\tspiderfyOnMaxZoom: true,\r\n\t\tshowCoverageOnHover: true,\r\n\t\tzoomToBoundsOnClick: true,\r\n\t\tsingleMarkerMode: false,\r\n\r\n\t\tdisableClusteringAtZoom: null,\r\n\r\n\t\t// Setting this to false prevents the removal of any clusters outside of the viewpoint, which\r\n\t\t// is the default behaviour for performance reasons.\r\n\t\tremoveOutsideVisibleBounds: true,\r\n\r\n\t\t// Set to false to disable all animations (zoom and spiderfy).\r\n\t\t// If false, option animateAddingMarkers below has no effect.\r\n\t\t// If L.DomUtil.TRANSITION is falsy, this option has no effect.\r\n\t\tanimate: true,\r\n\r\n\t\t//Whether to animate adding markers after adding the MarkerClusterGroup to the map\r\n\t\t// If you are adding individual markers set to true, if adding bulk markers leave false for massive performance gains.\r\n\t\tanimateAddingMarkers: false,\r\n\r\n\t\t//Increase to increase the distance away that spiderfied markers appear from the center\r\n\t\tspiderfyDistanceMultiplier: 1,\r\n\r\n\t\t// Make it possible to specify a polyline options on a spider leg\r\n\t\tspiderLegPolylineOptions: { weight: 1.5, color: '#222', opacity: 0.5 },\r\n\r\n\t\t// When bulk adding layers, adds markers in chunks. Means addLayers may not add all the layers in the call, others will be loaded during setTimeouts\r\n\t\tchunkedLoading: false,\r\n\t\tchunkInterval: 200, // process markers for a maximum of ~ n milliseconds (then trigger the chunkProgress callback)\r\n\t\tchunkDelay: 50, // at the end of each interval, give n milliseconds back to system/browser\r\n\t\tchunkProgress: null, // progress callback: function(processed, total, elapsed) (e.g. for a progress indicator)\r\n\r\n\t\t//Options to pass to the L.Polygon constructor\r\n\t\tpolygonOptions: {}\r\n\t},\r\n\r\n\tinitialize: function (options) {\r\n\t\tL.Util.setOptions(this, options);\r\n\t\tif (!this.options.iconCreateFunction) {\r\n\t\t\tthis.options.iconCreateFunction = this._defaultIconCreateFunction;\r\n\t\t}\r\n\r\n\t\tthis._featureGroup = L.featureGroup();\r\n\t\tthis._featureGroup.addEventParent(this);\r\n\r\n\t\tthis._nonPointGroup = L.featureGroup();\r\n\t\tthis._nonPointGroup.addEventParent(this);\r\n\r\n\t\tthis._inZoomAnimation = 0;\r\n\t\tthis._needsClustering = [];\r\n\t\tthis._needsRemoving = []; //Markers removed while we aren't on the map need to be kept track of\r\n\t\t//The bounds of the currently shown area (from _getExpandedVisibleBounds) Updated on zoom/move\r\n\t\tthis._currentShownBounds = null;\r\n\r\n\t\tthis._queue = [];\r\n\r\n\t\tthis._childMarkerEventHandlers = {\r\n\t\t\t'dragstart': this._childMarkerDragStart,\r\n\t\t\t'move': this._childMarkerMoved,\r\n\t\t\t'dragend': this._childMarkerDragEnd,\r\n\t\t};\r\n\r\n\t\t// Hook the appropriate animation methods.\r\n\t\tvar animate = L.DomUtil.TRANSITION && this.options.animate;\r\n\t\tL.extend(this, animate ? this._withAnimation : this._noAnimation);\r\n\t\t// Remember which MarkerCluster class to instantiate (animated or not).\r\n\t\tthis._markerCluster = animate ? L.MarkerCluster : L.MarkerClusterNonAnimated;\r\n\t},\r\n\r\n\taddLayer: function (layer) {\r\n\r\n\t\tif (layer instanceof L.LayerGroup) {\r\n\t\t\treturn this.addLayers([layer]);\r\n\t\t}\r\n\r\n\t\t//Don't cluster non point data\r\n\t\tif (!layer.getLatLng) {\r\n\t\t\tthis._nonPointGroup.addLayer(layer);\r\n\t\t\tthis.fire('layeradd', { layer: layer });\r\n\t\t\treturn this;\r\n\t\t}\r\n\r\n\t\tif (!this._map) {\r\n\t\t\tthis._needsClustering.push(layer);\r\n\t\t\tthis.fire('layeradd', { layer: layer });\r\n\t\t\treturn this;\r\n\t\t}\r\n\r\n\t\tif (this.hasLayer(layer)) {\r\n\t\t\treturn this;\r\n\t\t}\r\n\r\n\r\n\t\t//If we have already clustered we'll need to add this one to a cluster\r\n\r\n\t\tif (this._unspiderfy) {\r\n\t\t\tthis._unspiderfy();\r\n\t\t}\r\n\r\n\t\tthis._addLayer(layer, this._maxZoom);\r\n\t\tthis.fire('layeradd', { layer: layer });\r\n\r\n\t\t// Refresh bounds and weighted positions.\r\n\t\tthis._topClusterLevel._recalculateBounds();\r\n\r\n\t\tthis._refreshClustersIcons();\r\n\r\n\t\t//Work out what is visible\r\n\t\tvar visibleLayer = layer,\r\n\t\t currentZoom = this._zoom;\r\n\t\tif (layer.__parent) {\r\n\t\t\twhile (visibleLayer.__parent._zoom >= currentZoom) {\r\n\t\t\t\tvisibleLayer = visibleLayer.__parent;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (this._currentShownBounds.contains(visibleLayer.getLatLng())) {\r\n\t\t\tif (this.options.animateAddingMarkers) {\r\n\t\t\t\tthis._animationAddLayer(layer, visibleLayer);\r\n\t\t\t} else {\r\n\t\t\t\tthis._animationAddLayerNonAnimated(layer, visibleLayer);\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\tremoveLayer: function (layer) {\r\n\r\n\t\tif (layer instanceof L.LayerGroup) {\r\n\t\t\treturn this.removeLayers([layer]);\r\n\t\t}\r\n\r\n\t\t//Non point layers\r\n\t\tif (!layer.getLatLng) {\r\n\t\t\tthis._nonPointGroup.removeLayer(layer);\r\n\t\t\tthis.fire('layerremove', { layer: layer });\r\n\t\t\treturn this;\r\n\t\t}\r\n\r\n\t\tif (!this._map) {\r\n\t\t\tif (!this._arraySplice(this._needsClustering, layer) && this.hasLayer(layer)) {\r\n\t\t\t\tthis._needsRemoving.push({ layer: layer, latlng: layer._latlng });\r\n\t\t\t}\r\n\t\t\tthis.fire('layerremove', { layer: layer });\r\n\t\t\treturn this;\r\n\t\t}\r\n\r\n\t\tif (!layer.__parent) {\r\n\t\t\treturn this;\r\n\t\t}\r\n\r\n\t\tif (this._unspiderfy) {\r\n\t\t\tthis._unspiderfy();\r\n\t\t\tthis._unspiderfyLayer(layer);\r\n\t\t}\r\n\r\n\t\t//Remove the marker from clusters\r\n\t\tthis._removeLayer(layer, true);\r\n\t\tthis.fire('layerremove', { layer: layer });\r\n\r\n\t\t// Refresh bounds and weighted positions.\r\n\t\tthis._topClusterLevel._recalculateBounds();\r\n\r\n\t\tthis._refreshClustersIcons();\r\n\r\n\t\tlayer.off(this._childMarkerEventHandlers, this);\r\n\r\n\t\tif (this._featureGroup.hasLayer(layer)) {\r\n\t\t\tthis._featureGroup.removeLayer(layer);\r\n\t\t\tif (layer.clusterShow) {\r\n\t\t\t\tlayer.clusterShow();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t//Takes an array of markers and adds them in bulk\r\n\taddLayers: function (layersArray, skipLayerAddEvent) {\r\n\t\tif (!L.Util.isArray(layersArray)) {\r\n\t\t\treturn this.addLayer(layersArray);\r\n\t\t}\r\n\r\n\t\tvar fg = this._featureGroup,\r\n\t\t npg = this._nonPointGroup,\r\n\t\t chunked = this.options.chunkedLoading,\r\n\t\t chunkInterval = this.options.chunkInterval,\r\n\t\t chunkProgress = this.options.chunkProgress,\r\n\t\t l = layersArray.length,\r\n\t\t offset = 0,\r\n\t\t originalArray = true,\r\n\t\t m;\r\n\r\n\t\tif (this._map) {\r\n\t\t\tvar started = (new Date()).getTime();\r\n\t\t\tvar process = L.bind(function () {\r\n\t\t\t\tvar start = (new Date()).getTime();\r\n\t\t\t\tfor (; offset < l; offset++) {\r\n\t\t\t\t\tif (chunked && offset % 200 === 0) {\r\n\t\t\t\t\t\t// every couple hundred markers, instrument the time elapsed since processing started:\r\n\t\t\t\t\t\tvar elapsed = (new Date()).getTime() - start;\r\n\t\t\t\t\t\tif (elapsed > chunkInterval) {\r\n\t\t\t\t\t\t\tbreak; // been working too hard, time to take a break :-)\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tm = layersArray[offset];\r\n\r\n\t\t\t\t\t// Group of layers, append children to layersArray and skip.\r\n\t\t\t\t\t// Side effects:\r\n\t\t\t\t\t// - Total increases, so chunkProgress ratio jumps backward.\r\n\t\t\t\t\t// - Groups are not included in this group, only their non-group child layers (hasLayer).\r\n\t\t\t\t\t// Changing array length while looping does not affect performance in current browsers:\r\n\t\t\t\t\t// http://jsperf.com/for-loop-changing-length/6\r\n\t\t\t\t\tif (m instanceof L.LayerGroup) {\r\n\t\t\t\t\t\tif (originalArray) {\r\n\t\t\t\t\t\t\tlayersArray = layersArray.slice();\r\n\t\t\t\t\t\t\toriginalArray = false;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tthis._extractNonGroupLayers(m, layersArray);\r\n\t\t\t\t\t\tl = layersArray.length;\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t//Not point data, can't be clustered\r\n\t\t\t\t\tif (!m.getLatLng) {\r\n\t\t\t\t\t\tnpg.addLayer(m);\r\n\t\t\t\t\t\tif (!skipLayerAddEvent) {\r\n\t\t\t\t\t\t\tthis.fire('layeradd', { layer: m });\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif (this.hasLayer(m)) {\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tthis._addLayer(m, this._maxZoom);\r\n\t\t\t\t\tif (!skipLayerAddEvent) {\r\n\t\t\t\t\t\tthis.fire('layeradd', { layer: m });\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t//If we just made a cluster of size 2 then we need to remove the other marker from the map (if it is) or we never will\r\n\t\t\t\t\tif (m.__parent) {\r\n\t\t\t\t\t\tif (m.__parent.getChildCount() === 2) {\r\n\t\t\t\t\t\t\tvar markers = m.__parent.getAllChildMarkers(),\r\n\t\t\t\t\t\t\t otherMarker = markers[0] === m ? markers[1] : markers[0];\r\n\t\t\t\t\t\t\tfg.removeLayer(otherMarker);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (chunkProgress) {\r\n\t\t\t\t\t// report progress and time elapsed:\r\n\t\t\t\t\tchunkProgress(offset, l, (new Date()).getTime() - started);\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Completed processing all markers.\r\n\t\t\t\tif (offset === l) {\r\n\r\n\t\t\t\t\t// Refresh bounds and weighted positions.\r\n\t\t\t\t\tthis._topClusterLevel._recalculateBounds();\r\n\r\n\t\t\t\t\tthis._refreshClustersIcons();\r\n\r\n\t\t\t\t\tthis._topClusterLevel._recursivelyAddChildrenToMap(null, this._zoom, this._currentShownBounds);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tsetTimeout(process, this.options.chunkDelay);\r\n\t\t\t\t}\r\n\t\t\t}, this);\r\n\r\n\t\t\tprocess();\r\n\t\t} else {\r\n\t\t\tvar needsClustering = this._needsClustering;\r\n\r\n\t\t\tfor (; offset < l; offset++) {\r\n\t\t\t\tm = layersArray[offset];\r\n\r\n\t\t\t\t// Group of layers, append children to layersArray and skip.\r\n\t\t\t\tif (m instanceof L.LayerGroup) {\r\n\t\t\t\t\tif (originalArray) {\r\n\t\t\t\t\t\tlayersArray = layersArray.slice();\r\n\t\t\t\t\t\toriginalArray = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tthis._extractNonGroupLayers(m, layersArray);\r\n\t\t\t\t\tl = layersArray.length;\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t//Not point data, can't be clustered\r\n\t\t\t\tif (!m.getLatLng) {\r\n\t\t\t\t\tnpg.addLayer(m);\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (this.hasLayer(m)) {\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tneedsClustering.push(m);\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t//Takes an array of markers and removes them in bulk\r\n\tremoveLayers: function (layersArray) {\r\n\t\tvar i, m,\r\n\t\t l = layersArray.length,\r\n\t\t fg = this._featureGroup,\r\n\t\t npg = this._nonPointGroup,\r\n\t\t originalArray = true;\r\n\r\n\t\tif (!this._map) {\r\n\t\t\tfor (i = 0; i < l; i++) {\r\n\t\t\t\tm = layersArray[i];\r\n\r\n\t\t\t\t// Group of layers, append children to layersArray and skip.\r\n\t\t\t\tif (m instanceof L.LayerGroup) {\r\n\t\t\t\t\tif (originalArray) {\r\n\t\t\t\t\t\tlayersArray = layersArray.slice();\r\n\t\t\t\t\t\toriginalArray = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tthis._extractNonGroupLayers(m, layersArray);\r\n\t\t\t\t\tl = layersArray.length;\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis._arraySplice(this._needsClustering, m);\r\n\t\t\t\tnpg.removeLayer(m);\r\n\t\t\t\tif (this.hasLayer(m)) {\r\n\t\t\t\t\tthis._needsRemoving.push({ layer: m, latlng: m._latlng });\r\n\t\t\t\t}\r\n\t\t\t\tthis.fire('layerremove', { layer: m });\r\n\t\t\t}\r\n\t\t\treturn this;\r\n\t\t}\r\n\r\n\t\tif (this._unspiderfy) {\r\n\t\t\tthis._unspiderfy();\r\n\r\n\t\t\t// Work on a copy of the array, so that next loop is not affected.\r\n\t\t\tvar layersArray2 = layersArray.slice(),\r\n\t\t\t l2 = l;\r\n\t\t\tfor (i = 0; i < l2; i++) {\r\n\t\t\t\tm = layersArray2[i];\r\n\r\n\t\t\t\t// Group of layers, append children to layersArray and skip.\r\n\t\t\t\tif (m instanceof L.LayerGroup) {\r\n\t\t\t\t\tthis._extractNonGroupLayers(m, layersArray2);\r\n\t\t\t\t\tl2 = layersArray2.length;\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis._unspiderfyLayer(m);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tfor (i = 0; i < l; i++) {\r\n\t\t\tm = layersArray[i];\r\n\r\n\t\t\t// Group of layers, append children to layersArray and skip.\r\n\t\t\tif (m instanceof L.LayerGroup) {\r\n\t\t\t\tif (originalArray) {\r\n\t\t\t\t\tlayersArray = layersArray.slice();\r\n\t\t\t\t\toriginalArray = false;\r\n\t\t\t\t}\r\n\t\t\t\tthis._extractNonGroupLayers(m, layersArray);\r\n\t\t\t\tl = layersArray.length;\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tif (!m.__parent) {\r\n\t\t\t\tnpg.removeLayer(m);\r\n\t\t\t\tthis.fire('layerremove', { layer: m });\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tthis._removeLayer(m, true, true);\r\n\t\t\tthis.fire('layerremove', { layer: m });\r\n\r\n\t\t\tif (fg.hasLayer(m)) {\r\n\t\t\t\tfg.removeLayer(m);\r\n\t\t\t\tif (m.clusterShow) {\r\n\t\t\t\t\tm.clusterShow();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Refresh bounds and weighted positions.\r\n\t\tthis._topClusterLevel._recalculateBounds();\r\n\r\n\t\tthis._refreshClustersIcons();\r\n\r\n\t\t//Fix up the clusters and markers on the map\r\n\t\tthis._topClusterLevel._recursivelyAddChildrenToMap(null, this._zoom, this._currentShownBounds);\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t//Removes all layers from the MarkerClusterGroup\r\n\tclearLayers: function () {\r\n\t\t//Need our own special implementation as the LayerGroup one doesn't work for us\r\n\r\n\t\t//If we aren't on the map (yet), blow away the markers we know of\r\n\t\tif (!this._map) {\r\n\t\t\tthis._needsClustering = [];\r\n\t\t\tthis._needsRemoving = [];\r\n\t\t\tdelete this._gridClusters;\r\n\t\t\tdelete this._gridUnclustered;\r\n\t\t}\r\n\r\n\t\tif (this._noanimationUnspiderfy) {\r\n\t\t\tthis._noanimationUnspiderfy();\r\n\t\t}\r\n\r\n\t\t//Remove all the visible layers\r\n\t\tthis._featureGroup.clearLayers();\r\n\t\tthis._nonPointGroup.clearLayers();\r\n\r\n\t\tthis.eachLayer(function (marker) {\r\n\t\t\tmarker.off(this._childMarkerEventHandlers, this);\r\n\t\t\tdelete marker.__parent;\r\n\t\t}, this);\r\n\r\n\t\tif (this._map) {\r\n\t\t\t//Reset _topClusterLevel and the DistanceGrids\r\n\t\t\tthis._generateInitialClusters();\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t//Override FeatureGroup.getBounds as it doesn't work\r\n\tgetBounds: function () {\r\n\t\tvar bounds = new L.LatLngBounds();\r\n\r\n\t\tif (this._topClusterLevel) {\r\n\t\t\tbounds.extend(this._topClusterLevel._bounds);\r\n\t\t}\r\n\r\n\t\tfor (var i = this._needsClustering.length - 1; i >= 0; i--) {\r\n\t\t\tbounds.extend(this._needsClustering[i].getLatLng());\r\n\t\t}\r\n\r\n\t\tbounds.extend(this._nonPointGroup.getBounds());\r\n\r\n\t\treturn bounds;\r\n\t},\r\n\r\n\t//Overrides LayerGroup.eachLayer\r\n\teachLayer: function (method, context) {\r\n\t\tvar markers = this._needsClustering.slice(),\r\n\t\t\tneedsRemoving = this._needsRemoving,\r\n\t\t\tthisNeedsRemoving, i, j;\r\n\r\n\t\tif (this._topClusterLevel) {\r\n\t\t\tthis._topClusterLevel.getAllChildMarkers(markers);\r\n\t\t}\r\n\r\n\t\tfor (i = markers.length - 1; i >= 0; i--) {\r\n\t\t\tthisNeedsRemoving = true;\r\n\r\n\t\t\tfor (j = needsRemoving.length - 1; j >= 0; j--) {\r\n\t\t\t\tif (needsRemoving[j].layer === markers[i]) {\r\n\t\t\t\t\tthisNeedsRemoving = false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (thisNeedsRemoving) {\r\n\t\t\t\tmethod.call(context, markers[i]);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis._nonPointGroup.eachLayer(method, context);\r\n\t},\r\n\r\n\t//Overrides LayerGroup.getLayers\r\n\tgetLayers: function () {\r\n\t\tvar layers = [];\r\n\t\tthis.eachLayer(function (l) {\r\n\t\t\tlayers.push(l);\r\n\t\t});\r\n\t\treturn layers;\r\n\t},\r\n\r\n\t//Overrides LayerGroup.getLayer, WARNING: Really bad performance\r\n\tgetLayer: function (id) {\r\n\t\tvar result = null;\r\n\r\n\t\tid = parseInt(id, 10);\r\n\r\n\t\tthis.eachLayer(function (l) {\r\n\t\t\tif (L.stamp(l) === id) {\r\n\t\t\t\tresult = l;\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\treturn result;\r\n\t},\r\n\r\n\t//Returns true if the given layer is in this MarkerClusterGroup\r\n\thasLayer: function (layer) {\r\n\t\tif (!layer) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tvar i, anArray = this._needsClustering;\r\n\r\n\t\tfor (i = anArray.length - 1; i >= 0; i--) {\r\n\t\t\tif (anArray[i] === layer) {\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tanArray = this._needsRemoving;\r\n\t\tfor (i = anArray.length - 1; i >= 0; i--) {\r\n\t\t\tif (anArray[i].layer === layer) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn !!(layer.__parent && layer.__parent._group === this) || this._nonPointGroup.hasLayer(layer);\r\n\t},\r\n\r\n\t//Zoom down to show the given layer (spiderfying if necessary) then calls the callback\r\n\tzoomToShowLayer: function (layer, callback) {\r\n\r\n\t\tif (typeof callback !== 'function') {\r\n\t\t\tcallback = function () {};\r\n\t\t}\r\n\r\n\t\tvar showMarker = function () {\r\n\t\t\tif ((layer._icon || layer.__parent._icon) && !this._inZoomAnimation) {\r\n\t\t\t\tthis._map.off('moveend', showMarker, this);\r\n\t\t\t\tthis.off('animationend', showMarker, this);\r\n\r\n\t\t\t\tif (layer._icon) {\r\n\t\t\t\t\tcallback();\r\n\t\t\t\t} else if (layer.__parent._icon) {\r\n\t\t\t\t\tthis.once('spiderfied', callback, this);\r\n\t\t\t\t\tlayer.__parent.spiderfy();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tif (layer._icon && this._map.getBounds().contains(layer.getLatLng())) {\r\n\t\t\t//Layer is visible ond on screen, immediate return\r\n\t\t\tcallback();\r\n\t\t} else if (layer.__parent._zoom < Math.round(this._map._zoom)) {\r\n\t\t\t//Layer should be visible at this zoom level. It must not be on screen so just pan over to it\r\n\t\t\tthis._map.on('moveend', showMarker, this);\r\n\t\t\tthis._map.panTo(layer.getLatLng());\r\n\t\t} else {\r\n\t\t\tthis._map.on('moveend', showMarker, this);\r\n\t\t\tthis.on('animationend', showMarker, this);\r\n\t\t\tlayer.__parent.zoomToBounds();\r\n\t\t}\r\n\t},\r\n\r\n\t//Overrides FeatureGroup.onAdd\r\n\tonAdd: function (map) {\r\n\t\tthis._map = map;\r\n\t\tvar i, l, layer;\r\n\r\n\t\tif (!isFinite(this._map.getMaxZoom())) {\r\n\t\t\tthrow \"Map has no maxZoom specified\";\r\n\t\t}\r\n\r\n\t\tthis._featureGroup.addTo(map);\r\n\t\tthis._nonPointGroup.addTo(map);\r\n\r\n\t\tif (!this._gridClusters) {\r\n\t\t\tthis._generateInitialClusters();\r\n\t\t}\r\n\r\n\t\tthis._maxLat = map.options.crs.projection.MAX_LATITUDE;\r\n\r\n\t\t//Restore all the positions as they are in the MCG before removing them\r\n\t\tfor (i = 0, l = this._needsRemoving.length; i < l; i++) {\r\n\t\t\tlayer = this._needsRemoving[i];\r\n\t\t\tlayer.newlatlng = layer.layer._latlng;\r\n\t\t\tlayer.layer._latlng = layer.latlng;\r\n\t\t}\r\n\t\t//Remove them, then restore their new positions\r\n\t\tfor (i = 0, l = this._needsRemoving.length; i < l; i++) {\r\n\t\t\tlayer = this._needsRemoving[i];\r\n\t\t\tthis._removeLayer(layer.layer, true);\r\n\t\t\tlayer.layer._latlng = layer.newlatlng;\r\n\t\t}\r\n\t\tthis._needsRemoving = [];\r\n\r\n\t\t//Remember the current zoom level and bounds\r\n\t\tthis._zoom = Math.round(this._map._zoom);\r\n\t\tthis._currentShownBounds = this._getExpandedVisibleBounds();\r\n\r\n\t\tthis._map.on('zoomend', this._zoomEnd, this);\r\n\t\tthis._map.on('moveend', this._moveEnd, this);\r\n\r\n\t\tif (this._spiderfierOnAdd) { //TODO FIXME: Not sure how to have spiderfier add something on here nicely\r\n\t\t\tthis._spiderfierOnAdd();\r\n\t\t}\r\n\r\n\t\tthis._bindEvents();\r\n\r\n\t\t//Actually add our markers to the map:\r\n\t\tl = this._needsClustering;\r\n\t\tthis._needsClustering = [];\r\n\t\tthis.addLayers(l, true);\r\n\t},\r\n\r\n\t//Overrides FeatureGroup.onRemove\r\n\tonRemove: function (map) {\r\n\t\tmap.off('zoomend', this._zoomEnd, this);\r\n\t\tmap.off('moveend', this._moveEnd, this);\r\n\r\n\t\tthis._unbindEvents();\r\n\r\n\t\t//In case we are in a cluster animation\r\n\t\tthis._map._mapPane.className = this._map._mapPane.className.replace(' leaflet-cluster-anim', '');\r\n\r\n\t\tif (this._spiderfierOnRemove) { //TODO FIXME: Not sure how to have spiderfier add something on here nicely\r\n\t\t\tthis._spiderfierOnRemove();\r\n\t\t}\r\n\r\n\t\tdelete this._maxLat;\r\n\r\n\t\t//Clean up all the layers we added to the map\r\n\t\tthis._hideCoverage();\r\n\t\tthis._featureGroup.remove();\r\n\t\tthis._nonPointGroup.remove();\r\n\r\n\t\tthis._featureGroup.clearLayers();\r\n\r\n\t\tthis._map = null;\r\n\t},\r\n\r\n\tgetVisibleParent: function (marker) {\r\n\t\tvar vMarker = marker;\r\n\t\twhile (vMarker && !vMarker._icon) {\r\n\t\t\tvMarker = vMarker.__parent;\r\n\t\t}\r\n\t\treturn vMarker || null;\r\n\t},\r\n\r\n\t//Remove the given object from the given array\r\n\t_arraySplice: function (anArray, obj) {\r\n\t\tfor (var i = anArray.length - 1; i >= 0; i--) {\r\n\t\t\tif (anArray[i] === obj) {\r\n\t\t\t\tanArray.splice(i, 1);\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\t/**\r\n\t * Removes a marker from all _gridUnclustered zoom levels, starting at the supplied zoom.\r\n\t * @param marker to be removed from _gridUnclustered.\r\n\t * @param z integer bottom start zoom level (included)\r\n\t * @private\r\n\t */\r\n\t_removeFromGridUnclustered: function (marker, z) {\r\n\t\tvar map = this._map,\r\n\t\t gridUnclustered = this._gridUnclustered,\r\n\t\t\tminZoom = Math.floor(this._map.getMinZoom());\r\n\r\n\t\tfor (; z >= minZoom; z--) {\r\n\t\t\tif (!gridUnclustered[z].removeObject(marker, map.project(marker.getLatLng(), z))) {\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\t_childMarkerDragStart: function (e) {\r\n\t\te.target.__dragStart = e.target._latlng;\r\n\t},\r\n\r\n\t_childMarkerMoved: function (e) {\r\n\t\tif (!this._ignoreMove && !e.target.__dragStart) {\r\n\t\t\tvar isPopupOpen = e.target._popup && e.target._popup.isOpen();\r\n\r\n\t\t\tthis._moveChild(e.target, e.oldLatLng, e.latlng);\r\n\r\n\t\t\tif (isPopupOpen) {\r\n\t\t\t\te.target.openPopup();\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\t_moveChild: function (layer, from, to) {\r\n\t\tlayer._latlng = from;\r\n\t\tthis.removeLayer(layer);\r\n\r\n\t\tlayer._latlng = to;\r\n\t\tthis.addLayer(layer);\r\n\t},\r\n\r\n\t_childMarkerDragEnd: function (e) {\r\n\t\tvar dragStart = e.target.__dragStart;\r\n\t\tdelete e.target.__dragStart;\r\n\t\tif (dragStart) {\r\n\t\t\tthis._moveChild(e.target, dragStart, e.target._latlng);\r\n\t\t}\t\t\r\n\t},\r\n\r\n\r\n\t//Internal function for removing a marker from everything.\r\n\t//dontUpdateMap: set to true if you will handle updating the map manually (for bulk functions)\r\n\t_removeLayer: function (marker, removeFromDistanceGrid, dontUpdateMap) {\r\n\t\tvar gridClusters = this._gridClusters,\r\n\t\t\tgridUnclustered = this._gridUnclustered,\r\n\t\t\tfg = this._featureGroup,\r\n\t\t\tmap = this._map,\r\n\t\t\tminZoom = Math.floor(this._map.getMinZoom());\r\n\r\n\t\t//Remove the marker from distance clusters it might be in\r\n\t\tif (removeFromDistanceGrid) {\r\n\t\t\tthis._removeFromGridUnclustered(marker, this._maxZoom);\r\n\t\t}\r\n\r\n\t\t//Work our way up the clusters removing them as we go if required\r\n\t\tvar cluster = marker.__parent,\r\n\t\t\tmarkers = cluster._markers,\r\n\t\t\totherMarker;\r\n\r\n\t\t//Remove the marker from the immediate parents marker list\r\n\t\tthis._arraySplice(markers, marker);\r\n\r\n\t\twhile (cluster) {\r\n\t\t\tcluster._childCount--;\r\n\t\t\tcluster._boundsNeedUpdate = true;\r\n\r\n\t\t\tif (cluster._zoom < minZoom) {\r\n\t\t\t\t//Top level, do nothing\r\n\t\t\t\tbreak;\r\n\t\t\t} else if (removeFromDistanceGrid && cluster._childCount <= 1) { //Cluster no longer required\r\n\t\t\t\t//We need to push the other marker up to the parent\r\n\t\t\t\totherMarker = cluster._markers[0] === marker ? cluster._markers[1] : cluster._markers[0];\r\n\r\n\t\t\t\t//Update distance grid\r\n\t\t\t\tgridClusters[cluster._zoom].removeObject(cluster, map.project(cluster._cLatLng, cluster._zoom));\r\n\t\t\t\tgridUnclustered[cluster._zoom].addObject(otherMarker, map.project(otherMarker.getLatLng(), cluster._zoom));\r\n\r\n\t\t\t\t//Move otherMarker up to parent\r\n\t\t\t\tthis._arraySplice(cluster.__parent._childClusters, cluster);\r\n\t\t\t\tcluster.__parent._markers.push(otherMarker);\r\n\t\t\t\totherMarker.__parent = cluster.__parent;\r\n\r\n\t\t\t\tif (cluster._icon) {\r\n\t\t\t\t\t//Cluster is currently on the map, need to put the marker on the map instead\r\n\t\t\t\t\tfg.removeLayer(cluster);\r\n\t\t\t\t\tif (!dontUpdateMap) {\r\n\t\t\t\t\t\tfg.addLayer(otherMarker);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tcluster._iconNeedsUpdate = true;\r\n\t\t\t}\r\n\r\n\t\t\tcluster = cluster.__parent;\r\n\t\t}\r\n\r\n\t\tdelete marker.__parent;\r\n\t},\r\n\r\n\t_isOrIsParent: function (el, oel) {\r\n\t\twhile (oel) {\r\n\t\t\tif (el === oel) {\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\toel = oel.parentNode;\r\n\t\t}\r\n\t\treturn false;\r\n\t},\r\n\r\n\t//Override L.Evented.fire\r\n\tfire: function (type, data, propagate) {\r\n\t\tif (data && data.layer instanceof L.MarkerCluster) {\r\n\t\t\t//Prevent multiple clustermouseover/off events if the icon is made up of stacked divs (Doesn't work in ie <= 8, no relatedTarget)\r\n\t\t\tif (data.originalEvent && this._isOrIsParent(data.layer._icon, data.originalEvent.relatedTarget)) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\ttype = 'cluster' + type;\r\n\t\t}\r\n\r\n\t\tL.FeatureGroup.prototype.fire.call(this, type, data, propagate);\r\n\t},\r\n\r\n\t//Override L.Evented.listens\r\n\tlistens: function (type, propagate) {\r\n\t\treturn L.FeatureGroup.prototype.listens.call(this, type, propagate) || L.FeatureGroup.prototype.listens.call(this, 'cluster' + type, propagate);\r\n\t},\r\n\r\n\t//Default functionality\r\n\t_defaultIconCreateFunction: function (cluster) {\r\n\t\tvar childCount = cluster.getChildCount();\r\n\r\n\t\tvar c = ' marker-cluster-';\r\n\t\tif (childCount < 10) {\r\n\t\t\tc += 'small';\r\n\t\t} else if (childCount < 100) {\r\n\t\t\tc += 'medium';\r\n\t\t} else {\r\n\t\t\tc += 'large';\r\n\t\t}\r\n\r\n\t\treturn new L.DivIcon({ html: '
' + childCount + '
', className: 'marker-cluster' + c, iconSize: new L.Point(40, 40) });\r\n\t},\r\n\r\n\t_bindEvents: function () {\r\n\t\tvar map = this._map,\r\n\t\t spiderfyOnMaxZoom = this.options.spiderfyOnMaxZoom,\r\n\t\t showCoverageOnHover = this.options.showCoverageOnHover,\r\n\t\t zoomToBoundsOnClick = this.options.zoomToBoundsOnClick;\r\n\r\n\t\t//Zoom on cluster click or spiderfy if we are at the lowest level\r\n\t\tif (spiderfyOnMaxZoom || zoomToBoundsOnClick) {\r\n\t\t\tthis.on('clusterclick', this._zoomOrSpiderfy, this);\r\n\t\t}\r\n\r\n\t\t//Show convex hull (boundary) polygon on mouse over\r\n\t\tif (showCoverageOnHover) {\r\n\t\t\tthis.on('clustermouseover', this._showCoverage, this);\r\n\t\t\tthis.on('clustermouseout', this._hideCoverage, this);\r\n\t\t\tmap.on('zoomend', this._hideCoverage, this);\r\n\t\t}\r\n\t},\r\n\r\n\t_zoomOrSpiderfy: function (e) {\r\n\t\tvar cluster = e.layer,\r\n\t\t bottomCluster = cluster;\r\n\r\n\t\twhile (bottomCluster._childClusters.length === 1) {\r\n\t\t\tbottomCluster = bottomCluster._childClusters[0];\r\n\t\t}\r\n\r\n\t\tif (bottomCluster._zoom === this._maxZoom &&\r\n\t\t\tbottomCluster._childCount === cluster._childCount &&\r\n\t\t\tthis.options.spiderfyOnMaxZoom) {\r\n\r\n\t\t\t// All child markers are contained in a single cluster from this._maxZoom to this cluster.\r\n\t\t\tcluster.spiderfy();\r\n\t\t} else if (this.options.zoomToBoundsOnClick) {\r\n\t\t\tcluster.zoomToBounds();\r\n\t\t}\r\n\r\n\t\t// Focus the map again for keyboard users.\r\n\t\tif (e.originalEvent && e.originalEvent.keyCode === 13) {\r\n\t\t\tthis._map._container.focus();\r\n\t\t}\r\n\t},\r\n\r\n\t_showCoverage: function (e) {\r\n\t\tvar map = this._map;\r\n\t\tif (this._inZoomAnimation) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (this._shownPolygon) {\r\n\t\t\tmap.removeLayer(this._shownPolygon);\r\n\t\t}\r\n\t\tif (e.layer.getChildCount() > 2 && e.layer !== this._spiderfied) {\r\n\t\t\tthis._shownPolygon = new L.Polygon(e.layer.getConvexHull(), this.options.polygonOptions);\r\n\t\t\tmap.addLayer(this._shownPolygon);\r\n\t\t}\r\n\t},\r\n\r\n\t_hideCoverage: function () {\r\n\t\tif (this._shownPolygon) {\r\n\t\t\tthis._map.removeLayer(this._shownPolygon);\r\n\t\t\tthis._shownPolygon = null;\r\n\t\t}\r\n\t},\r\n\r\n\t_unbindEvents: function () {\r\n\t\tvar spiderfyOnMaxZoom = this.options.spiderfyOnMaxZoom,\r\n\t\t\tshowCoverageOnHover = this.options.showCoverageOnHover,\r\n\t\t\tzoomToBoundsOnClick = this.options.zoomToBoundsOnClick,\r\n\t\t\tmap = this._map;\r\n\r\n\t\tif (spiderfyOnMaxZoom || zoomToBoundsOnClick) {\r\n\t\t\tthis.off('clusterclick', this._zoomOrSpiderfy, this);\r\n\t\t}\r\n\t\tif (showCoverageOnHover) {\r\n\t\t\tthis.off('clustermouseover', this._showCoverage, this);\r\n\t\t\tthis.off('clustermouseout', this._hideCoverage, this);\r\n\t\t\tmap.off('zoomend', this._hideCoverage, this);\r\n\t\t}\r\n\t},\r\n\r\n\t_zoomEnd: function () {\r\n\t\tif (!this._map) { //May have been removed from the map by a zoomEnd handler\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis._mergeSplitClusters();\r\n\r\n\t\tthis._zoom = Math.round(this._map._zoom);\r\n\t\tthis._currentShownBounds = this._getExpandedVisibleBounds();\r\n\t},\r\n\r\n\t_moveEnd: function () {\r\n\t\tif (this._inZoomAnimation) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tvar newBounds = this._getExpandedVisibleBounds();\r\n\r\n\t\tthis._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, Math.floor(this._map.getMinZoom()), this._zoom, newBounds);\r\n\t\tthis._topClusterLevel._recursivelyAddChildrenToMap(null, Math.round(this._map._zoom), newBounds);\r\n\r\n\t\tthis._currentShownBounds = newBounds;\r\n\t\treturn;\r\n\t},\r\n\r\n\t_generateInitialClusters: function () {\r\n\t\tvar maxZoom = Math.ceil(this._map.getMaxZoom()),\r\n\t\t\tminZoom = Math.floor(this._map.getMinZoom()),\r\n\t\t\tradius = this.options.maxClusterRadius,\r\n\t\t\tradiusFn = radius;\r\n\r\n\t\t//If we just set maxClusterRadius to a single number, we need to create\r\n\t\t//a simple function to return that number. Otherwise, we just have to\r\n\t\t//use the function we've passed in.\r\n\t\tif (typeof radius !== \"function\") {\r\n\t\t\tradiusFn = function () { return radius; };\r\n\t\t}\r\n\r\n\t\tif (this.options.disableClusteringAtZoom !== null) {\r\n\t\t\tmaxZoom = this.options.disableClusteringAtZoom - 1;\r\n\t\t}\r\n\t\tthis._maxZoom = maxZoom;\r\n\t\tthis._gridClusters = {};\r\n\t\tthis._gridUnclustered = {};\r\n\r\n\t\t//Set up DistanceGrids for each zoom\r\n\t\tfor (var zoom = maxZoom; zoom >= minZoom; zoom--) {\r\n\t\t\tthis._gridClusters[zoom] = new L.DistanceGrid(radiusFn(zoom));\r\n\t\t\tthis._gridUnclustered[zoom] = new L.DistanceGrid(radiusFn(zoom));\r\n\t\t}\r\n\r\n\t\t// Instantiate the appropriate L.MarkerCluster class (animated or not).\r\n\t\tthis._topClusterLevel = new this._markerCluster(this, minZoom - 1);\r\n\t},\r\n\r\n\t//Zoom: Zoom to start adding at (Pass this._maxZoom to start at the bottom)\r\n\t_addLayer: function (layer, zoom) {\r\n\t\tvar gridClusters = this._gridClusters,\r\n\t\t gridUnclustered = this._gridUnclustered,\r\n\t\t\tminZoom = Math.floor(this._map.getMinZoom()),\r\n\t\t markerPoint, z;\r\n\r\n\t\tif (this.options.singleMarkerMode) {\r\n\t\t\tthis._overrideMarkerIcon(layer);\r\n\t\t}\r\n\r\n\t\tlayer.on(this._childMarkerEventHandlers, this);\r\n\r\n\t\t//Find the lowest zoom level to slot this one in\r\n\t\tfor (; zoom >= minZoom; zoom--) {\r\n\t\t\tmarkerPoint = this._map.project(layer.getLatLng(), zoom); // calculate pixel position\r\n\r\n\t\t\t//Try find a cluster close by\r\n\t\t\tvar closest = gridClusters[zoom].getNearObject(markerPoint);\r\n\t\t\tif (closest) {\r\n\t\t\t\tclosest._addChild(layer);\r\n\t\t\t\tlayer.__parent = closest;\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\t//Try find a marker close by to form a new cluster with\r\n\t\t\tclosest = gridUnclustered[zoom].getNearObject(markerPoint);\r\n\t\t\tif (closest) {\r\n\t\t\t\tvar parent = closest.__parent;\r\n\t\t\t\tif (parent) {\r\n\t\t\t\t\tthis._removeLayer(closest, false);\r\n\t\t\t\t}\r\n\r\n\t\t\t\t//Create new cluster with these 2 in it\r\n\r\n\t\t\t\tvar newCluster = new this._markerCluster(this, zoom, closest, layer);\r\n\t\t\t\tgridClusters[zoom].addObject(newCluster, this._map.project(newCluster._cLatLng, zoom));\r\n\t\t\t\tclosest.__parent = newCluster;\r\n\t\t\t\tlayer.__parent = newCluster;\r\n\r\n\t\t\t\t//First create any new intermediate parent clusters that don't exist\r\n\t\t\t\tvar lastParent = newCluster;\r\n\t\t\t\tfor (z = zoom - 1; z > parent._zoom; z--) {\r\n\t\t\t\t\tlastParent = new this._markerCluster(this, z, lastParent);\r\n\t\t\t\t\tgridClusters[z].addObject(lastParent, this._map.project(closest.getLatLng(), z));\r\n\t\t\t\t}\r\n\t\t\t\tparent._addChild(lastParent);\r\n\r\n\t\t\t\t//Remove closest from this zoom level and any above that it is in, replace with newCluster\r\n\t\t\t\tthis._removeFromGridUnclustered(closest, zoom);\r\n\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\t//Didn't manage to cluster in at this zoom, record us as a marker here and continue upwards\r\n\t\t\tgridUnclustered[zoom].addObject(layer, markerPoint);\r\n\t\t}\r\n\r\n\t\t//Didn't get in anything, add us to the top\r\n\t\tthis._topClusterLevel._addChild(layer);\r\n\t\tlayer.__parent = this._topClusterLevel;\r\n\t\treturn;\r\n\t},\r\n\r\n\t/**\r\n\t * Refreshes the icon of all \"dirty\" visible clusters.\r\n\t * Non-visible \"dirty\" clusters will be updated when they are added to the map.\r\n\t * @private\r\n\t */\r\n\t_refreshClustersIcons: function () {\r\n\t\tthis._featureGroup.eachLayer(function (c) {\r\n\t\t\tif (c instanceof L.MarkerCluster && c._iconNeedsUpdate) {\r\n\t\t\t\tc._updateIcon();\r\n\t\t\t}\r\n\t\t});\r\n\t},\r\n\r\n\t//Enqueue code to fire after the marker expand/contract has happened\r\n\t_enqueue: function (fn) {\r\n\t\tthis._queue.push(fn);\r\n\t\tif (!this._queueTimeout) {\r\n\t\t\tthis._queueTimeout = setTimeout(L.bind(this._processQueue, this), 300);\r\n\t\t}\r\n\t},\r\n\t_processQueue: function () {\r\n\t\tfor (var i = 0; i < this._queue.length; i++) {\r\n\t\t\tthis._queue[i].call(this);\r\n\t\t}\r\n\t\tthis._queue.length = 0;\r\n\t\tclearTimeout(this._queueTimeout);\r\n\t\tthis._queueTimeout = null;\r\n\t},\r\n\r\n\t//Merge and split any existing clusters that are too big or small\r\n\t_mergeSplitClusters: function () {\r\n\t\tvar mapZoom = Math.round(this._map._zoom);\r\n\r\n\t\t//In case we are starting to split before the animation finished\r\n\t\tthis._processQueue();\r\n\r\n\t\tif (this._zoom < mapZoom && this._currentShownBounds.intersects(this._getExpandedVisibleBounds())) { //Zoom in, split\r\n\t\t\tthis._animationStart();\r\n\t\t\t//Remove clusters now off screen\r\n\t\t\tthis._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, Math.floor(this._map.getMinZoom()), this._zoom, this._getExpandedVisibleBounds());\r\n\r\n\t\t\tthis._animationZoomIn(this._zoom, mapZoom);\r\n\r\n\t\t} else if (this._zoom > mapZoom) { //Zoom out, merge\r\n\t\t\tthis._animationStart();\r\n\r\n\t\t\tthis._animationZoomOut(this._zoom, mapZoom);\r\n\t\t} else {\r\n\t\t\tthis._moveEnd();\r\n\t\t}\r\n\t},\r\n\r\n\t//Gets the maps visible bounds expanded in each direction by the size of the screen (so the user cannot see an area we do not cover in one pan)\r\n\t_getExpandedVisibleBounds: function () {\r\n\t\tif (!this.options.removeOutsideVisibleBounds) {\r\n\t\t\treturn this._mapBoundsInfinite;\r\n\t\t} else if (L.Browser.mobile) {\r\n\t\t\treturn this._checkBoundsMaxLat(this._map.getBounds());\r\n\t\t}\r\n\r\n\t\treturn this._checkBoundsMaxLat(this._map.getBounds().pad(1)); // Padding expands the bounds by its own dimensions but scaled with the given factor.\r\n\t},\r\n\r\n\t/**\r\n\t * Expands the latitude to Infinity (or -Infinity) if the input bounds reach the map projection maximum defined latitude\r\n\t * (in the case of Web/Spherical Mercator, it is 85.0511287798 / see https://en.wikipedia.org/wiki/Web_Mercator#Formulas).\r\n\t * Otherwise, the removeOutsideVisibleBounds option will remove markers beyond that limit, whereas the same markers without\r\n\t * this option (or outside MCG) will have their position floored (ceiled) by the projection and rendered at that limit,\r\n\t * making the user think that MCG \"eats\" them and never displays them again.\r\n\t * @param bounds L.LatLngBounds\r\n\t * @returns {L.LatLngBounds}\r\n\t * @private\r\n\t */\r\n\t_checkBoundsMaxLat: function (bounds) {\r\n\t\tvar maxLat = this._maxLat;\r\n\r\n\t\tif (maxLat !== undefined) {\r\n\t\t\tif (bounds.getNorth() >= maxLat) {\r\n\t\t\t\tbounds._northEast.lat = Infinity;\r\n\t\t\t}\r\n\t\t\tif (bounds.getSouth() <= -maxLat) {\r\n\t\t\t\tbounds._southWest.lat = -Infinity;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn bounds;\r\n\t},\r\n\r\n\t//Shared animation code\r\n\t_animationAddLayerNonAnimated: function (layer, newCluster) {\r\n\t\tif (newCluster === layer) {\r\n\t\t\tthis._featureGroup.addLayer(layer);\r\n\t\t} else if (newCluster._childCount === 2) {\r\n\t\t\tnewCluster._addToMap();\r\n\r\n\t\t\tvar markers = newCluster.getAllChildMarkers();\r\n\t\t\tthis._featureGroup.removeLayer(markers[0]);\r\n\t\t\tthis._featureGroup.removeLayer(markers[1]);\r\n\t\t} else {\r\n\t\t\tnewCluster._updateIcon();\r\n\t\t}\r\n\t},\r\n\r\n\t/**\r\n\t * Extracts individual (i.e. non-group) layers from a Layer Group.\r\n\t * @param group to extract layers from.\r\n\t * @param output {Array} in which to store the extracted layers.\r\n\t * @returns {*|Array}\r\n\t * @private\r\n\t */\r\n\t_extractNonGroupLayers: function (group, output) {\r\n\t\tvar layers = group.getLayers(),\r\n\t\t i = 0,\r\n\t\t layer;\r\n\r\n\t\toutput = output || [];\r\n\r\n\t\tfor (; i < layers.length; i++) {\r\n\t\t\tlayer = layers[i];\r\n\r\n\t\t\tif (layer instanceof L.LayerGroup) {\r\n\t\t\t\tthis._extractNonGroupLayers(layer, output);\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\toutput.push(layer);\r\n\t\t}\r\n\r\n\t\treturn output;\r\n\t},\r\n\r\n\t/**\r\n\t * Implements the singleMarkerMode option.\r\n\t * @param layer Marker to re-style using the Clusters iconCreateFunction.\r\n\t * @returns {L.Icon} The newly created icon.\r\n\t * @private\r\n\t */\r\n\t_overrideMarkerIcon: function (layer) {\r\n\t\tvar icon = layer.options.icon = this.options.iconCreateFunction({\r\n\t\t\tgetChildCount: function () {\r\n\t\t\t\treturn 1;\r\n\t\t\t},\r\n\t\t\tgetAllChildMarkers: function () {\r\n\t\t\t\treturn [layer];\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\treturn icon;\r\n\t}\r\n});\r\n\r\n// Constant bounds used in case option \"removeOutsideVisibleBounds\" is set to false.\r\nL.MarkerClusterGroup.include({\r\n\t_mapBoundsInfinite: new L.LatLngBounds(new L.LatLng(-Infinity, -Infinity), new L.LatLng(Infinity, Infinity))\r\n});\r\n\r\nL.MarkerClusterGroup.include({\r\n\t_noAnimation: {\r\n\t\t//Non Animated versions of everything\r\n\t\t_animationStart: function () {\r\n\t\t\t//Do nothing...\r\n\t\t},\r\n\t\t_animationZoomIn: function (previousZoomLevel, newZoomLevel) {\r\n\t\t\tthis._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, Math.floor(this._map.getMinZoom()), previousZoomLevel);\r\n\t\t\tthis._topClusterLevel._recursivelyAddChildrenToMap(null, newZoomLevel, this._getExpandedVisibleBounds());\r\n\r\n\t\t\t//We didn't actually animate, but we use this event to mean \"clustering animations have finished\"\r\n\t\t\tthis.fire('animationend');\r\n\t\t},\r\n\t\t_animationZoomOut: function (previousZoomLevel, newZoomLevel) {\r\n\t\t\tthis._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, Math.floor(this._map.getMinZoom()), previousZoomLevel);\r\n\t\t\tthis._topClusterLevel._recursivelyAddChildrenToMap(null, newZoomLevel, this._getExpandedVisibleBounds());\r\n\r\n\t\t\t//We didn't actually animate, but we use this event to mean \"clustering animations have finished\"\r\n\t\t\tthis.fire('animationend');\r\n\t\t},\r\n\t\t_animationAddLayer: function (layer, newCluster) {\r\n\t\t\tthis._animationAddLayerNonAnimated(layer, newCluster);\r\n\t\t}\r\n\t},\r\n\r\n\t_withAnimation: {\r\n\t\t//Animated versions here\r\n\t\t_animationStart: function () {\r\n\t\t\tthis._map._mapPane.className += ' leaflet-cluster-anim';\r\n\t\t\tthis._inZoomAnimation++;\r\n\t\t},\r\n\r\n\t\t_animationZoomIn: function (previousZoomLevel, newZoomLevel) {\r\n\t\t\tvar bounds = this._getExpandedVisibleBounds(),\r\n\t\t\t fg = this._featureGroup,\r\n\t\t\t\tminZoom = Math.floor(this._map.getMinZoom()),\r\n\t\t\t i;\r\n\r\n\t\t\tthis._ignoreMove = true;\r\n\r\n\t\t\t//Add all children of current clusters to map and remove those clusters from map\r\n\t\t\tthis._topClusterLevel._recursively(bounds, previousZoomLevel, minZoom, function (c) {\r\n\t\t\t\tvar startPos = c._latlng,\r\n\t\t\t\t markers = c._markers,\r\n\t\t\t\t m;\r\n\r\n\t\t\t\tif (!bounds.contains(startPos)) {\r\n\t\t\t\t\tstartPos = null;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (c._isSingleParent() && previousZoomLevel + 1 === newZoomLevel) { //Immediately add the new child and remove us\r\n\t\t\t\t\tfg.removeLayer(c);\r\n\t\t\t\t\tc._recursivelyAddChildrenToMap(null, newZoomLevel, bounds);\r\n\t\t\t\t} else {\r\n\t\t\t\t\t//Fade out old cluster\r\n\t\t\t\t\tc.clusterHide();\r\n\t\t\t\t\tc._recursivelyAddChildrenToMap(startPos, newZoomLevel, bounds);\r\n\t\t\t\t}\r\n\r\n\t\t\t\t//Remove all markers that aren't visible any more\r\n\t\t\t\t//TODO: Do we actually need to do this on the higher levels too?\r\n\t\t\t\tfor (i = markers.length - 1; i >= 0; i--) {\r\n\t\t\t\t\tm = markers[i];\r\n\t\t\t\t\tif (!bounds.contains(m._latlng)) {\r\n\t\t\t\t\t\tfg.removeLayer(m);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t});\r\n\r\n\t\t\tthis._forceLayout();\r\n\r\n\t\t\t//Update opacities\r\n\t\t\tthis._topClusterLevel._recursivelyBecomeVisible(bounds, newZoomLevel);\r\n\t\t\t//TODO Maybe? Update markers in _recursivelyBecomeVisible\r\n\t\t\tfg.eachLayer(function (n) {\r\n\t\t\t\tif (!(n instanceof L.MarkerCluster) && n._icon) {\r\n\t\t\t\t\tn.clusterShow();\r\n\t\t\t\t}\r\n\t\t\t});\r\n\r\n\t\t\t//update the positions of the just added clusters/markers\r\n\t\t\tthis._topClusterLevel._recursively(bounds, previousZoomLevel, newZoomLevel, function (c) {\r\n\t\t\t\tc._recursivelyRestoreChildPositions(newZoomLevel);\r\n\t\t\t});\r\n\r\n\t\t\tthis._ignoreMove = false;\r\n\r\n\t\t\t//Remove the old clusters and close the zoom animation\r\n\t\t\tthis._enqueue(function () {\r\n\t\t\t\t//update the positions of the just added clusters/markers\r\n\t\t\t\tthis._topClusterLevel._recursively(bounds, previousZoomLevel, minZoom, function (c) {\r\n\t\t\t\t\tfg.removeLayer(c);\r\n\t\t\t\t\tc.clusterShow();\r\n\t\t\t\t});\r\n\r\n\t\t\t\tthis._animationEnd();\r\n\t\t\t});\r\n\t\t},\r\n\r\n\t\t_animationZoomOut: function (previousZoomLevel, newZoomLevel) {\r\n\t\t\tthis._animationZoomOutSingle(this._topClusterLevel, previousZoomLevel - 1, newZoomLevel);\r\n\r\n\t\t\t//Need to add markers for those that weren't on the map before but are now\r\n\t\t\tthis._topClusterLevel._recursivelyAddChildrenToMap(null, newZoomLevel, this._getExpandedVisibleBounds());\r\n\t\t\t//Remove markers that were on the map before but won't be now\r\n\t\t\tthis._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, Math.floor(this._map.getMinZoom()), previousZoomLevel, this._getExpandedVisibleBounds());\r\n\t\t},\r\n\r\n\t\t_animationAddLayer: function (layer, newCluster) {\r\n\t\t\tvar me = this,\r\n\t\t\t fg = this._featureGroup;\r\n\r\n\t\t\tfg.addLayer(layer);\r\n\t\t\tif (newCluster !== layer) {\r\n\t\t\t\tif (newCluster._childCount > 2) { //Was already a cluster\r\n\r\n\t\t\t\t\tnewCluster._updateIcon();\r\n\t\t\t\t\tthis._forceLayout();\r\n\t\t\t\t\tthis._animationStart();\r\n\r\n\t\t\t\t\tlayer._setPos(this._map.latLngToLayerPoint(newCluster.getLatLng()));\r\n\t\t\t\t\tlayer.clusterHide();\r\n\r\n\t\t\t\t\tthis._enqueue(function () {\r\n\t\t\t\t\t\tfg.removeLayer(layer);\r\n\t\t\t\t\t\tlayer.clusterShow();\r\n\r\n\t\t\t\t\t\tme._animationEnd();\r\n\t\t\t\t\t});\r\n\r\n\t\t\t\t} else { //Just became a cluster\r\n\t\t\t\t\tthis._forceLayout();\r\n\r\n\t\t\t\t\tme._animationStart();\r\n\t\t\t\t\tme._animationZoomOutSingle(newCluster, this._map.getMaxZoom(), this._zoom);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\t// Private methods for animated versions.\r\n\t_animationZoomOutSingle: function (cluster, previousZoomLevel, newZoomLevel) {\r\n\t\tvar bounds = this._getExpandedVisibleBounds(),\r\n\t\t\tminZoom = Math.floor(this._map.getMinZoom());\r\n\r\n\t\t//Animate all of the markers in the clusters to move to their cluster center point\r\n\t\tcluster._recursivelyAnimateChildrenInAndAddSelfToMap(bounds, minZoom, previousZoomLevel + 1, newZoomLevel);\r\n\r\n\t\tvar me = this;\r\n\r\n\t\t//Update the opacity (If we immediately set it they won't animate)\r\n\t\tthis._forceLayout();\r\n\t\tcluster._recursivelyBecomeVisible(bounds, newZoomLevel);\r\n\r\n\t\t//TODO: Maybe use the transition timing stuff to make this more reliable\r\n\t\t//When the animations are done, tidy up\r\n\t\tthis._enqueue(function () {\r\n\r\n\t\t\t//This cluster stopped being a cluster before the timeout fired\r\n\t\t\tif (cluster._childCount === 1) {\r\n\t\t\t\tvar m = cluster._markers[0];\r\n\t\t\t\t//If we were in a cluster animation at the time then the opacity and position of our child could be wrong now, so fix it\r\n\t\t\t\tthis._ignoreMove = true;\r\n\t\t\t\tm.setLatLng(m.getLatLng());\r\n\t\t\t\tthis._ignoreMove = false;\r\n\t\t\t\tif (m.clusterShow) {\r\n\t\t\t\t\tm.clusterShow();\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tcluster._recursively(bounds, newZoomLevel, minZoom, function (c) {\r\n\t\t\t\t\tc._recursivelyRemoveChildrenFromMap(bounds, minZoom, previousZoomLevel + 1);\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t\tme._animationEnd();\r\n\t\t});\r\n\t},\r\n\r\n\t_animationEnd: function () {\r\n\t\tif (this._map) {\r\n\t\t\tthis._map._mapPane.className = this._map._mapPane.className.replace(' leaflet-cluster-anim', '');\r\n\t\t}\r\n\t\tthis._inZoomAnimation--;\r\n\t\tthis.fire('animationend');\r\n\t},\r\n\r\n\t//Force a browser layout of stuff in the map\r\n\t// Should apply the current opacity and location to all elements so we can update them again for an animation\r\n\t_forceLayout: function () {\r\n\t\t//In my testing this works, infact offsetWidth of any element seems to work.\r\n\t\t//Could loop all this._layers and do this for each _icon if it stops working\r\n\r\n\t\tL.Util.falseFn(document.body.offsetWidth);\r\n\t}\r\n});\r\n\r\nL.markerClusterGroup = function (options) {\r\n\treturn new L.MarkerClusterGroup(options);\r\n};\r\n","export var MarkerCluster = L.MarkerCluster = L.Marker.extend({\r\n\toptions: L.Icon.prototype.options,\r\n\r\n\tinitialize: function (group, zoom, a, b) {\r\n\r\n\t\tL.Marker.prototype.initialize.call(this, a ? (a._cLatLng || a.getLatLng()) : new L.LatLng(0, 0),\r\n { icon: this, pane: group.options.clusterPane });\r\n\r\n\t\tthis._group = group;\r\n\t\tthis._zoom = zoom;\r\n\r\n\t\tthis._markers = [];\r\n\t\tthis._childClusters = [];\r\n\t\tthis._childCount = 0;\r\n\t\tthis._iconNeedsUpdate = true;\r\n\t\tthis._boundsNeedUpdate = true;\r\n\r\n\t\tthis._bounds = new L.LatLngBounds();\r\n\r\n\t\tif (a) {\r\n\t\t\tthis._addChild(a);\r\n\t\t}\r\n\t\tif (b) {\r\n\t\t\tthis._addChild(b);\r\n\t\t}\r\n\t},\r\n\r\n\t//Recursively retrieve all child markers of this cluster\r\n\tgetAllChildMarkers: function (storageArray, ignoreDraggedMarker) {\r\n\t\tstorageArray = storageArray || [];\r\n\r\n\t\tfor (var i = this._childClusters.length - 1; i >= 0; i--) {\r\n\t\t\tthis._childClusters[i].getAllChildMarkers(storageArray);\r\n\t\t}\r\n\r\n\t\tfor (var j = this._markers.length - 1; j >= 0; j--) {\r\n\t\t\tif (ignoreDraggedMarker && this._markers[j].__dragStart) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tstorageArray.push(this._markers[j]);\r\n\t\t}\r\n\r\n\t\treturn storageArray;\r\n\t},\r\n\r\n\t//Returns the count of how many child markers we have\r\n\tgetChildCount: function () {\r\n\t\treturn this._childCount;\r\n\t},\r\n\r\n\t//Zoom to the minimum of showing all of the child markers, or the extents of this cluster\r\n\tzoomToBounds: function (fitBoundsOptions) {\r\n\t\tvar childClusters = this._childClusters.slice(),\r\n\t\t\tmap = this._group._map,\r\n\t\t\tboundsZoom = map.getBoundsZoom(this._bounds),\r\n\t\t\tzoom = this._zoom + 1,\r\n\t\t\tmapZoom = map.getZoom(),\r\n\t\t\ti;\r\n\r\n\t\t//calculate how far we need to zoom down to see all of the markers\r\n\t\twhile (childClusters.length > 0 && boundsZoom > zoom) {\r\n\t\t\tzoom++;\r\n\t\t\tvar newClusters = [];\r\n\t\t\tfor (i = 0; i < childClusters.length; i++) {\r\n\t\t\t\tnewClusters = newClusters.concat(childClusters[i]._childClusters);\r\n\t\t\t}\r\n\t\t\tchildClusters = newClusters;\r\n\t\t}\r\n\r\n\t\tif (boundsZoom > zoom) {\r\n\t\t\tthis._group._map.setView(this._latlng, zoom);\r\n\t\t} else if (boundsZoom <= mapZoom) { //If fitBounds wouldn't zoom us down, zoom us down instead\r\n\t\t\tthis._group._map.setView(this._latlng, mapZoom + 1);\r\n\t\t} else {\r\n\t\t\tthis._group._map.fitBounds(this._bounds, fitBoundsOptions);\r\n\t\t}\r\n\t},\r\n\r\n\tgetBounds: function () {\r\n\t\tvar bounds = new L.LatLngBounds();\r\n\t\tbounds.extend(this._bounds);\r\n\t\treturn bounds;\r\n\t},\r\n\r\n\t_updateIcon: function () {\r\n\t\tthis._iconNeedsUpdate = true;\r\n\t\tif (this._icon) {\r\n\t\t\tthis.setIcon(this);\r\n\t\t}\r\n\t},\r\n\r\n\t//Cludge for Icon, we pretend to be an icon for performance\r\n\tcreateIcon: function () {\r\n\t\tif (this._iconNeedsUpdate) {\r\n\t\t\tthis._iconObj = this._group.options.iconCreateFunction(this);\r\n\t\t\tthis._iconNeedsUpdate = false;\r\n\t\t}\r\n\t\treturn this._iconObj.createIcon();\r\n\t},\r\n\tcreateShadow: function () {\r\n\t\treturn this._iconObj.createShadow();\r\n\t},\r\n\r\n\r\n\t_addChild: function (new1, isNotificationFromChild) {\r\n\r\n\t\tthis._iconNeedsUpdate = true;\r\n\r\n\t\tthis._boundsNeedUpdate = true;\r\n\t\tthis._setClusterCenter(new1);\r\n\r\n\t\tif (new1 instanceof L.MarkerCluster) {\r\n\t\t\tif (!isNotificationFromChild) {\r\n\t\t\t\tthis._childClusters.push(new1);\r\n\t\t\t\tnew1.__parent = this;\r\n\t\t\t}\r\n\t\t\tthis._childCount += new1._childCount;\r\n\t\t} else {\r\n\t\t\tif (!isNotificationFromChild) {\r\n\t\t\t\tthis._markers.push(new1);\r\n\t\t\t}\r\n\t\t\tthis._childCount++;\r\n\t\t}\r\n\r\n\t\tif (this.__parent) {\r\n\t\t\tthis.__parent._addChild(new1, true);\r\n\t\t}\r\n\t},\r\n\r\n\t/**\r\n\t * Makes sure the cluster center is set. If not, uses the child center if it is a cluster, or the marker position.\r\n\t * @param child L.MarkerCluster|L.Marker that will be used as cluster center if not defined yet.\r\n\t * @private\r\n\t */\r\n\t_setClusterCenter: function (child) {\r\n\t\tif (!this._cLatLng) {\r\n\t\t\t// when clustering, take position of the first point as the cluster center\r\n\t\t\tthis._cLatLng = child._cLatLng || child._latlng;\r\n\t\t}\r\n\t},\r\n\r\n\t/**\r\n\t * Assigns impossible bounding values so that the next extend entirely determines the new bounds.\r\n\t * This method avoids having to trash the previous L.LatLngBounds object and to create a new one, which is much slower for this class.\r\n\t * As long as the bounds are not extended, most other methods would probably fail, as they would with bounds initialized but not extended.\r\n\t * @private\r\n\t */\r\n\t_resetBounds: function () {\r\n\t\tvar bounds = this._bounds;\r\n\r\n\t\tif (bounds._southWest) {\r\n\t\t\tbounds._southWest.lat = Infinity;\r\n\t\t\tbounds._southWest.lng = Infinity;\r\n\t\t}\r\n\t\tif (bounds._northEast) {\r\n\t\t\tbounds._northEast.lat = -Infinity;\r\n\t\t\tbounds._northEast.lng = -Infinity;\r\n\t\t}\r\n\t},\r\n\r\n\t_recalculateBounds: function () {\r\n\t\tvar markers = this._markers,\r\n\t\t childClusters = this._childClusters,\r\n\t\t latSum = 0,\r\n\t\t lngSum = 0,\r\n\t\t totalCount = this._childCount,\r\n\t\t i, child, childLatLng, childCount;\r\n\r\n\t\t// Case where all markers are removed from the map and we are left with just an empty _topClusterLevel.\r\n\t\tif (totalCount === 0) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// Reset rather than creating a new object, for performance.\r\n\t\tthis._resetBounds();\r\n\r\n\t\t// Child markers.\r\n\t\tfor (i = 0; i < markers.length; i++) {\r\n\t\t\tchildLatLng = markers[i]._latlng;\r\n\r\n\t\t\tthis._bounds.extend(childLatLng);\r\n\r\n\t\t\tlatSum += childLatLng.lat;\r\n\t\t\tlngSum += childLatLng.lng;\r\n\t\t}\r\n\r\n\t\t// Child clusters.\r\n\t\tfor (i = 0; i < childClusters.length; i++) {\r\n\t\t\tchild = childClusters[i];\r\n\r\n\t\t\t// Re-compute child bounds and weighted position first if necessary.\r\n\t\t\tif (child._boundsNeedUpdate) {\r\n\t\t\t\tchild._recalculateBounds();\r\n\t\t\t}\r\n\r\n\t\t\tthis._bounds.extend(child._bounds);\r\n\r\n\t\t\tchildLatLng = child._wLatLng;\r\n\t\t\tchildCount = child._childCount;\r\n\r\n\t\t\tlatSum += childLatLng.lat * childCount;\r\n\t\t\tlngSum += childLatLng.lng * childCount;\r\n\t\t}\r\n\r\n\t\tthis._latlng = this._wLatLng = new L.LatLng(latSum / totalCount, lngSum / totalCount);\r\n\r\n\t\t// Reset dirty flag.\r\n\t\tthis._boundsNeedUpdate = false;\r\n\t},\r\n\r\n\t//Set our markers position as given and add it to the map\r\n\t_addToMap: function (startPos) {\r\n\t\tif (startPos) {\r\n\t\t\tthis._backupLatlng = this._latlng;\r\n\t\t\tthis.setLatLng(startPos);\r\n\t\t}\r\n\t\tthis._group._featureGroup.addLayer(this);\r\n\t},\r\n\r\n\t_recursivelyAnimateChildrenIn: function (bounds, center, maxZoom) {\r\n\t\tthis._recursively(bounds, this._group._map.getMinZoom(), maxZoom - 1,\r\n\t\t\tfunction (c) {\r\n\t\t\t\tvar markers = c._markers,\r\n\t\t\t\t\ti, m;\r\n\t\t\t\tfor (i = markers.length - 1; i >= 0; i--) {\r\n\t\t\t\t\tm = markers[i];\r\n\r\n\t\t\t\t\t//Only do it if the icon is still on the map\r\n\t\t\t\t\tif (m._icon) {\r\n\t\t\t\t\t\tm._setPos(center);\r\n\t\t\t\t\t\tm.clusterHide();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\tfunction (c) {\r\n\t\t\t\tvar childClusters = c._childClusters,\r\n\t\t\t\t\tj, cm;\r\n\t\t\t\tfor (j = childClusters.length - 1; j >= 0; j--) {\r\n\t\t\t\t\tcm = childClusters[j];\r\n\t\t\t\t\tif (cm._icon) {\r\n\t\t\t\t\t\tcm._setPos(center);\r\n\t\t\t\t\t\tcm.clusterHide();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t);\r\n\t},\r\n\r\n\t_recursivelyAnimateChildrenInAndAddSelfToMap: function (bounds, mapMinZoom, previousZoomLevel, newZoomLevel) {\r\n\t\tthis._recursively(bounds, newZoomLevel, mapMinZoom,\r\n\t\t\tfunction (c) {\r\n\t\t\t\tc._recursivelyAnimateChildrenIn(bounds, c._group._map.latLngToLayerPoint(c.getLatLng()).round(), previousZoomLevel);\r\n\r\n\t\t\t\t//TODO: depthToAnimateIn affects _isSingleParent, if there is a multizoom we may/may not be.\r\n\t\t\t\t//As a hack we only do a animation free zoom on a single level zoom, if someone does multiple levels then we always animate\r\n\t\t\t\tif (c._isSingleParent() && previousZoomLevel - 1 === newZoomLevel) {\r\n\t\t\t\t\tc.clusterShow();\r\n\t\t\t\t\tc._recursivelyRemoveChildrenFromMap(bounds, mapMinZoom, previousZoomLevel); //Immediately remove our children as we are replacing them. TODO previousBounds not bounds\r\n\t\t\t\t} else {\r\n\t\t\t\t\tc.clusterHide();\r\n\t\t\t\t}\r\n\r\n\t\t\t\tc._addToMap();\r\n\t\t\t}\r\n\t\t);\r\n\t},\r\n\r\n\t_recursivelyBecomeVisible: function (bounds, zoomLevel) {\r\n\t\tthis._recursively(bounds, this._group._map.getMinZoom(), zoomLevel, null, function (c) {\r\n\t\t\tc.clusterShow();\r\n\t\t});\r\n\t},\r\n\r\n\t_recursivelyAddChildrenToMap: function (startPos, zoomLevel, bounds) {\r\n\t\tthis._recursively(bounds, this._group._map.getMinZoom() - 1, zoomLevel,\r\n\t\t\tfunction (c) {\r\n\t\t\t\tif (zoomLevel === c._zoom) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t//Add our child markers at startPos (so they can be animated out)\r\n\t\t\t\tfor (var i = c._markers.length - 1; i >= 0; i--) {\r\n\t\t\t\t\tvar nm = c._markers[i];\r\n\r\n\t\t\t\t\tif (!bounds.contains(nm._latlng)) {\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif (startPos) {\r\n\t\t\t\t\t\tnm._backupLatlng = nm.getLatLng();\r\n\r\n\t\t\t\t\t\tnm.setLatLng(startPos);\r\n\t\t\t\t\t\tif (nm.clusterHide) {\r\n\t\t\t\t\t\t\tnm.clusterHide();\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tc._group._featureGroup.addLayer(nm);\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\tfunction (c) {\r\n\t\t\t\tc._addToMap(startPos);\r\n\t\t\t}\r\n\t\t);\r\n\t},\r\n\r\n\t_recursivelyRestoreChildPositions: function (zoomLevel) {\r\n\t\t//Fix positions of child markers\r\n\t\tfor (var i = this._markers.length - 1; i >= 0; i--) {\r\n\t\t\tvar nm = this._markers[i];\r\n\t\t\tif (nm._backupLatlng) {\r\n\t\t\t\tnm.setLatLng(nm._backupLatlng);\r\n\t\t\t\tdelete nm._backupLatlng;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (zoomLevel - 1 === this._zoom) {\r\n\t\t\t//Reposition child clusters\r\n\t\t\tfor (var j = this._childClusters.length - 1; j >= 0; j--) {\r\n\t\t\t\tthis._childClusters[j]._restorePosition();\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tfor (var k = this._childClusters.length - 1; k >= 0; k--) {\r\n\t\t\t\tthis._childClusters[k]._recursivelyRestoreChildPositions(zoomLevel);\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\t_restorePosition: function () {\r\n\t\tif (this._backupLatlng) {\r\n\t\t\tthis.setLatLng(this._backupLatlng);\r\n\t\t\tdelete this._backupLatlng;\r\n\t\t}\r\n\t},\r\n\r\n\t//exceptBounds: If set, don't remove any markers/clusters in it\r\n\t_recursivelyRemoveChildrenFromMap: function (previousBounds, mapMinZoom, zoomLevel, exceptBounds) {\r\n\t\tvar m, i;\r\n\t\tthis._recursively(previousBounds, mapMinZoom - 1, zoomLevel - 1,\r\n\t\t\tfunction (c) {\r\n\t\t\t\t//Remove markers at every level\r\n\t\t\t\tfor (i = c._markers.length - 1; i >= 0; i--) {\r\n\t\t\t\t\tm = c._markers[i];\r\n\t\t\t\t\tif (!exceptBounds || !exceptBounds.contains(m._latlng)) {\r\n\t\t\t\t\t\tc._group._featureGroup.removeLayer(m);\r\n\t\t\t\t\t\tif (m.clusterShow) {\r\n\t\t\t\t\t\t\tm.clusterShow();\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\tfunction (c) {\r\n\t\t\t\t//Remove child clusters at just the bottom level\r\n\t\t\t\tfor (i = c._childClusters.length - 1; i >= 0; i--) {\r\n\t\t\t\t\tm = c._childClusters[i];\r\n\t\t\t\t\tif (!exceptBounds || !exceptBounds.contains(m._latlng)) {\r\n\t\t\t\t\t\tc._group._featureGroup.removeLayer(m);\r\n\t\t\t\t\t\tif (m.clusterShow) {\r\n\t\t\t\t\t\t\tm.clusterShow();\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t);\r\n\t},\r\n\r\n\t//Run the given functions recursively to this and child clusters\r\n\t// boundsToApplyTo: a L.LatLngBounds representing the bounds of what clusters to recurse in to\r\n\t// zoomLevelToStart: zoom level to start running functions (inclusive)\r\n\t// zoomLevelToStop: zoom level to stop running functions (inclusive)\r\n\t// runAtEveryLevel: function that takes an L.MarkerCluster as an argument that should be applied on every level\r\n\t// runAtBottomLevel: function that takes an L.MarkerCluster as an argument that should be applied at only the bottom level\r\n\t_recursively: function (boundsToApplyTo, zoomLevelToStart, zoomLevelToStop, runAtEveryLevel, runAtBottomLevel) {\r\n\t\tvar childClusters = this._childClusters,\r\n\t\t zoom = this._zoom,\r\n\t\t i, c;\r\n\r\n\t\tif (zoomLevelToStart <= zoom) {\r\n\t\t\tif (runAtEveryLevel) {\r\n\t\t\t\trunAtEveryLevel(this);\r\n\t\t\t}\r\n\t\t\tif (runAtBottomLevel && zoom === zoomLevelToStop) {\r\n\t\t\t\trunAtBottomLevel(this);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (zoom < zoomLevelToStart || zoom < zoomLevelToStop) {\r\n\t\t\tfor (i = childClusters.length - 1; i >= 0; i--) {\r\n\t\t\t\tc = childClusters[i];\r\n\t\t\t\tif (c._boundsNeedUpdate) {\r\n\t\t\t\t\tc._recalculateBounds();\r\n\t\t\t\t}\r\n\t\t\t\tif (boundsToApplyTo.intersects(c._bounds)) {\r\n\t\t\t\t\tc._recursively(boundsToApplyTo, zoomLevelToStart, zoomLevelToStop, runAtEveryLevel, runAtBottomLevel);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\t//Returns true if we are the parent of only one cluster and that cluster is the same as us\r\n\t_isSingleParent: function () {\r\n\t\t//Don't need to check this._markers as the rest won't work if there are any\r\n\t\treturn this._childClusters.length > 0 && this._childClusters[0]._childCount === this._childCount;\r\n\t}\r\n});\r\n\r\n","/*\r\n* Extends L.Marker to include two extra methods: clusterHide and clusterShow.\r\n* \r\n* They work as setOpacity(0) and setOpacity(1) respectively, but\r\n* don't overwrite the options.opacity\r\n* \r\n*/\r\n\r\nL.Marker.include({\r\n\tclusterHide: function () {\r\n\t\tvar backup = this.options.opacity;\r\n\t\tthis.setOpacity(0);\r\n\t\tthis.options.opacity = backup;\r\n\t\treturn this;\r\n\t},\r\n\t\r\n\tclusterShow: function () {\r\n\t\treturn this.setOpacity(this.options.opacity);\r\n\t}\r\n});\r\n\r\n\r\n","\r\nL.DistanceGrid = function (cellSize) {\r\n\tthis._cellSize = cellSize;\r\n\tthis._sqCellSize = cellSize * cellSize;\r\n\tthis._grid = {};\r\n\tthis._objectPoint = { };\r\n};\r\n\r\nL.DistanceGrid.prototype = {\r\n\r\n\taddObject: function (obj, point) {\r\n\t\tvar x = this._getCoord(point.x),\r\n\t\t y = this._getCoord(point.y),\r\n\t\t grid = this._grid,\r\n\t\t row = grid[y] = grid[y] || {},\r\n\t\t cell = row[x] = row[x] || [],\r\n\t\t stamp = L.Util.stamp(obj);\r\n\r\n\t\tthis._objectPoint[stamp] = point;\r\n\r\n\t\tcell.push(obj);\r\n\t},\r\n\r\n\tupdateObject: function (obj, point) {\r\n\t\tthis.removeObject(obj);\r\n\t\tthis.addObject(obj, point);\r\n\t},\r\n\r\n\t//Returns true if the object was found\r\n\tremoveObject: function (obj, point) {\r\n\t\tvar x = this._getCoord(point.x),\r\n\t\t y = this._getCoord(point.y),\r\n\t\t grid = this._grid,\r\n\t\t row = grid[y] = grid[y] || {},\r\n\t\t cell = row[x] = row[x] || [],\r\n\t\t i, len;\r\n\r\n\t\tdelete this._objectPoint[L.Util.stamp(obj)];\r\n\r\n\t\tfor (i = 0, len = cell.length; i < len; i++) {\r\n\t\t\tif (cell[i] === obj) {\r\n\r\n\t\t\t\tcell.splice(i, 1);\r\n\r\n\t\t\t\tif (len === 1) {\r\n\t\t\t\t\tdelete row[x];\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t},\r\n\r\n\teachObject: function (fn, context) {\r\n\t\tvar i, j, k, len, row, cell, removed,\r\n\t\t grid = this._grid;\r\n\r\n\t\tfor (i in grid) {\r\n\t\t\trow = grid[i];\r\n\r\n\t\t\tfor (j in row) {\r\n\t\t\t\tcell = row[j];\r\n\r\n\t\t\t\tfor (k = 0, len = cell.length; k < len; k++) {\r\n\t\t\t\t\tremoved = fn.call(context, cell[k]);\r\n\t\t\t\t\tif (removed) {\r\n\t\t\t\t\t\tk--;\r\n\t\t\t\t\t\tlen--;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\tgetNearObject: function (point) {\r\n\t\tvar x = this._getCoord(point.x),\r\n\t\t y = this._getCoord(point.y),\r\n\t\t i, j, k, row, cell, len, obj, dist,\r\n\t\t objectPoint = this._objectPoint,\r\n\t\t closestDistSq = this._sqCellSize,\r\n\t\t closest = null;\r\n\r\n\t\tfor (i = y - 1; i <= y + 1; i++) {\r\n\t\t\trow = this._grid[i];\r\n\t\t\tif (row) {\r\n\r\n\t\t\t\tfor (j = x - 1; j <= x + 1; j++) {\r\n\t\t\t\t\tcell = row[j];\r\n\t\t\t\t\tif (cell) {\r\n\r\n\t\t\t\t\t\tfor (k = 0, len = cell.length; k < len; k++) {\r\n\t\t\t\t\t\t\tobj = cell[k];\r\n\t\t\t\t\t\t\tdist = this._sqDist(objectPoint[L.Util.stamp(obj)], point);\r\n\t\t\t\t\t\t\tif (dist < closestDistSq ||\r\n\t\t\t\t\t\t\t\tdist <= closestDistSq && closest === null) {\r\n\t\t\t\t\t\t\t\tclosestDistSq = dist;\r\n\t\t\t\t\t\t\t\tclosest = obj;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn closest;\r\n\t},\r\n\r\n\t_getCoord: function (x) {\r\n\t\tvar coord = Math.floor(x / this._cellSize);\r\n\t\treturn isFinite(coord) ? coord : x;\r\n\t},\r\n\r\n\t_sqDist: function (p, p2) {\r\n\t\tvar dx = p2.x - p.x,\r\n\t\t dy = p2.y - p.y;\r\n\t\treturn dx * dx + dy * dy;\r\n\t}\r\n};\r\n","/* Copyright (c) 2012 the authors listed at the following URL, and/or\r\nthe authors of referenced articles or incorporated external code:\r\nhttp://en.literateprograms.org/Quickhull_(Javascript)?action=history&offset=20120410175256\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining\r\na copy of this software and associated documentation files (the\r\n\"Software\"), to deal in the Software without restriction, including\r\nwithout limitation the rights to use, copy, modify, merge, publish,\r\ndistribute, sublicense, and/or sell copies of the Software, and to\r\npermit persons to whom the Software is furnished to do so, subject to\r\nthe following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be\r\nincluded in all copies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\r\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\r\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\r\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\r\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\r\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r\n\r\nRetrieved from: http://en.literateprograms.org/Quickhull_(Javascript)?oldid=18434\r\n*/\r\n\r\n(function () {\r\n\tL.QuickHull = {\r\n\r\n\t\t/*\r\n\t\t * @param {Object} cpt a point to be measured from the baseline\r\n\t\t * @param {Array} bl the baseline, as represented by a two-element\r\n\t\t * array of latlng objects.\r\n\t\t * @returns {Number} an approximate distance measure\r\n\t\t */\r\n\t\tgetDistant: function (cpt, bl) {\r\n\t\t\tvar vY = bl[1].lat - bl[0].lat,\r\n\t\t\t\tvX = bl[0].lng - bl[1].lng;\r\n\t\t\treturn (vX * (cpt.lat - bl[0].lat) + vY * (cpt.lng - bl[0].lng));\r\n\t\t},\r\n\r\n\t\t/*\r\n\t\t * @param {Array} baseLine a two-element array of latlng objects\r\n\t\t * representing the baseline to project from\r\n\t\t * @param {Array} latLngs an array of latlng objects\r\n\t\t * @returns {Object} the maximum point and all new points to stay\r\n\t\t * in consideration for the hull.\r\n\t\t */\r\n\t\tfindMostDistantPointFromBaseLine: function (baseLine, latLngs) {\r\n\t\t\tvar maxD = 0,\r\n\t\t\t\tmaxPt = null,\r\n\t\t\t\tnewPoints = [],\r\n\t\t\t\ti, pt, d;\r\n\r\n\t\t\tfor (i = latLngs.length - 1; i >= 0; i--) {\r\n\t\t\t\tpt = latLngs[i];\r\n\t\t\t\td = this.getDistant(pt, baseLine);\r\n\r\n\t\t\t\tif (d > 0) {\r\n\t\t\t\t\tnewPoints.push(pt);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (d > maxD) {\r\n\t\t\t\t\tmaxD = d;\r\n\t\t\t\t\tmaxPt = pt;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\treturn { maxPoint: maxPt, newPoints: newPoints };\r\n\t\t},\r\n\r\n\r\n\t\t/*\r\n\t\t * Given a baseline, compute the convex hull of latLngs as an array\r\n\t\t * of latLngs.\r\n\t\t *\r\n\t\t * @param {Array} latLngs\r\n\t\t * @returns {Array}\r\n\t\t */\r\n\t\tbuildConvexHull: function (baseLine, latLngs) {\r\n\t\t\tvar convexHullBaseLines = [],\r\n\t\t\t\tt = this.findMostDistantPointFromBaseLine(baseLine, latLngs);\r\n\r\n\t\t\tif (t.maxPoint) { // if there is still a point \"outside\" the base line\r\n\t\t\t\tconvexHullBaseLines =\r\n\t\t\t\t\tconvexHullBaseLines.concat(\r\n\t\t\t\t\t\tthis.buildConvexHull([baseLine[0], t.maxPoint], t.newPoints)\r\n\t\t\t\t\t);\r\n\t\t\t\tconvexHullBaseLines =\r\n\t\t\t\t\tconvexHullBaseLines.concat(\r\n\t\t\t\t\t\tthis.buildConvexHull([t.maxPoint, baseLine[1]], t.newPoints)\r\n\t\t\t\t\t);\r\n\t\t\t\treturn convexHullBaseLines;\r\n\t\t\t} else { // if there is no more point \"outside\" the base line, the current base line is part of the convex hull\r\n\t\t\t\treturn [baseLine[0]];\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\t/*\r\n\t\t * Given an array of latlngs, compute a convex hull as an array\r\n\t\t * of latlngs\r\n\t\t *\r\n\t\t * @param {Array} latLngs\r\n\t\t * @returns {Array}\r\n\t\t */\r\n\t\tgetConvexHull: function (latLngs) {\r\n\t\t\t// find first baseline\r\n\t\t\tvar maxLat = false, minLat = false,\r\n\t\t\t\tmaxLng = false, minLng = false,\r\n\t\t\t\tmaxLatPt = null, minLatPt = null,\r\n\t\t\t\tmaxLngPt = null, minLngPt = null,\r\n\t\t\t\tmaxPt = null, minPt = null,\r\n\t\t\t\ti;\r\n\r\n\t\t\tfor (i = latLngs.length - 1; i >= 0; i--) {\r\n\t\t\t\tvar pt = latLngs[i];\r\n\t\t\t\tif (maxLat === false || pt.lat > maxLat) {\r\n\t\t\t\t\tmaxLatPt = pt;\r\n\t\t\t\t\tmaxLat = pt.lat;\r\n\t\t\t\t}\r\n\t\t\t\tif (minLat === false || pt.lat < minLat) {\r\n\t\t\t\t\tminLatPt = pt;\r\n\t\t\t\t\tminLat = pt.lat;\r\n\t\t\t\t}\r\n\t\t\t\tif (maxLng === false || pt.lng > maxLng) {\r\n\t\t\t\t\tmaxLngPt = pt;\r\n\t\t\t\t\tmaxLng = pt.lng;\r\n\t\t\t\t}\r\n\t\t\t\tif (minLng === false || pt.lng < minLng) {\r\n\t\t\t\t\tminLngPt = pt;\r\n\t\t\t\t\tminLng = pt.lng;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (minLat !== maxLat) {\r\n\t\t\t\tminPt = minLatPt;\r\n\t\t\t\tmaxPt = maxLatPt;\r\n\t\t\t} else {\r\n\t\t\t\tminPt = minLngPt;\r\n\t\t\t\tmaxPt = maxLngPt;\r\n\t\t\t}\r\n\r\n\t\t\tvar ch = [].concat(this.buildConvexHull([minPt, maxPt], latLngs),\r\n\t\t\t\t\t\t\t\tthis.buildConvexHull([maxPt, minPt], latLngs));\r\n\t\t\treturn ch;\r\n\t\t}\r\n\t};\r\n}());\r\n\r\nL.MarkerCluster.include({\r\n\tgetConvexHull: function () {\r\n\t\tvar childMarkers = this.getAllChildMarkers(),\r\n\t\t\tpoints = [],\r\n\t\t\tp, i;\r\n\r\n\t\tfor (i = childMarkers.length - 1; i >= 0; i--) {\r\n\t\t\tp = childMarkers[i].getLatLng();\r\n\t\t\tpoints.push(p);\r\n\t\t}\r\n\r\n\t\treturn L.QuickHull.getConvexHull(points);\r\n\t}\r\n});\r\n","//This code is 100% based on https://github.com/jawj/OverlappingMarkerSpiderfier-Leaflet\r\n//Huge thanks to jawj for implementing it first to make my job easy :-)\r\n\r\nL.MarkerCluster.include({\r\n\r\n\t_2PI: Math.PI * 2,\r\n\t_circleFootSeparation: 25, //related to circumference of circle\r\n\t_circleStartAngle: 0,\r\n\r\n\t_spiralFootSeparation: 28, //related to size of spiral (experiment!)\r\n\t_spiralLengthStart: 11,\r\n\t_spiralLengthFactor: 5,\r\n\r\n\t_circleSpiralSwitchover: 9, //show spiral instead of circle from this marker count upwards.\r\n\t\t\t\t\t\t\t\t// 0 -> always spiral; Infinity -> always circle\r\n\r\n\tspiderfy: function () {\r\n\t\tif (this._group._spiderfied === this || this._group._inZoomAnimation) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tvar childMarkers = this.getAllChildMarkers(null, true),\r\n\t\t\tgroup = this._group,\r\n\t\t\tmap = group._map,\r\n\t\t\tcenter = map.latLngToLayerPoint(this._latlng),\r\n\t\t\tpositions;\r\n\r\n\t\tthis._group._unspiderfy();\r\n\t\tthis._group._spiderfied = this;\r\n\r\n\t\t//TODO Maybe: childMarkers order by distance to center\r\n\r\n\t\tif (childMarkers.length >= this._circleSpiralSwitchover) {\r\n\t\t\tpositions = this._generatePointsSpiral(childMarkers.length, center);\r\n\t\t} else {\r\n\t\t\tcenter.y += 10; // Otherwise circles look wrong => hack for standard blue icon, renders differently for other icons.\r\n\t\t\tpositions = this._generatePointsCircle(childMarkers.length, center);\r\n\t\t}\r\n\r\n\t\tthis._animationSpiderfy(childMarkers, positions);\r\n\t},\r\n\r\n\tunspiderfy: function (zoomDetails) {\r\n\t\t/// Argument from zoomanim if being called in a zoom animation or null otherwise\r\n\t\tif (this._group._inZoomAnimation) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis._animationUnspiderfy(zoomDetails);\r\n\r\n\t\tthis._group._spiderfied = null;\r\n\t},\r\n\r\n\t_generatePointsCircle: function (count, centerPt) {\r\n\t\tvar circumference = this._group.options.spiderfyDistanceMultiplier * this._circleFootSeparation * (2 + count),\r\n\t\t\tlegLength = circumference / this._2PI, //radius from circumference\r\n\t\t\tangleStep = this._2PI / count,\r\n\t\t\tres = [],\r\n\t\t\ti, angle;\r\n\r\n\t\tlegLength = Math.max(legLength, 35); // Minimum distance to get outside the cluster icon.\r\n\r\n\t\tres.length = count;\r\n\r\n\t\tfor (i = 0; i < count; i++) { // Clockwise, like spiral.\r\n\t\t\tangle = this._circleStartAngle + i * angleStep;\r\n\t\t\tres[i] = new L.Point(centerPt.x + legLength * Math.cos(angle), centerPt.y + legLength * Math.sin(angle))._round();\r\n\t\t}\r\n\r\n\t\treturn res;\r\n\t},\r\n\r\n\t_generatePointsSpiral: function (count, centerPt) {\r\n\t\tvar spiderfyDistanceMultiplier = this._group.options.spiderfyDistanceMultiplier,\r\n\t\t\tlegLength = spiderfyDistanceMultiplier * this._spiralLengthStart,\r\n\t\t\tseparation = spiderfyDistanceMultiplier * this._spiralFootSeparation,\r\n\t\t\tlengthFactor = spiderfyDistanceMultiplier * this._spiralLengthFactor * this._2PI,\r\n\t\t\tangle = 0,\r\n\t\t\tres = [],\r\n\t\t\ti;\r\n\r\n\t\tres.length = count;\r\n\r\n\t\t// Higher index, closer position to cluster center.\r\n\t\tfor (i = count; i >= 0; i--) {\r\n\t\t\t// Skip the first position, so that we are already farther from center and we avoid\r\n\t\t\t// being under the default cluster icon (especially important for Circle Markers).\r\n\t\t\tif (i < count) {\r\n\t\t\t\tres[i] = new L.Point(centerPt.x + legLength * Math.cos(angle), centerPt.y + legLength * Math.sin(angle))._round();\r\n\t\t\t}\r\n\t\t\tangle += separation / legLength + i * 0.0005;\r\n\t\t\tlegLength += lengthFactor / angle;\r\n\t\t}\r\n\t\treturn res;\r\n\t},\r\n\r\n\t_noanimationUnspiderfy: function () {\r\n\t\tvar group = this._group,\r\n\t\t\tmap = group._map,\r\n\t\t\tfg = group._featureGroup,\r\n\t\t\tchildMarkers = this.getAllChildMarkers(null, true),\r\n\t\t\tm, i;\r\n\r\n\t\tgroup._ignoreMove = true;\r\n\r\n\t\tthis.setOpacity(1);\r\n\t\tfor (i = childMarkers.length - 1; i >= 0; i--) {\r\n\t\t\tm = childMarkers[i];\r\n\r\n\t\t\tfg.removeLayer(m);\r\n\r\n\t\t\tif (m._preSpiderfyLatlng) {\r\n\t\t\t\tm.setLatLng(m._preSpiderfyLatlng);\r\n\t\t\t\tdelete m._preSpiderfyLatlng;\r\n\t\t\t}\r\n\t\t\tif (m.setZIndexOffset) {\r\n\t\t\t\tm.setZIndexOffset(0);\r\n\t\t\t}\r\n\r\n\t\t\tif (m._spiderLeg) {\r\n\t\t\t\tmap.removeLayer(m._spiderLeg);\r\n\t\t\t\tdelete m._spiderLeg;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tgroup.fire('unspiderfied', {\r\n\t\t\tcluster: this,\r\n\t\t\tmarkers: childMarkers\r\n\t\t});\r\n\t\tgroup._ignoreMove = false;\r\n\t\tgroup._spiderfied = null;\r\n\t}\r\n});\r\n\r\n//Non Animated versions of everything\r\nL.MarkerClusterNonAnimated = L.MarkerCluster.extend({\r\n\t_animationSpiderfy: function (childMarkers, positions) {\r\n\t\tvar group = this._group,\r\n\t\t\tmap = group._map,\r\n\t\t\tfg = group._featureGroup,\r\n\t\t\tlegOptions = this._group.options.spiderLegPolylineOptions,\r\n\t\t\ti, m, leg, newPos;\r\n\r\n\t\tgroup._ignoreMove = true;\r\n\r\n\t\t// Traverse in ascending order to make sure that inner circleMarkers are on top of further legs. Normal markers are re-ordered by newPosition.\r\n\t\t// The reverse order trick no longer improves performance on modern browsers.\r\n\t\tfor (i = 0; i < childMarkers.length; i++) {\r\n\t\t\tnewPos = map.layerPointToLatLng(positions[i]);\r\n\t\t\tm = childMarkers[i];\r\n\r\n\t\t\t// Add the leg before the marker, so that in case the latter is a circleMarker, the leg is behind it.\r\n\t\t\tleg = new L.Polyline([this._latlng, newPos], legOptions);\r\n\t\t\tmap.addLayer(leg);\r\n\t\t\tm._spiderLeg = leg;\r\n\r\n\t\t\t// Now add the marker.\r\n\t\t\tm._preSpiderfyLatlng = m._latlng;\r\n\t\t\tm.setLatLng(newPos);\r\n\t\t\tif (m.setZIndexOffset) {\r\n\t\t\t\tm.setZIndexOffset(1000000); //Make these appear on top of EVERYTHING\r\n\t\t\t}\r\n\r\n\t\t\tfg.addLayer(m);\r\n\t\t}\r\n\t\tthis.setOpacity(0.3);\r\n\r\n\t\tgroup._ignoreMove = false;\r\n\t\tgroup.fire('spiderfied', {\r\n\t\t\tcluster: this,\r\n\t\t\tmarkers: childMarkers\r\n\t\t});\r\n\t},\r\n\r\n\t_animationUnspiderfy: function () {\r\n\t\tthis._noanimationUnspiderfy();\r\n\t}\r\n});\r\n\r\n//Animated versions here\r\nL.MarkerCluster.include({\r\n\r\n\t_animationSpiderfy: function (childMarkers, positions) {\r\n\t\tvar me = this,\r\n\t\t\tgroup = this._group,\r\n\t\t\tmap = group._map,\r\n\t\t\tfg = group._featureGroup,\r\n\t\t\tthisLayerLatLng = this._latlng,\r\n\t\t\tthisLayerPos = map.latLngToLayerPoint(thisLayerLatLng),\r\n\t\t\tsvg = L.Path.SVG,\r\n\t\t\tlegOptions = L.extend({}, this._group.options.spiderLegPolylineOptions), // Copy the options so that we can modify them for animation.\r\n\t\t\tfinalLegOpacity = legOptions.opacity,\r\n\t\t\ti, m, leg, legPath, legLength, newPos;\r\n\r\n\t\tif (finalLegOpacity === undefined) {\r\n\t\t\tfinalLegOpacity = L.MarkerClusterGroup.prototype.options.spiderLegPolylineOptions.opacity;\r\n\t\t}\r\n\r\n\t\tif (svg) {\r\n\t\t\t// If the initial opacity of the spider leg is not 0 then it appears before the animation starts.\r\n\t\t\tlegOptions.opacity = 0;\r\n\r\n\t\t\t// Add the class for CSS transitions.\r\n\t\t\tlegOptions.className = (legOptions.className || '') + ' leaflet-cluster-spider-leg';\r\n\t\t} else {\r\n\t\t\t// Make sure we have a defined opacity.\r\n\t\t\tlegOptions.opacity = finalLegOpacity;\r\n\t\t}\r\n\r\n\t\tgroup._ignoreMove = true;\r\n\r\n\t\t// Add markers and spider legs to map, hidden at our center point.\r\n\t\t// Traverse in ascending order to make sure that inner circleMarkers are on top of further legs. Normal markers are re-ordered by newPosition.\r\n\t\t// The reverse order trick no longer improves performance on modern browsers.\r\n\t\tfor (i = 0; i < childMarkers.length; i++) {\r\n\t\t\tm = childMarkers[i];\r\n\r\n\t\t\tnewPos = map.layerPointToLatLng(positions[i]);\r\n\r\n\t\t\t// Add the leg before the marker, so that in case the latter is a circleMarker, the leg is behind it.\r\n\t\t\tleg = new L.Polyline([thisLayerLatLng, newPos], legOptions);\r\n\t\t\tmap.addLayer(leg);\r\n\t\t\tm._spiderLeg = leg;\r\n\r\n\t\t\t// Explanations: https://jakearchibald.com/2013/animated-line-drawing-svg/\r\n\t\t\t// In our case the transition property is declared in the CSS file.\r\n\t\t\tif (svg) {\r\n\t\t\t\tlegPath = leg._path;\r\n\t\t\t\tlegLength = legPath.getTotalLength() + 0.1; // Need a small extra length to avoid remaining dot in Firefox.\r\n\t\t\t\tlegPath.style.strokeDasharray = legLength; // Just 1 length is enough, it will be duplicated.\r\n\t\t\t\tlegPath.style.strokeDashoffset = legLength;\r\n\t\t\t}\r\n\r\n\t\t\t// If it is a marker, add it now and we'll animate it out\r\n\t\t\tif (m.setZIndexOffset) {\r\n\t\t\t\tm.setZIndexOffset(1000000); // Make normal markers appear on top of EVERYTHING\r\n\t\t\t}\r\n\t\t\tif (m.clusterHide) {\r\n\t\t\t\tm.clusterHide();\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t// Vectors just get immediately added\r\n\t\t\tfg.addLayer(m);\r\n\r\n\t\t\tif (m._setPos) {\r\n\t\t\t\tm._setPos(thisLayerPos);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tgroup._forceLayout();\r\n\t\tgroup._animationStart();\r\n\r\n\t\t// Reveal markers and spider legs.\r\n\t\tfor (i = childMarkers.length - 1; i >= 0; i--) {\r\n\t\t\tnewPos = map.layerPointToLatLng(positions[i]);\r\n\t\t\tm = childMarkers[i];\r\n\r\n\t\t\t//Move marker to new position\r\n\t\t\tm._preSpiderfyLatlng = m._latlng;\r\n\t\t\tm.setLatLng(newPos);\r\n\t\t\t\r\n\t\t\tif (m.clusterShow) {\r\n\t\t\t\tm.clusterShow();\r\n\t\t\t}\r\n\r\n\t\t\t// Animate leg (animation is actually delegated to CSS transition).\r\n\t\t\tif (svg) {\r\n\t\t\t\tleg = m._spiderLeg;\r\n\t\t\t\tlegPath = leg._path;\r\n\t\t\t\tlegPath.style.strokeDashoffset = 0;\r\n\t\t\t\t//legPath.style.strokeOpacity = finalLegOpacity;\r\n\t\t\t\tleg.setStyle({opacity: finalLegOpacity});\r\n\t\t\t}\r\n\t\t}\r\n\t\tthis.setOpacity(0.3);\r\n\r\n\t\tgroup._ignoreMove = false;\r\n\r\n\t\tsetTimeout(function () {\r\n\t\t\tgroup._animationEnd();\r\n\t\t\tgroup.fire('spiderfied', {\r\n\t\t\t\tcluster: me,\r\n\t\t\t\tmarkers: childMarkers\r\n\t\t\t});\r\n\t\t}, 200);\r\n\t},\r\n\r\n\t_animationUnspiderfy: function (zoomDetails) {\r\n\t\tvar me = this,\r\n\t\t\tgroup = this._group,\r\n\t\t\tmap = group._map,\r\n\t\t\tfg = group._featureGroup,\r\n\t\t\tthisLayerPos = zoomDetails ? map._latLngToNewLayerPoint(this._latlng, zoomDetails.zoom, zoomDetails.center) : map.latLngToLayerPoint(this._latlng),\r\n\t\t\tchildMarkers = this.getAllChildMarkers(null, true),\r\n\t\t\tsvg = L.Path.SVG,\r\n\t\t\tm, i, leg, legPath, legLength, nonAnimatable;\r\n\r\n\t\tgroup._ignoreMove = true;\r\n\t\tgroup._animationStart();\r\n\r\n\t\t//Make us visible and bring the child markers back in\r\n\t\tthis.setOpacity(1);\r\n\t\tfor (i = childMarkers.length - 1; i >= 0; i--) {\r\n\t\t\tm = childMarkers[i];\r\n\r\n\t\t\t//Marker was added to us after we were spiderfied\r\n\t\t\tif (!m._preSpiderfyLatlng) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\t//Close any popup on the marker first, otherwise setting the location of the marker will make the map scroll\r\n\t\t\tm.closePopup();\r\n\r\n\t\t\t//Fix up the location to the real one\r\n\t\t\tm.setLatLng(m._preSpiderfyLatlng);\r\n\t\t\tdelete m._preSpiderfyLatlng;\r\n\r\n\t\t\t//Hack override the location to be our center\r\n\t\t\tnonAnimatable = true;\r\n\t\t\tif (m._setPos) {\r\n\t\t\t\tm._setPos(thisLayerPos);\r\n\t\t\t\tnonAnimatable = false;\r\n\t\t\t}\r\n\t\t\tif (m.clusterHide) {\r\n\t\t\t\tm.clusterHide();\r\n\t\t\t\tnonAnimatable = false;\r\n\t\t\t}\r\n\t\t\tif (nonAnimatable) {\r\n\t\t\t\tfg.removeLayer(m);\r\n\t\t\t}\r\n\r\n\t\t\t// Animate the spider leg back in (animation is actually delegated to CSS transition).\r\n\t\t\tif (svg) {\r\n\t\t\t\tleg = m._spiderLeg;\r\n\t\t\t\tlegPath = leg._path;\r\n\t\t\t\tlegLength = legPath.getTotalLength() + 0.1;\r\n\t\t\t\tlegPath.style.strokeDashoffset = legLength;\r\n\t\t\t\tleg.setStyle({opacity: 0});\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tgroup._ignoreMove = false;\r\n\r\n\t\tsetTimeout(function () {\r\n\t\t\t//If we have only <= one child left then that marker will be shown on the map so don't remove it!\r\n\t\t\tvar stillThereChildCount = 0;\r\n\t\t\tfor (i = childMarkers.length - 1; i >= 0; i--) {\r\n\t\t\t\tm = childMarkers[i];\r\n\t\t\t\tif (m._spiderLeg) {\r\n\t\t\t\t\tstillThereChildCount++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\r\n\t\t\tfor (i = childMarkers.length - 1; i >= 0; i--) {\r\n\t\t\t\tm = childMarkers[i];\r\n\r\n\t\t\t\tif (!m._spiderLeg) { //Has already been unspiderfied\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (m.clusterShow) {\r\n\t\t\t\t\tm.clusterShow();\r\n\t\t\t\t}\r\n\t\t\t\tif (m.setZIndexOffset) {\r\n\t\t\t\t\tm.setZIndexOffset(0);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (stillThereChildCount > 1) {\r\n\t\t\t\t\tfg.removeLayer(m);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tmap.removeLayer(m._spiderLeg);\r\n\t\t\t\tdelete m._spiderLeg;\r\n\t\t\t}\r\n\t\t\tgroup._animationEnd();\r\n\t\t\tgroup.fire('unspiderfied', {\r\n\t\t\t\tcluster: me,\r\n\t\t\t\tmarkers: childMarkers\r\n\t\t\t});\r\n\t\t}, 200);\r\n\t}\r\n});\r\n\r\n\r\nL.MarkerClusterGroup.include({\r\n\t//The MarkerCluster currently spiderfied (if any)\r\n\t_spiderfied: null,\r\n\r\n\tunspiderfy: function () {\r\n\t\tthis._unspiderfy.apply(this, arguments);\r\n\t},\r\n\r\n\t_spiderfierOnAdd: function () {\r\n\t\tthis._map.on('click', this._unspiderfyWrapper, this);\r\n\r\n\t\tif (this._map.options.zoomAnimation) {\r\n\t\t\tthis._map.on('zoomstart', this._unspiderfyZoomStart, this);\r\n\t\t}\r\n\t\t//Browsers without zoomAnimation or a big zoom don't fire zoomstart\r\n\t\tthis._map.on('zoomend', this._noanimationUnspiderfy, this);\r\n\r\n\t\tif (!L.Browser.touch) {\r\n\t\t\tthis._map.getRenderer(this);\r\n\t\t\t//Needs to happen in the pageload, not after, or animations don't work in webkit\r\n\t\t\t// http://stackoverflow.com/questions/8455200/svg-animate-with-dynamically-added-elements\r\n\t\t\t//Disable on touch browsers as the animation messes up on a touch zoom and isn't very noticable\r\n\t\t}\r\n\t},\r\n\r\n\t_spiderfierOnRemove: function () {\r\n\t\tthis._map.off('click', this._unspiderfyWrapper, this);\r\n\t\tthis._map.off('zoomstart', this._unspiderfyZoomStart, this);\r\n\t\tthis._map.off('zoomanim', this._unspiderfyZoomAnim, this);\r\n\t\tthis._map.off('zoomend', this._noanimationUnspiderfy, this);\r\n\r\n\t\t//Ensure that markers are back where they should be\r\n\t\t// Use no animation to avoid a sticky leaflet-cluster-anim class on mapPane\r\n\t\tthis._noanimationUnspiderfy();\r\n\t},\r\n\r\n\t//On zoom start we add a zoomanim handler so that we are guaranteed to be last (after markers are animated)\r\n\t//This means we can define the animation they do rather than Markers doing an animation to their actual location\r\n\t_unspiderfyZoomStart: function () {\r\n\t\tif (!this._map) { //May have been removed from the map by a zoomEnd handler\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tthis._map.on('zoomanim', this._unspiderfyZoomAnim, this);\r\n\t},\r\n\r\n\t_unspiderfyZoomAnim: function (zoomDetails) {\r\n\t\t//Wait until the first zoomanim after the user has finished touch-zooming before running the animation\r\n\t\tif (L.DomUtil.hasClass(this._map._mapPane, 'leaflet-touching')) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tthis._map.off('zoomanim', this._unspiderfyZoomAnim, this);\r\n\t\tthis._unspiderfy(zoomDetails);\r\n\t},\r\n\r\n\t_unspiderfyWrapper: function () {\r\n\t\t/// _unspiderfy but passes no arguments\r\n\t\tthis._unspiderfy();\r\n\t},\r\n\r\n\t_unspiderfy: function (zoomDetails) {\r\n\t\tif (this._spiderfied) {\r\n\t\t\tthis._spiderfied.unspiderfy(zoomDetails);\r\n\t\t}\r\n\t},\r\n\r\n\t_noanimationUnspiderfy: function () {\r\n\t\tif (this._spiderfied) {\r\n\t\t\tthis._spiderfied._noanimationUnspiderfy();\r\n\t\t}\r\n\t},\r\n\r\n\t//If the given layer is currently being spiderfied then we unspiderfy it so it isn't on the map anymore etc\r\n\t_unspiderfyLayer: function (layer) {\r\n\t\tif (layer._spiderLeg) {\r\n\t\t\tthis._featureGroup.removeLayer(layer);\r\n\r\n\t\t\tif (layer.clusterShow) {\r\n\t\t\t\tlayer.clusterShow();\r\n\t\t\t}\r\n\t\t\t\t//Position will be fixed up immediately in _animationUnspiderfy\r\n\t\t\tif (layer.setZIndexOffset) {\r\n\t\t\t\tlayer.setZIndexOffset(0);\r\n\t\t\t}\r\n\r\n\t\t\tthis._map.removeLayer(layer._spiderLeg);\r\n\t\t\tdelete layer._spiderLeg;\r\n\t\t}\r\n\t}\r\n});\r\n","/**\r\n * Adds 1 public method to MCG and 1 to L.Marker to facilitate changing\r\n * markers' icon options and refreshing their icon and their parent clusters\r\n * accordingly (case where their iconCreateFunction uses data of childMarkers\r\n * to make up the cluster icon).\r\n */\r\n\r\n\r\nL.MarkerClusterGroup.include({\r\n\t/**\r\n\t * Updates the icon of all clusters which are parents of the given marker(s).\r\n\t * In singleMarkerMode, also updates the given marker(s) icon.\r\n\t * @param layers L.MarkerClusterGroup|L.LayerGroup|Array(L.Marker)|Map(L.Marker)|\r\n\t * L.MarkerCluster|L.Marker (optional) list of markers (or single marker) whose parent\r\n\t * clusters need to be updated. If not provided, retrieves all child markers of this.\r\n\t * @returns {L.MarkerClusterGroup}\r\n\t */\r\n\trefreshClusters: function (layers) {\r\n\t\tif (!layers) {\r\n\t\t\tlayers = this._topClusterLevel.getAllChildMarkers();\r\n\t\t} else if (layers instanceof L.MarkerClusterGroup) {\r\n\t\t\tlayers = layers._topClusterLevel.getAllChildMarkers();\r\n\t\t} else if (layers instanceof L.LayerGroup) {\r\n\t\t\tlayers = layers._layers;\r\n\t\t} else if (layers instanceof L.MarkerCluster) {\r\n\t\t\tlayers = layers.getAllChildMarkers();\r\n\t\t} else if (layers instanceof L.Marker) {\r\n\t\t\tlayers = [layers];\r\n\t\t} // else: must be an Array(L.Marker)|Map(L.Marker)\r\n\t\tthis._flagParentsIconsNeedUpdate(layers);\r\n\t\tthis._refreshClustersIcons();\r\n\r\n\t\t// In case of singleMarkerMode, also re-draw the markers.\r\n\t\tif (this.options.singleMarkerMode) {\r\n\t\t\tthis._refreshSingleMarkerModeMarkers(layers);\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t/**\r\n\t * Simply flags all parent clusters of the given markers as having a \"dirty\" icon.\r\n\t * @param layers Array(L.Marker)|Map(L.Marker) list of markers.\r\n\t * @private\r\n\t */\r\n\t_flagParentsIconsNeedUpdate: function (layers) {\r\n\t\tvar id, parent;\r\n\r\n\t\t// Assumes layers is an Array or an Object whose prototype is non-enumerable.\r\n\t\tfor (id in layers) {\r\n\t\t\t// Flag parent clusters' icon as \"dirty\", all the way up.\r\n\t\t\t// Dumb process that flags multiple times upper parents, but still\r\n\t\t\t// much more efficient than trying to be smart and make short lists,\r\n\t\t\t// at least in the case of a hierarchy following a power law:\r\n\t\t\t// http://jsperf.com/flag-nodes-in-power-hierarchy/2\r\n\t\t\tparent = layers[id].__parent;\r\n\t\t\twhile (parent) {\r\n\t\t\t\tparent._iconNeedsUpdate = true;\r\n\t\t\t\tparent = parent.__parent;\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\t/**\r\n\t * Re-draws the icon of the supplied markers.\r\n\t * To be used in singleMarkerMode only.\r\n\t * @param layers Array(L.Marker)|Map(L.Marker) list of markers.\r\n\t * @private\r\n\t */\r\n\t_refreshSingleMarkerModeMarkers: function (layers) {\r\n\t\tvar id, layer;\r\n\r\n\t\tfor (id in layers) {\r\n\t\t\tlayer = layers[id];\r\n\r\n\t\t\t// Make sure we do not override markers that do not belong to THIS group.\r\n\t\t\tif (this.hasLayer(layer)) {\r\n\t\t\t\t// Need to re-create the icon first, then re-draw the marker.\r\n\t\t\t\tlayer.setIcon(this._overrideMarkerIcon(layer));\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n});\r\n\r\nL.Marker.include({\r\n\t/**\r\n\t * Updates the given options in the marker's icon and refreshes the marker.\r\n\t * @param options map object of icon options.\r\n\t * @param directlyRefreshClusters boolean (optional) true to trigger\r\n\t * MCG.refreshClustersOf() right away with this single marker.\r\n\t * @returns {L.Marker}\r\n\t */\r\n\trefreshIconOptions: function (options, directlyRefreshClusters) {\r\n\t\tvar icon = this.options.icon;\r\n\r\n\t\tL.setOptions(icon, options);\r\n\r\n\t\tthis.setIcon(icon);\r\n\r\n\t\t// Shortcut to refresh the associated MCG clusters right away.\r\n\t\t// To be used when refreshing a single marker.\r\n\t\t// Otherwise, better use MCG.refreshClusters() once at the end with\r\n\t\t// the list of modified markers.\r\n\t\tif (directlyRefreshClusters && this.__parent) {\r\n\t\t\tthis.__parent._group.refreshClusters(this);\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t}\r\n});\r\n"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/vendor/leaflet.markercluster/leaflet.markercluster.js b/deploy/grafana-map-plugin/dist/vendor/leaflet.markercluster/leaflet.markercluster.js new file mode 100755 index 0000000..67c52dc --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/leaflet.markercluster/leaflet.markercluster.js @@ -0,0 +1,3 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e.Leaflet=e.Leaflet||{},e.Leaflet.markercluster=e.Leaflet.markercluster||{}))}(this,function(e){"use strict";var t=L.MarkerClusterGroup=L.FeatureGroup.extend({options:{maxClusterRadius:80,iconCreateFunction:null,clusterPane:L.Marker.prototype.options.pane,spiderfyOnMaxZoom:!0,showCoverageOnHover:!0,zoomToBoundsOnClick:!0,singleMarkerMode:!1,disableClusteringAtZoom:null,removeOutsideVisibleBounds:!0,animate:!0,animateAddingMarkers:!1,spiderfyDistanceMultiplier:1,spiderLegPolylineOptions:{weight:1.5,color:"#222",opacity:.5},chunkedLoading:!1,chunkInterval:200,chunkDelay:50,chunkProgress:null,polygonOptions:{}},initialize:function(e){L.Util.setOptions(this,e),this.options.iconCreateFunction||(this.options.iconCreateFunction=this._defaultIconCreateFunction),this._featureGroup=L.featureGroup(),this._featureGroup.addEventParent(this),this._nonPointGroup=L.featureGroup(),this._nonPointGroup.addEventParent(this),this._inZoomAnimation=0,this._needsClustering=[],this._needsRemoving=[],this._currentShownBounds=null,this._queue=[],this._childMarkerEventHandlers={dragstart:this._childMarkerDragStart,move:this._childMarkerMoved,dragend:this._childMarkerDragEnd};var t=L.DomUtil.TRANSITION&&this.options.animate;L.extend(this,t?this._withAnimation:this._noAnimation),this._markerCluster=t?L.MarkerCluster:L.MarkerClusterNonAnimated},addLayer:function(e){if(e instanceof L.LayerGroup)return this.addLayers([e]);if(!e.getLatLng)return this._nonPointGroup.addLayer(e),this.fire("layeradd",{layer:e}),this;if(!this._map)return this._needsClustering.push(e),this.fire("layeradd",{layer:e}),this;if(this.hasLayer(e))return this;this._unspiderfy&&this._unspiderfy(),this._addLayer(e,this._maxZoom),this.fire("layeradd",{layer:e}),this._topClusterLevel._recalculateBounds(),this._refreshClustersIcons();var t=e,i=this._zoom;if(e.__parent)for(;t.__parent._zoom>=i;)t=t.__parent;return this._currentShownBounds.contains(t.getLatLng())&&(this.options.animateAddingMarkers?this._animationAddLayer(e,t):this._animationAddLayerNonAnimated(e,t)),this},removeLayer:function(e){return e instanceof L.LayerGroup?this.removeLayers([e]):e.getLatLng?this._map?e.__parent?(this._unspiderfy&&(this._unspiderfy(),this._unspiderfyLayer(e)),this._removeLayer(e,!0),this.fire("layerremove",{layer:e}),this._topClusterLevel._recalculateBounds(),this._refreshClustersIcons(),e.off(this._childMarkerEventHandlers,this),this._featureGroup.hasLayer(e)&&(this._featureGroup.removeLayer(e),e.clusterShow&&e.clusterShow()),this):this:(!this._arraySplice(this._needsClustering,e)&&this.hasLayer(e)&&this._needsRemoving.push({layer:e,latlng:e._latlng}),this.fire("layerremove",{layer:e}),this):(this._nonPointGroup.removeLayer(e),this.fire("layerremove",{layer:e}),this)},addLayers:function(e,t){if(!L.Util.isArray(e))return this.addLayer(e);var i,n=this._featureGroup,r=this._nonPointGroup,s=this.options.chunkedLoading,o=this.options.chunkInterval,a=this.options.chunkProgress,h=e.length,l=0,u=!0;if(this._map){var _=(new Date).getTime(),d=L.bind(function(){for(var c=(new Date).getTime();h>l;l++){if(s&&0===l%200){var p=(new Date).getTime()-c;if(p>o)break}if(i=e[l],i instanceof L.LayerGroup)u&&(e=e.slice(),u=!1),this._extractNonGroupLayers(i,e),h=e.length;else if(i.getLatLng){if(!this.hasLayer(i)&&(this._addLayer(i,this._maxZoom),t||this.fire("layeradd",{layer:i}),i.__parent&&2===i.__parent.getChildCount())){var f=i.__parent.getAllChildMarkers(),m=f[0]===i?f[1]:f[0];n.removeLayer(m)}}else r.addLayer(i),t||this.fire("layeradd",{layer:i})}a&&a(l,h,(new Date).getTime()-_),l===h?(this._topClusterLevel._recalculateBounds(),this._refreshClustersIcons(),this._topClusterLevel._recursivelyAddChildrenToMap(null,this._zoom,this._currentShownBounds)):setTimeout(d,this.options.chunkDelay)},this);d()}else for(var c=this._needsClustering;h>l;l++)i=e[l],i instanceof L.LayerGroup?(u&&(e=e.slice(),u=!1),this._extractNonGroupLayers(i,e),h=e.length):i.getLatLng?this.hasLayer(i)||c.push(i):r.addLayer(i);return this},removeLayers:function(e){var t,i,n=e.length,r=this._featureGroup,s=this._nonPointGroup,o=!0;if(!this._map){for(t=0;n>t;t++)i=e[t],i instanceof L.LayerGroup?(o&&(e=e.slice(),o=!1),this._extractNonGroupLayers(i,e),n=e.length):(this._arraySplice(this._needsClustering,i),s.removeLayer(i),this.hasLayer(i)&&this._needsRemoving.push({layer:i,latlng:i._latlng}),this.fire("layerremove",{layer:i}));return this}if(this._unspiderfy){this._unspiderfy();var a=e.slice(),h=n;for(t=0;h>t;t++)i=a[t],i instanceof L.LayerGroup?(this._extractNonGroupLayers(i,a),h=a.length):this._unspiderfyLayer(i)}for(t=0;n>t;t++)i=e[t],i instanceof L.LayerGroup?(o&&(e=e.slice(),o=!1),this._extractNonGroupLayers(i,e),n=e.length):i.__parent?(this._removeLayer(i,!0,!0),this.fire("layerremove",{layer:i}),r.hasLayer(i)&&(r.removeLayer(i),i.clusterShow&&i.clusterShow())):(s.removeLayer(i),this.fire("layerremove",{layer:i}));return this._topClusterLevel._recalculateBounds(),this._refreshClustersIcons(),this._topClusterLevel._recursivelyAddChildrenToMap(null,this._zoom,this._currentShownBounds),this},clearLayers:function(){return this._map||(this._needsClustering=[],this._needsRemoving=[],delete this._gridClusters,delete this._gridUnclustered),this._noanimationUnspiderfy&&this._noanimationUnspiderfy(),this._featureGroup.clearLayers(),this._nonPointGroup.clearLayers(),this.eachLayer(function(e){e.off(this._childMarkerEventHandlers,this),delete e.__parent},this),this._map&&this._generateInitialClusters(),this},getBounds:function(){var e=new L.LatLngBounds;this._topClusterLevel&&e.extend(this._topClusterLevel._bounds);for(var t=this._needsClustering.length-1;t>=0;t--)e.extend(this._needsClustering[t].getLatLng());return e.extend(this._nonPointGroup.getBounds()),e},eachLayer:function(e,t){var i,n,r,s=this._needsClustering.slice(),o=this._needsRemoving;for(this._topClusterLevel&&this._topClusterLevel.getAllChildMarkers(s),n=s.length-1;n>=0;n--){for(i=!0,r=o.length-1;r>=0;r--)if(o[r].layer===s[n]){i=!1;break}i&&e.call(t,s[n])}this._nonPointGroup.eachLayer(e,t)},getLayers:function(){var e=[];return this.eachLayer(function(t){e.push(t)}),e},getLayer:function(e){var t=null;return e=parseInt(e,10),this.eachLayer(function(i){L.stamp(i)===e&&(t=i)}),t},hasLayer:function(e){if(!e)return!1;var t,i=this._needsClustering;for(t=i.length-1;t>=0;t--)if(i[t]===e)return!0;for(i=this._needsRemoving,t=i.length-1;t>=0;t--)if(i[t].layer===e)return!1;return!(!e.__parent||e.__parent._group!==this)||this._nonPointGroup.hasLayer(e)},zoomToShowLayer:function(e,t){"function"!=typeof t&&(t=function(){});var i=function(){!e._icon&&!e.__parent._icon||this._inZoomAnimation||(this._map.off("moveend",i,this),this.off("animationend",i,this),e._icon?t():e.__parent._icon&&(this.once("spiderfied",t,this),e.__parent.spiderfy()))};e._icon&&this._map.getBounds().contains(e.getLatLng())?t():e.__parent._zoomt;t++)n=this._needsRemoving[t],n.newlatlng=n.layer._latlng,n.layer._latlng=n.latlng;for(t=0,i=this._needsRemoving.length;i>t;t++)n=this._needsRemoving[t],this._removeLayer(n.layer,!0),n.layer._latlng=n.newlatlng;this._needsRemoving=[],this._zoom=Math.round(this._map._zoom),this._currentShownBounds=this._getExpandedVisibleBounds(),this._map.on("zoomend",this._zoomEnd,this),this._map.on("moveend",this._moveEnd,this),this._spiderfierOnAdd&&this._spiderfierOnAdd(),this._bindEvents(),i=this._needsClustering,this._needsClustering=[],this.addLayers(i,!0)},onRemove:function(e){e.off("zoomend",this._zoomEnd,this),e.off("moveend",this._moveEnd,this),this._unbindEvents(),this._map._mapPane.className=this._map._mapPane.className.replace(" leaflet-cluster-anim",""),this._spiderfierOnRemove&&this._spiderfierOnRemove(),delete this._maxLat,this._hideCoverage(),this._featureGroup.remove(),this._nonPointGroup.remove(),this._featureGroup.clearLayers(),this._map=null},getVisibleParent:function(e){for(var t=e;t&&!t._icon;)t=t.__parent;return t||null},_arraySplice:function(e,t){for(var i=e.length-1;i>=0;i--)if(e[i]===t)return e.splice(i,1),!0},_removeFromGridUnclustered:function(e,t){for(var i=this._map,n=this._gridUnclustered,r=Math.floor(this._map.getMinZoom());t>=r&&n[t].removeObject(e,i.project(e.getLatLng(),t));t--);},_childMarkerDragStart:function(e){e.target.__dragStart=e.target._latlng},_childMarkerMoved:function(e){if(!this._ignoreMove&&!e.target.__dragStart){var t=e.target._popup&&e.target._popup.isOpen();this._moveChild(e.target,e.oldLatLng,e.latlng),t&&e.target.openPopup()}},_moveChild:function(e,t,i){e._latlng=t,this.removeLayer(e),e._latlng=i,this.addLayer(e)},_childMarkerDragEnd:function(e){var t=e.target.__dragStart;delete e.target.__dragStart,t&&this._moveChild(e.target,t,e.target._latlng)},_removeLayer:function(e,t,i){var n=this._gridClusters,r=this._gridUnclustered,s=this._featureGroup,o=this._map,a=Math.floor(this._map.getMinZoom());t&&this._removeFromGridUnclustered(e,this._maxZoom);var h,l=e.__parent,u=l._markers;for(this._arraySplice(u,e);l&&(l._childCount--,l._boundsNeedUpdate=!0,!(l._zoomt?"small":100>t?"medium":"large",new L.DivIcon({html:"
"+t+"
",className:"marker-cluster"+i,iconSize:new L.Point(40,40)})},_bindEvents:function(){var e=this._map,t=this.options.spiderfyOnMaxZoom,i=this.options.showCoverageOnHover,n=this.options.zoomToBoundsOnClick;(t||n)&&this.on("clusterclick",this._zoomOrSpiderfy,this),i&&(this.on("clustermouseover",this._showCoverage,this),this.on("clustermouseout",this._hideCoverage,this),e.on("zoomend",this._hideCoverage,this))},_zoomOrSpiderfy:function(e){for(var t=e.layer,i=t;1===i._childClusters.length;)i=i._childClusters[0];i._zoom===this._maxZoom&&i._childCount===t._childCount&&this.options.spiderfyOnMaxZoom?t.spiderfy():this.options.zoomToBoundsOnClick&&t.zoomToBounds(),e.originalEvent&&13===e.originalEvent.keyCode&&this._map._container.focus()},_showCoverage:function(e){var t=this._map;this._inZoomAnimation||(this._shownPolygon&&t.removeLayer(this._shownPolygon),e.layer.getChildCount()>2&&e.layer!==this._spiderfied&&(this._shownPolygon=new L.Polygon(e.layer.getConvexHull(),this.options.polygonOptions),t.addLayer(this._shownPolygon)))},_hideCoverage:function(){this._shownPolygon&&(this._map.removeLayer(this._shownPolygon),this._shownPolygon=null)},_unbindEvents:function(){var e=this.options.spiderfyOnMaxZoom,t=this.options.showCoverageOnHover,i=this.options.zoomToBoundsOnClick,n=this._map;(e||i)&&this.off("clusterclick",this._zoomOrSpiderfy,this),t&&(this.off("clustermouseover",this._showCoverage,this),this.off("clustermouseout",this._hideCoverage,this),n.off("zoomend",this._hideCoverage,this))},_zoomEnd:function(){this._map&&(this._mergeSplitClusters(),this._zoom=Math.round(this._map._zoom),this._currentShownBounds=this._getExpandedVisibleBounds())},_moveEnd:function(){if(!this._inZoomAnimation){var e=this._getExpandedVisibleBounds();this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,Math.floor(this._map.getMinZoom()),this._zoom,e),this._topClusterLevel._recursivelyAddChildrenToMap(null,Math.round(this._map._zoom),e),this._currentShownBounds=e}},_generateInitialClusters:function(){var e=Math.ceil(this._map.getMaxZoom()),t=Math.floor(this._map.getMinZoom()),i=this.options.maxClusterRadius,n=i;"function"!=typeof i&&(n=function(){return i}),null!==this.options.disableClusteringAtZoom&&(e=this.options.disableClusteringAtZoom-1),this._maxZoom=e,this._gridClusters={},this._gridUnclustered={};for(var r=e;r>=t;r--)this._gridClusters[r]=new L.DistanceGrid(n(r)),this._gridUnclustered[r]=new L.DistanceGrid(n(r));this._topClusterLevel=new this._markerCluster(this,t-1)},_addLayer:function(e,t){var i,n,r=this._gridClusters,s=this._gridUnclustered,o=Math.floor(this._map.getMinZoom());for(this.options.singleMarkerMode&&this._overrideMarkerIcon(e),e.on(this._childMarkerEventHandlers,this);t>=o;t--){i=this._map.project(e.getLatLng(),t);var a=r[t].getNearObject(i);if(a)return a._addChild(e),e.__parent=a,void 0;if(a=s[t].getNearObject(i)){var h=a.__parent;h&&this._removeLayer(a,!1);var l=new this._markerCluster(this,t,a,e);r[t].addObject(l,this._map.project(l._cLatLng,t)),a.__parent=l,e.__parent=l;var u=l;for(n=t-1;n>h._zoom;n--)u=new this._markerCluster(this,n,u),r[n].addObject(u,this._map.project(a.getLatLng(),n));return h._addChild(u),this._removeFromGridUnclustered(a,t),void 0}s[t].addObject(e,i)}this._topClusterLevel._addChild(e),e.__parent=this._topClusterLevel},_refreshClustersIcons:function(){this._featureGroup.eachLayer(function(e){e instanceof L.MarkerCluster&&e._iconNeedsUpdate&&e._updateIcon()})},_enqueue:function(e){this._queue.push(e),this._queueTimeout||(this._queueTimeout=setTimeout(L.bind(this._processQueue,this),300))},_processQueue:function(){for(var e=0;ee?(this._animationStart(),this._animationZoomOut(this._zoom,e)):this._moveEnd()},_getExpandedVisibleBounds:function(){return this.options.removeOutsideVisibleBounds?L.Browser.mobile?this._checkBoundsMaxLat(this._map.getBounds()):this._checkBoundsMaxLat(this._map.getBounds().pad(1)):this._mapBoundsInfinite},_checkBoundsMaxLat:function(e){var t=this._maxLat;return void 0!==t&&(e.getNorth()>=t&&(e._northEast.lat=1/0),e.getSouth()<=-t&&(e._southWest.lat=-1/0)),e},_animationAddLayerNonAnimated:function(e,t){if(t===e)this._featureGroup.addLayer(e);else if(2===t._childCount){t._addToMap();var i=t.getAllChildMarkers();this._featureGroup.removeLayer(i[0]),this._featureGroup.removeLayer(i[1])}else t._updateIcon()},_extractNonGroupLayers:function(e,t){var i,n=e.getLayers(),r=0;for(t=t||[];r=0;i--)o=h[i],n.contains(o._latlng)||r.removeLayer(o)}),this._forceLayout(),this._topClusterLevel._recursivelyBecomeVisible(n,t),r.eachLayer(function(e){e instanceof L.MarkerCluster||!e._icon||e.clusterShow()}),this._topClusterLevel._recursively(n,e,t,function(e){e._recursivelyRestoreChildPositions(t)}),this._ignoreMove=!1,this._enqueue(function(){this._topClusterLevel._recursively(n,e,s,function(e){r.removeLayer(e),e.clusterShow()}),this._animationEnd()})},_animationZoomOut:function(e,t){this._animationZoomOutSingle(this._topClusterLevel,e-1,t),this._topClusterLevel._recursivelyAddChildrenToMap(null,t,this._getExpandedVisibleBounds()),this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,Math.floor(this._map.getMinZoom()),e,this._getExpandedVisibleBounds())},_animationAddLayer:function(e,t){var i=this,n=this._featureGroup;n.addLayer(e),t!==e&&(t._childCount>2?(t._updateIcon(),this._forceLayout(),this._animationStart(),e._setPos(this._map.latLngToLayerPoint(t.getLatLng())),e.clusterHide(),this._enqueue(function(){n.removeLayer(e),e.clusterShow(),i._animationEnd()})):(this._forceLayout(),i._animationStart(),i._animationZoomOutSingle(t,this._map.getMaxZoom(),this._zoom)))}},_animationZoomOutSingle:function(e,t,i){var n=this._getExpandedVisibleBounds(),r=Math.floor(this._map.getMinZoom());e._recursivelyAnimateChildrenInAndAddSelfToMap(n,r,t+1,i);var s=this;this._forceLayout(),e._recursivelyBecomeVisible(n,i),this._enqueue(function(){if(1===e._childCount){var o=e._markers[0];this._ignoreMove=!0,o.setLatLng(o.getLatLng()),this._ignoreMove=!1,o.clusterShow&&o.clusterShow()}else e._recursively(n,i,r,function(e){e._recursivelyRemoveChildrenFromMap(n,r,t+1)});s._animationEnd()})},_animationEnd:function(){this._map&&(this._map._mapPane.className=this._map._mapPane.className.replace(" leaflet-cluster-anim","")),this._inZoomAnimation--,this.fire("animationend")},_forceLayout:function(){L.Util.falseFn(document.body.offsetWidth)}}),L.markerClusterGroup=function(e){return new L.MarkerClusterGroup(e)};var i=L.MarkerCluster=L.Marker.extend({options:L.Icon.prototype.options,initialize:function(e,t,i,n){L.Marker.prototype.initialize.call(this,i?i._cLatLng||i.getLatLng():new L.LatLng(0,0),{icon:this,pane:e.options.clusterPane}),this._group=e,this._zoom=t,this._markers=[],this._childClusters=[],this._childCount=0,this._iconNeedsUpdate=!0,this._boundsNeedUpdate=!0,this._bounds=new L.LatLngBounds,i&&this._addChild(i),n&&this._addChild(n)},getAllChildMarkers:function(e,t){e=e||[];for(var i=this._childClusters.length-1;i>=0;i--)this._childClusters[i].getAllChildMarkers(e);for(var n=this._markers.length-1;n>=0;n--)t&&this._markers[n].__dragStart||e.push(this._markers[n]);return e},getChildCount:function(){return this._childCount},zoomToBounds:function(e){for(var t,i=this._childClusters.slice(),n=this._group._map,r=n.getBoundsZoom(this._bounds),s=this._zoom+1,o=n.getZoom();i.length>0&&r>s;){s++;var a=[];for(t=0;ts?this._group._map.setView(this._latlng,s):o>=r?this._group._map.setView(this._latlng,o+1):this._group._map.fitBounds(this._bounds,e)},getBounds:function(){var e=new L.LatLngBounds;return e.extend(this._bounds),e},_updateIcon:function(){this._iconNeedsUpdate=!0,this._icon&&this.setIcon(this)},createIcon:function(){return this._iconNeedsUpdate&&(this._iconObj=this._group.options.iconCreateFunction(this),this._iconNeedsUpdate=!1),this._iconObj.createIcon()},createShadow:function(){return this._iconObj.createShadow()},_addChild:function(e,t){this._iconNeedsUpdate=!0,this._boundsNeedUpdate=!0,this._setClusterCenter(e),e instanceof L.MarkerCluster?(t||(this._childClusters.push(e),e.__parent=this),this._childCount+=e._childCount):(t||this._markers.push(e),this._childCount++),this.__parent&&this.__parent._addChild(e,!0)},_setClusterCenter:function(e){this._cLatLng||(this._cLatLng=e._cLatLng||e._latlng)},_resetBounds:function(){var e=this._bounds;e._southWest&&(e._southWest.lat=1/0,e._southWest.lng=1/0),e._northEast&&(e._northEast.lat=-1/0,e._northEast.lng=-1/0)},_recalculateBounds:function(){var e,t,i,n,r=this._markers,s=this._childClusters,o=0,a=0,h=this._childCount;if(0!==h){for(this._resetBounds(),e=0;e=0;i--)n=r[i],n._icon&&(n._setPos(t),n.clusterHide())},function(e){var i,n,r=e._childClusters;for(i=r.length-1;i>=0;i--)n=r[i],n._icon&&(n._setPos(t),n.clusterHide())})},_recursivelyAnimateChildrenInAndAddSelfToMap:function(e,t,i,n){this._recursively(e,n,t,function(r){r._recursivelyAnimateChildrenIn(e,r._group._map.latLngToLayerPoint(r.getLatLng()).round(),i),r._isSingleParent()&&i-1===n?(r.clusterShow(),r._recursivelyRemoveChildrenFromMap(e,t,i)):r.clusterHide(),r._addToMap()})},_recursivelyBecomeVisible:function(e,t){this._recursively(e,this._group._map.getMinZoom(),t,null,function(e){e.clusterShow()})},_recursivelyAddChildrenToMap:function(e,t,i){this._recursively(i,this._group._map.getMinZoom()-1,t,function(n){if(t!==n._zoom)for(var r=n._markers.length-1;r>=0;r--){var s=n._markers[r];i.contains(s._latlng)&&(e&&(s._backupLatlng=s.getLatLng(),s.setLatLng(e),s.clusterHide&&s.clusterHide()),n._group._featureGroup.addLayer(s))}},function(t){t._addToMap(e)})},_recursivelyRestoreChildPositions:function(e){for(var t=this._markers.length-1;t>=0;t--){var i=this._markers[t];i._backupLatlng&&(i.setLatLng(i._backupLatlng),delete i._backupLatlng)}if(e-1===this._zoom)for(var n=this._childClusters.length-1;n>=0;n--)this._childClusters[n]._restorePosition();else for(var r=this._childClusters.length-1;r>=0;r--)this._childClusters[r]._recursivelyRestoreChildPositions(e)},_restorePosition:function(){this._backupLatlng&&(this.setLatLng(this._backupLatlng),delete this._backupLatlng)},_recursivelyRemoveChildrenFromMap:function(e,t,i,n){var r,s;this._recursively(e,t-1,i-1,function(e){for(s=e._markers.length-1;s>=0;s--)r=e._markers[s],n&&n.contains(r._latlng)||(e._group._featureGroup.removeLayer(r),r.clusterShow&&r.clusterShow())},function(e){for(s=e._childClusters.length-1;s>=0;s--)r=e._childClusters[s],n&&n.contains(r._latlng)||(e._group._featureGroup.removeLayer(r),r.clusterShow&&r.clusterShow())})},_recursively:function(e,t,i,n,r){var s,o,a=this._childClusters,h=this._zoom;if(h>=t&&(n&&n(this),r&&h===i&&r(this)),t>h||i>h)for(s=a.length-1;s>=0;s--)o=a[s],o._boundsNeedUpdate&&o._recalculateBounds(),e.intersects(o._bounds)&&o._recursively(e,t,i,n,r)},_isSingleParent:function(){return this._childClusters.length>0&&this._childClusters[0]._childCount===this._childCount}});L.Marker.include({clusterHide:function(){var e=this.options.opacity;return this.setOpacity(0),this.options.opacity=e,this},clusterShow:function(){return this.setOpacity(this.options.opacity)}}),L.DistanceGrid=function(e){this._cellSize=e,this._sqCellSize=e*e,this._grid={},this._objectPoint={}},L.DistanceGrid.prototype={addObject:function(e,t){var i=this._getCoord(t.x),n=this._getCoord(t.y),r=this._grid,s=r[n]=r[n]||{},o=s[i]=s[i]||[],a=L.Util.stamp(e);this._objectPoint[a]=t,o.push(e)},updateObject:function(e,t){this.removeObject(e),this.addObject(e,t)},removeObject:function(e,t){var i,n,r=this._getCoord(t.x),s=this._getCoord(t.y),o=this._grid,a=o[s]=o[s]||{},h=a[r]=a[r]||[];for(delete this._objectPoint[L.Util.stamp(e)],i=0,n=h.length;n>i;i++)if(h[i]===e)return h.splice(i,1),1===n&&delete a[r],!0},eachObject:function(e,t){var i,n,r,s,o,a,h,l=this._grid;for(i in l){o=l[i];for(n in o)for(a=o[n],r=0,s=a.length;s>r;r++)h=e.call(t,a[r]),h&&(r--,s--)}},getNearObject:function(e){var t,i,n,r,s,o,a,h,l=this._getCoord(e.x),u=this._getCoord(e.y),_=this._objectPoint,d=this._sqCellSize,c=null;for(t=u-1;u+1>=t;t++)if(r=this._grid[t])for(i=l-1;l+1>=i;i++)if(s=r[i])for(n=0,o=s.length;o>n;n++)a=s[n],h=this._sqDist(_[L.Util.stamp(a)],e),(d>h||d>=h&&null===c)&&(d=h,c=a);return c},_getCoord:function(e){var t=Math.floor(e/this._cellSize);return isFinite(t)?t:e},_sqDist:function(e,t){var i=t.x-e.x,n=t.y-e.y;return i*i+n*n}},function(){L.QuickHull={getDistant:function(e,t){var i=t[1].lat-t[0].lat,n=t[0].lng-t[1].lng;return n*(e.lat-t[0].lat)+i*(e.lng-t[0].lng)},findMostDistantPointFromBaseLine:function(e,t){var i,n,r,s=0,o=null,a=[];for(i=t.length-1;i>=0;i--)n=t[i],r=this.getDistant(n,e),r>0&&(a.push(n),r>s&&(s=r,o=n));return{maxPoint:o,newPoints:a}},buildConvexHull:function(e,t){var i=[],n=this.findMostDistantPointFromBaseLine(e,t);return n.maxPoint?(i=i.concat(this.buildConvexHull([e[0],n.maxPoint],n.newPoints)),i=i.concat(this.buildConvexHull([n.maxPoint,e[1]],n.newPoints))):[e[0]]},getConvexHull:function(e){var t,i=!1,n=!1,r=!1,s=!1,o=null,a=null,h=null,l=null,u=null,_=null;for(t=e.length-1;t>=0;t--){var d=e[t];(i===!1||d.lat>i)&&(o=d,i=d.lat),(n===!1||d.latr)&&(h=d,r=d.lng),(s===!1||d.lng=0;t--)e=i[t].getLatLng(),n.push(e);return L.QuickHull.getConvexHull(n)}}),L.MarkerCluster.include({_2PI:2*Math.PI,_circleFootSeparation:25,_circleStartAngle:0,_spiralFootSeparation:28,_spiralLengthStart:11,_spiralLengthFactor:5,_circleSpiralSwitchover:9,spiderfy:function(){if(this._group._spiderfied!==this&&!this._group._inZoomAnimation){var e,t=this.getAllChildMarkers(null,!0),i=this._group,n=i._map,r=n.latLngToLayerPoint(this._latlng);this._group._unspiderfy(),this._group._spiderfied=this,t.length>=this._circleSpiralSwitchover?e=this._generatePointsSpiral(t.length,r):(r.y+=10,e=this._generatePointsCircle(t.length,r)),this._animationSpiderfy(t,e)}},unspiderfy:function(e){this._group._inZoomAnimation||(this._animationUnspiderfy(e),this._group._spiderfied=null)},_generatePointsCircle:function(e,t){var i,n,r=this._group.options.spiderfyDistanceMultiplier*this._circleFootSeparation*(2+e),s=r/this._2PI,o=this._2PI/e,a=[];for(s=Math.max(s,35),a.length=e,i=0;e>i;i++)n=this._circleStartAngle+i*o,a[i]=new L.Point(t.x+s*Math.cos(n),t.y+s*Math.sin(n))._round();return a},_generatePointsSpiral:function(e,t){var i,n=this._group.options.spiderfyDistanceMultiplier,r=n*this._spiralLengthStart,s=n*this._spiralFootSeparation,o=n*this._spiralLengthFactor*this._2PI,a=0,h=[];for(h.length=e,i=e;i>=0;i--)e>i&&(h[i]=new L.Point(t.x+r*Math.cos(a),t.y+r*Math.sin(a))._round()),a+=s/r+5e-4*i,r+=o/a;return h},_noanimationUnspiderfy:function(){var e,t,i=this._group,n=i._map,r=i._featureGroup,s=this.getAllChildMarkers(null,!0);for(i._ignoreMove=!0,this.setOpacity(1),t=s.length-1;t>=0;t--)e=s[t],r.removeLayer(e),e._preSpiderfyLatlng&&(e.setLatLng(e._preSpiderfyLatlng),delete e._preSpiderfyLatlng),e.setZIndexOffset&&e.setZIndexOffset(0),e._spiderLeg&&(n.removeLayer(e._spiderLeg),delete e._spiderLeg);i.fire("unspiderfied",{cluster:this,markers:s}),i._ignoreMove=!1,i._spiderfied=null}}),L.MarkerClusterNonAnimated=L.MarkerCluster.extend({_animationSpiderfy:function(e,t){var i,n,r,s,o=this._group,a=o._map,h=o._featureGroup,l=this._group.options.spiderLegPolylineOptions;for(o._ignoreMove=!0,i=0;i=0;i--)a=u.layerPointToLatLng(t[i]),n=e[i],n._preSpiderfyLatlng=n._latlng,n.setLatLng(a),n.clusterShow&&n.clusterShow(),p&&(r=n._spiderLeg,s=r._path,s.style.strokeDashoffset=0,r.setStyle({opacity:m}));this.setOpacity(.3),l._ignoreMove=!1,setTimeout(function(){l._animationEnd(),l.fire("spiderfied",{cluster:h,markers:e})},200)},_animationUnspiderfy:function(e){var t,i,n,r,s,o,a=this,h=this._group,l=h._map,u=h._featureGroup,_=e?l._latLngToNewLayerPoint(this._latlng,e.zoom,e.center):l.latLngToLayerPoint(this._latlng),d=this.getAllChildMarkers(null,!0),c=L.Path.SVG;for(h._ignoreMove=!0,h._animationStart(),this.setOpacity(1),i=d.length-1;i>=0;i--)t=d[i],t._preSpiderfyLatlng&&(t.closePopup(),t.setLatLng(t._preSpiderfyLatlng),delete t._preSpiderfyLatlng,o=!0,t._setPos&&(t._setPos(_),o=!1),t.clusterHide&&(t.clusterHide(),o=!1),o&&u.removeLayer(t),c&&(n=t._spiderLeg,r=n._path,s=r.getTotalLength()+.1,r.style.strokeDashoffset=s,n.setStyle({opacity:0})));h._ignoreMove=!1,setTimeout(function(){var e=0;for(i=d.length-1;i>=0;i--)t=d[i],t._spiderLeg&&e++;for(i=d.length-1;i>=0;i--)t=d[i],t._spiderLeg&&(t.clusterShow&&t.clusterShow(),t.setZIndexOffset&&t.setZIndexOffset(0),e>1&&u.removeLayer(t),l.removeLayer(t._spiderLeg),delete t._spiderLeg);h._animationEnd(),h.fire("unspiderfied",{cluster:a,markers:d})},200)}}),L.MarkerClusterGroup.include({_spiderfied:null,unspiderfy:function(){this._unspiderfy.apply(this,arguments)},_spiderfierOnAdd:function(){this._map.on("click",this._unspiderfyWrapper,this),this._map.options.zoomAnimation&&this._map.on("zoomstart",this._unspiderfyZoomStart,this),this._map.on("zoomend",this._noanimationUnspiderfy,this),L.Browser.touch||this._map.getRenderer(this)},_spiderfierOnRemove:function(){this._map.off("click",this._unspiderfyWrapper,this),this._map.off("zoomstart",this._unspiderfyZoomStart,this),this._map.off("zoomanim",this._unspiderfyZoomAnim,this),this._map.off("zoomend",this._noanimationUnspiderfy,this),this._noanimationUnspiderfy() +},_unspiderfyZoomStart:function(){this._map&&this._map.on("zoomanim",this._unspiderfyZoomAnim,this)},_unspiderfyZoomAnim:function(e){L.DomUtil.hasClass(this._map._mapPane,"leaflet-touching")||(this._map.off("zoomanim",this._unspiderfyZoomAnim,this),this._unspiderfy(e))},_unspiderfyWrapper:function(){this._unspiderfy()},_unspiderfy:function(e){this._spiderfied&&this._spiderfied.unspiderfy(e)},_noanimationUnspiderfy:function(){this._spiderfied&&this._spiderfied._noanimationUnspiderfy()},_unspiderfyLayer:function(e){e._spiderLeg&&(this._featureGroup.removeLayer(e),e.clusterShow&&e.clusterShow(),e.setZIndexOffset&&e.setZIndexOffset(0),this._map.removeLayer(e._spiderLeg),delete e._spiderLeg)}}),L.MarkerClusterGroup.include({refreshClusters:function(e){return e?e instanceof L.MarkerClusterGroup?e=e._topClusterLevel.getAllChildMarkers():e instanceof L.LayerGroup?e=e._layers:e instanceof L.MarkerCluster?e=e.getAllChildMarkers():e instanceof L.Marker&&(e=[e]):e=this._topClusterLevel.getAllChildMarkers(),this._flagParentsIconsNeedUpdate(e),this._refreshClustersIcons(),this.options.singleMarkerMode&&this._refreshSingleMarkerModeMarkers(e),this},_flagParentsIconsNeedUpdate:function(e){var t,i;for(t in e)for(i=e[t].__parent;i;)i._iconNeedsUpdate=!0,i=i.__parent},_refreshSingleMarkerModeMarkers:function(e){var t,i;for(t in e)i=e[t],this.hasLayer(i)&&i.setIcon(this._overrideMarkerIcon(i))}}),L.Marker.include({refreshIconOptions:function(e,t){var i=this.options.icon;return L.setOptions(i,e),this.setIcon(i),t&&this.__parent&&this.__parent._group.refreshClusters(this),this}}),e.MarkerClusterGroup=t,e.MarkerCluster=i}); +//# sourceMappingURL=leaflet.markercluster.js.map \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/vendor/leaflet.markercluster/leaflet.markercluster.js.map b/deploy/grafana-map-plugin/dist/vendor/leaflet.markercluster/leaflet.markercluster.js.map new file mode 100755 index 0000000..a4b459c --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/leaflet.markercluster/leaflet.markercluster.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/MarkerClusterGroup.js","../src/MarkerCluster.js","../src/MarkerOpacity.js","../src/DistanceGrid.js","../src/MarkerCluster.QuickHull.js","../src/MarkerCluster.Spiderfier.js","../src/MarkerClusterGroup.Refresh.js"],"names":[],"mappings":"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","file":"dist/leaflet.markercluster.js"} \ No newline at end of file diff --git a/deploy/grafana-map-plugin/dist/vendor/leaflet/images/layers-2x.png b/deploy/grafana-map-plugin/dist/vendor/leaflet/images/layers-2x.png new file mode 100755 index 0000000..200c333 Binary files /dev/null and b/deploy/grafana-map-plugin/dist/vendor/leaflet/images/layers-2x.png differ diff --git a/deploy/grafana-map-plugin/dist/vendor/leaflet/images/layers.png b/deploy/grafana-map-plugin/dist/vendor/leaflet/images/layers.png new file mode 100755 index 0000000..1a72e57 Binary files /dev/null and b/deploy/grafana-map-plugin/dist/vendor/leaflet/images/layers.png differ diff --git a/deploy/grafana-map-plugin/dist/vendor/leaflet/images/marker-icon-2x.png b/deploy/grafana-map-plugin/dist/vendor/leaflet/images/marker-icon-2x.png new file mode 100755 index 0000000..88f9e50 Binary files /dev/null and b/deploy/grafana-map-plugin/dist/vendor/leaflet/images/marker-icon-2x.png differ diff --git a/deploy/grafana-map-plugin/dist/vendor/leaflet/images/marker-icon.png b/deploy/grafana-map-plugin/dist/vendor/leaflet/images/marker-icon.png new file mode 100755 index 0000000..950edf2 Binary files /dev/null and b/deploy/grafana-map-plugin/dist/vendor/leaflet/images/marker-icon.png differ diff --git a/deploy/grafana-map-plugin/dist/vendor/leaflet/images/marker-shadow.png b/deploy/grafana-map-plugin/dist/vendor/leaflet/images/marker-shadow.png new file mode 100755 index 0000000..9fd2979 Binary files /dev/null and b/deploy/grafana-map-plugin/dist/vendor/leaflet/images/marker-shadow.png differ diff --git a/deploy/grafana-map-plugin/dist/vendor/leaflet/leaflet-src.esm.js b/deploy/grafana-map-plugin/dist/vendor/leaflet/leaflet-src.esm.js new file mode 100755 index 0000000..819a257 --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/leaflet/leaflet-src.esm.js @@ -0,0 +1,13986 @@ +/* @preserve + * Leaflet 1.6.0, a JS library for interactive maps. http://leafletjs.com + * (c) 2010-2019 Vladimir Agafonkin, (c) 2010-2011 CloudMade + */ + +var version = "1.6.0"; + +/* + * @namespace Util + * + * Various utility functions, used by Leaflet internally. + */ + +var freeze = Object.freeze; +Object.freeze = function (obj) { return obj; }; + +// @function extend(dest: Object, src?: Object): Object +// Merges the properties of the `src` object (or multiple objects) into `dest` object and returns the latter. Has an `L.extend` shortcut. +function extend(dest) { + var i, j, len, src; + + for (j = 1, len = arguments.length; j < len; j++) { + src = arguments[j]; + for (i in src) { + dest[i] = src[i]; + } + } + return dest; +} + +// @function create(proto: Object, properties?: Object): Object +// Compatibility polyfill for [Object.create](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/create) +var create = Object.create || (function () { + function F() {} + return function (proto) { + F.prototype = proto; + return new F(); + }; +})(); + +// @function bind(fn: Function, …): Function +// Returns a new function bound to the arguments passed, like [Function.prototype.bind](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Function/bind). +// Has a `L.bind()` shortcut. +function bind(fn, obj) { + var slice = Array.prototype.slice; + + if (fn.bind) { + return fn.bind.apply(fn, slice.call(arguments, 1)); + } + + var args = slice.call(arguments, 2); + + return function () { + return fn.apply(obj, args.length ? args.concat(slice.call(arguments)) : arguments); + }; +} + +// @property lastId: Number +// Last unique ID used by [`stamp()`](#util-stamp) +var lastId = 0; + +// @function stamp(obj: Object): Number +// Returns the unique ID of an object, assigning it one if it doesn't have it. +function stamp(obj) { + /*eslint-disable */ + obj._leaflet_id = obj._leaflet_id || ++lastId; + return obj._leaflet_id; + /* eslint-enable */ +} + +// @function throttle(fn: Function, time: Number, context: Object): Function +// Returns a function which executes function `fn` with the given scope `context` +// (so that the `this` keyword refers to `context` inside `fn`'s code). The function +// `fn` will be called no more than one time per given amount of `time`. The arguments +// received by the bound function will be any arguments passed when binding the +// function, followed by any arguments passed when invoking the bound function. +// Has an `L.throttle` shortcut. +function throttle(fn, time, context) { + var lock, args, wrapperFn, later; + + later = function () { + // reset lock and call if queued + lock = false; + if (args) { + wrapperFn.apply(context, args); + args = false; + } + }; + + wrapperFn = function () { + if (lock) { + // called too soon, queue to call later + args = arguments; + + } else { + // call and lock until later + fn.apply(context, arguments); + setTimeout(later, time); + lock = true; + } + }; + + return wrapperFn; +} + +// @function wrapNum(num: Number, range: Number[], includeMax?: Boolean): Number +// Returns the number `num` modulo `range` in such a way so it lies within +// `range[0]` and `range[1]`. The returned value will be always smaller than +// `range[1]` unless `includeMax` is set to `true`. +function wrapNum(x, range, includeMax) { + var max = range[1], + min = range[0], + d = max - min; + return x === max && includeMax ? x : ((x - min) % d + d) % d + min; +} + +// @function falseFn(): Function +// Returns a function which always returns `false`. +function falseFn() { return false; } + +// @function formatNum(num: Number, digits?: Number): Number +// Returns the number `num` rounded to `digits` decimals, or to 6 decimals by default. +function formatNum(num, digits) { + var pow = Math.pow(10, (digits === undefined ? 6 : digits)); + return Math.round(num * pow) / pow; +} + +// @function trim(str: String): String +// Compatibility polyfill for [String.prototype.trim](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/Trim) +function trim(str) { + return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, ''); +} + +// @function splitWords(str: String): String[] +// Trims and splits the string on whitespace and returns the array of parts. +function splitWords(str) { + return trim(str).split(/\s+/); +} + +// @function setOptions(obj: Object, options: Object): Object +// Merges the given properties to the `options` of the `obj` object, returning the resulting options. See `Class options`. Has an `L.setOptions` shortcut. +function setOptions(obj, options) { + if (!obj.hasOwnProperty('options')) { + obj.options = obj.options ? create(obj.options) : {}; + } + for (var i in options) { + obj.options[i] = options[i]; + } + return obj.options; +} + +// @function getParamString(obj: Object, existingUrl?: String, uppercase?: Boolean): String +// Converts an object into a parameter URL string, e.g. `{a: "foo", b: "bar"}` +// translates to `'?a=foo&b=bar'`. If `existingUrl` is set, the parameters will +// be appended at the end. If `uppercase` is `true`, the parameter names will +// be uppercased (e.g. `'?A=foo&B=bar'`) +function getParamString(obj, existingUrl, uppercase) { + var params = []; + for (var i in obj) { + params.push(encodeURIComponent(uppercase ? i.toUpperCase() : i) + '=' + encodeURIComponent(obj[i])); + } + return ((!existingUrl || existingUrl.indexOf('?') === -1) ? '?' : '&') + params.join('&'); +} + +var templateRe = /\{ *([\w_-]+) *\}/g; + +// @function template(str: String, data: Object): String +// Simple templating facility, accepts a template string of the form `'Hello {a}, {b}'` +// and a data object like `{a: 'foo', b: 'bar'}`, returns evaluated string +// `('Hello foo, bar')`. You can also specify functions instead of strings for +// data values — they will be evaluated passing `data` as an argument. +function template(str, data) { + return str.replace(templateRe, function (str, key) { + var value = data[key]; + + if (value === undefined) { + throw new Error('No value provided for variable ' + str); + + } else if (typeof value === 'function') { + value = value(data); + } + return value; + }); +} + +// @function isArray(obj): Boolean +// Compatibility polyfill for [Array.isArray](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray) +var isArray = Array.isArray || function (obj) { + return (Object.prototype.toString.call(obj) === '[object Array]'); +}; + +// @function indexOf(array: Array, el: Object): Number +// Compatibility polyfill for [Array.prototype.indexOf](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf) +function indexOf(array, el) { + for (var i = 0; i < array.length; i++) { + if (array[i] === el) { return i; } + } + return -1; +} + +// @property emptyImageUrl: String +// Data URI string containing a base64-encoded empty GIF image. +// Used as a hack to free memory from unused images on WebKit-powered +// mobile devices (by setting image `src` to this string). +var emptyImageUrl = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs='; + +// inspired by http://paulirish.com/2011/requestanimationframe-for-smart-animating/ + +function getPrefixed(name) { + return window['webkit' + name] || window['moz' + name] || window['ms' + name]; +} + +var lastTime = 0; + +// fallback for IE 7-8 +function timeoutDefer(fn) { + var time = +new Date(), + timeToCall = Math.max(0, 16 - (time - lastTime)); + + lastTime = time + timeToCall; + return window.setTimeout(fn, timeToCall); +} + +var requestFn = window.requestAnimationFrame || getPrefixed('RequestAnimationFrame') || timeoutDefer; +var cancelFn = window.cancelAnimationFrame || getPrefixed('CancelAnimationFrame') || + getPrefixed('CancelRequestAnimationFrame') || function (id) { window.clearTimeout(id); }; + +// @function requestAnimFrame(fn: Function, context?: Object, immediate?: Boolean): Number +// Schedules `fn` to be executed when the browser repaints. `fn` is bound to +// `context` if given. When `immediate` is set, `fn` is called immediately if +// the browser doesn't have native support for +// [`window.requestAnimationFrame`](https://developer.mozilla.org/docs/Web/API/window/requestAnimationFrame), +// otherwise it's delayed. Returns a request ID that can be used to cancel the request. +function requestAnimFrame(fn, context, immediate) { + if (immediate && requestFn === timeoutDefer) { + fn.call(context); + } else { + return requestFn.call(window, bind(fn, context)); + } +} + +// @function cancelAnimFrame(id: Number): undefined +// Cancels a previous `requestAnimFrame`. See also [window.cancelAnimationFrame](https://developer.mozilla.org/docs/Web/API/window/cancelAnimationFrame). +function cancelAnimFrame(id) { + if (id) { + cancelFn.call(window, id); + } +} + + +var Util = (Object.freeze || Object)({ + freeze: freeze, + extend: extend, + create: create, + bind: bind, + lastId: lastId, + stamp: stamp, + throttle: throttle, + wrapNum: wrapNum, + falseFn: falseFn, + formatNum: formatNum, + trim: trim, + splitWords: splitWords, + setOptions: setOptions, + getParamString: getParamString, + template: template, + isArray: isArray, + indexOf: indexOf, + emptyImageUrl: emptyImageUrl, + requestFn: requestFn, + cancelFn: cancelFn, + requestAnimFrame: requestAnimFrame, + cancelAnimFrame: cancelAnimFrame +}); + +// @class Class +// @aka L.Class + +// @section +// @uninheritable + +// Thanks to John Resig and Dean Edwards for inspiration! + +function Class() {} + +Class.extend = function (props) { + + // @function extend(props: Object): Function + // [Extends the current class](#class-inheritance) given the properties to be included. + // Returns a Javascript function that is a class constructor (to be called with `new`). + var NewClass = function () { + + // call the constructor + if (this.initialize) { + this.initialize.apply(this, arguments); + } + + // call all constructor hooks + this.callInitHooks(); + }; + + var parentProto = NewClass.__super__ = this.prototype; + + var proto = create(parentProto); + proto.constructor = NewClass; + + NewClass.prototype = proto; + + // inherit parent's statics + for (var i in this) { + if (this.hasOwnProperty(i) && i !== 'prototype' && i !== '__super__') { + NewClass[i] = this[i]; + } + } + + // mix static properties into the class + if (props.statics) { + extend(NewClass, props.statics); + delete props.statics; + } + + // mix includes into the prototype + if (props.includes) { + checkDeprecatedMixinEvents(props.includes); + extend.apply(null, [proto].concat(props.includes)); + delete props.includes; + } + + // merge options + if (proto.options) { + props.options = extend(create(proto.options), props.options); + } + + // mix given properties into the prototype + extend(proto, props); + + proto._initHooks = []; + + // add method for calling all hooks + proto.callInitHooks = function () { + + if (this._initHooksCalled) { return; } + + if (parentProto.callInitHooks) { + parentProto.callInitHooks.call(this); + } + + this._initHooksCalled = true; + + for (var i = 0, len = proto._initHooks.length; i < len; i++) { + proto._initHooks[i].call(this); + } + }; + + return NewClass; +}; + + +// @function include(properties: Object): this +// [Includes a mixin](#class-includes) into the current class. +Class.include = function (props) { + extend(this.prototype, props); + return this; +}; + +// @function mergeOptions(options: Object): this +// [Merges `options`](#class-options) into the defaults of the class. +Class.mergeOptions = function (options) { + extend(this.prototype.options, options); + return this; +}; + +// @function addInitHook(fn: Function): this +// Adds a [constructor hook](#class-constructor-hooks) to the class. +Class.addInitHook = function (fn) { // (Function) || (String, args...) + var args = Array.prototype.slice.call(arguments, 1); + + var init = typeof fn === 'function' ? fn : function () { + this[fn].apply(this, args); + }; + + this.prototype._initHooks = this.prototype._initHooks || []; + this.prototype._initHooks.push(init); + return this; +}; + +function checkDeprecatedMixinEvents(includes) { + if (typeof L === 'undefined' || !L || !L.Mixin) { return; } + + includes = isArray(includes) ? includes : [includes]; + + for (var i = 0; i < includes.length; i++) { + if (includes[i] === L.Mixin.Events) { + console.warn('Deprecated include of L.Mixin.Events: ' + + 'this property will be removed in future releases, ' + + 'please inherit from L.Evented instead.', new Error().stack); + } + } +} + +/* + * @class Evented + * @aka L.Evented + * @inherits Class + * + * A set of methods shared between event-powered classes (like `Map` and `Marker`). Generally, events allow you to execute some function when something happens with an object (e.g. the user clicks on the map, causing the map to fire `'click'` event). + * + * @example + * + * ```js + * map.on('click', function(e) { + * alert(e.latlng); + * } ); + * ``` + * + * Leaflet deals with event listeners by reference, so if you want to add a listener and then remove it, define it as a function: + * + * ```js + * function onClick(e) { ... } + * + * map.on('click', onClick); + * map.off('click', onClick); + * ``` + */ + +var Events = { + /* @method on(type: String, fn: Function, context?: Object): this + * Adds a listener function (`fn`) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. `'click dblclick'`). + * + * @alternative + * @method on(eventMap: Object): this + * Adds a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}` + */ + on: function (types, fn, context) { + + // types can be a map of types/handlers + if (typeof types === 'object') { + for (var type in types) { + // we don't process space-separated events here for performance; + // it's a hot path since Layer uses the on(obj) syntax + this._on(type, types[type], fn); + } + + } else { + // types can be a string of space-separated words + types = splitWords(types); + + for (var i = 0, len = types.length; i < len; i++) { + this._on(types[i], fn, context); + } + } + + return this; + }, + + /* @method off(type: String, fn?: Function, context?: Object): this + * Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to `on`, you must pass the same context to `off` in order to remove the listener. + * + * @alternative + * @method off(eventMap: Object): this + * Removes a set of type/listener pairs. + * + * @alternative + * @method off: this + * Removes all listeners to all events on the object. This includes implicitly attached events. + */ + off: function (types, fn, context) { + + if (!types) { + // clear all listeners if called without arguments + delete this._events; + + } else if (typeof types === 'object') { + for (var type in types) { + this._off(type, types[type], fn); + } + + } else { + types = splitWords(types); + + for (var i = 0, len = types.length; i < len; i++) { + this._off(types[i], fn, context); + } + } + + return this; + }, + + // attach listener (without syntactic sugar now) + _on: function (type, fn, context) { + this._events = this._events || {}; + + /* get/init listeners for type */ + var typeListeners = this._events[type]; + if (!typeListeners) { + typeListeners = []; + this._events[type] = typeListeners; + } + + if (context === this) { + // Less memory footprint. + context = undefined; + } + var newListener = {fn: fn, ctx: context}, + listeners = typeListeners; + + // check if fn already there + for (var i = 0, len = listeners.length; i < len; i++) { + if (listeners[i].fn === fn && listeners[i].ctx === context) { + return; + } + } + + listeners.push(newListener); + }, + + _off: function (type, fn, context) { + var listeners, + i, + len; + + if (!this._events) { return; } + + listeners = this._events[type]; + + if (!listeners) { + return; + } + + if (!fn) { + // Set all removed listeners to noop so they are not called if remove happens in fire + for (i = 0, len = listeners.length; i < len; i++) { + listeners[i].fn = falseFn; + } + // clear all listeners for a type if function isn't specified + delete this._events[type]; + return; + } + + if (context === this) { + context = undefined; + } + + if (listeners) { + + // find fn and remove it + for (i = 0, len = listeners.length; i < len; i++) { + var l = listeners[i]; + if (l.ctx !== context) { continue; } + if (l.fn === fn) { + + // set the removed listener to noop so that's not called if remove happens in fire + l.fn = falseFn; + + if (this._firingCount) { + /* copy array in case events are being fired */ + this._events[type] = listeners = listeners.slice(); + } + listeners.splice(i, 1); + + return; + } + } + } + }, + + // @method fire(type: String, data?: Object, propagate?: Boolean): this + // Fires an event of the specified type. You can optionally provide an data + // object — the first argument of the listener function will contain its + // properties. The event can optionally be propagated to event parents. + fire: function (type, data, propagate) { + if (!this.listens(type, propagate)) { return this; } + + var event = extend({}, data, { + type: type, + target: this, + sourceTarget: data && data.sourceTarget || this + }); + + if (this._events) { + var listeners = this._events[type]; + + if (listeners) { + this._firingCount = (this._firingCount + 1) || 1; + for (var i = 0, len = listeners.length; i < len; i++) { + var l = listeners[i]; + l.fn.call(l.ctx || this, event); + } + + this._firingCount--; + } + } + + if (propagate) { + // propagate the event to parents (set with addEventParent) + this._propagateEvent(event); + } + + return this; + }, + + // @method listens(type: String): Boolean + // Returns `true` if a particular event type has any listeners attached to it. + listens: function (type, propagate) { + var listeners = this._events && this._events[type]; + if (listeners && listeners.length) { return true; } + + if (propagate) { + // also check parents for listeners if event propagates + for (var id in this._eventParents) { + if (this._eventParents[id].listens(type, propagate)) { return true; } + } + } + return false; + }, + + // @method once(…): this + // Behaves as [`on(…)`](#evented-on), except the listener will only get fired once and then removed. + once: function (types, fn, context) { + + if (typeof types === 'object') { + for (var type in types) { + this.once(type, types[type], fn); + } + return this; + } + + var handler = bind(function () { + this + .off(types, fn, context) + .off(types, handler, context); + }, this); + + // add a listener that's executed once and removed after that + return this + .on(types, fn, context) + .on(types, handler, context); + }, + + // @method addEventParent(obj: Evented): this + // Adds an event parent - an `Evented` that will receive propagated events + addEventParent: function (obj) { + this._eventParents = this._eventParents || {}; + this._eventParents[stamp(obj)] = obj; + return this; + }, + + // @method removeEventParent(obj: Evented): this + // Removes an event parent, so it will stop receiving propagated events + removeEventParent: function (obj) { + if (this._eventParents) { + delete this._eventParents[stamp(obj)]; + } + return this; + }, + + _propagateEvent: function (e) { + for (var id in this._eventParents) { + this._eventParents[id].fire(e.type, extend({ + layer: e.target, + propagatedFrom: e.target + }, e), true); + } + } +}; + +// aliases; we should ditch those eventually + +// @method addEventListener(…): this +// Alias to [`on(…)`](#evented-on) +Events.addEventListener = Events.on; + +// @method removeEventListener(…): this +// Alias to [`off(…)`](#evented-off) + +// @method clearAllEventListeners(…): this +// Alias to [`off()`](#evented-off) +Events.removeEventListener = Events.clearAllEventListeners = Events.off; + +// @method addOneTimeEventListener(…): this +// Alias to [`once(…)`](#evented-once) +Events.addOneTimeEventListener = Events.once; + +// @method fireEvent(…): this +// Alias to [`fire(…)`](#evented-fire) +Events.fireEvent = Events.fire; + +// @method hasEventListeners(…): Boolean +// Alias to [`listens(…)`](#evented-listens) +Events.hasEventListeners = Events.listens; + +var Evented = Class.extend(Events); + +/* + * @class Point + * @aka L.Point + * + * Represents a point with `x` and `y` coordinates in pixels. + * + * @example + * + * ```js + * var point = L.point(200, 300); + * ``` + * + * All Leaflet methods and options that accept `Point` objects also accept them in a simple Array form (unless noted otherwise), so these lines are equivalent: + * + * ```js + * map.panBy([200, 300]); + * map.panBy(L.point(200, 300)); + * ``` + * + * Note that `Point` does not inherit from Leafet's `Class` object, + * which means new classes can't inherit from it, and new methods + * can't be added to it with the `include` function. + */ + +function Point(x, y, round) { + // @property x: Number; The `x` coordinate of the point + this.x = (round ? Math.round(x) : x); + // @property y: Number; The `y` coordinate of the point + this.y = (round ? Math.round(y) : y); +} + +var trunc = Math.trunc || function (v) { + return v > 0 ? Math.floor(v) : Math.ceil(v); +}; + +Point.prototype = { + + // @method clone(): Point + // Returns a copy of the current point. + clone: function () { + return new Point(this.x, this.y); + }, + + // @method add(otherPoint: Point): Point + // Returns the result of addition of the current and the given points. + add: function (point) { + // non-destructive, returns a new point + return this.clone()._add(toPoint(point)); + }, + + _add: function (point) { + // destructive, used directly for performance in situations where it's safe to modify existing point + this.x += point.x; + this.y += point.y; + return this; + }, + + // @method subtract(otherPoint: Point): Point + // Returns the result of subtraction of the given point from the current. + subtract: function (point) { + return this.clone()._subtract(toPoint(point)); + }, + + _subtract: function (point) { + this.x -= point.x; + this.y -= point.y; + return this; + }, + + // @method divideBy(num: Number): Point + // Returns the result of division of the current point by the given number. + divideBy: function (num) { + return this.clone()._divideBy(num); + }, + + _divideBy: function (num) { + this.x /= num; + this.y /= num; + return this; + }, + + // @method multiplyBy(num: Number): Point + // Returns the result of multiplication of the current point by the given number. + multiplyBy: function (num) { + return this.clone()._multiplyBy(num); + }, + + _multiplyBy: function (num) { + this.x *= num; + this.y *= num; + return this; + }, + + // @method scaleBy(scale: Point): Point + // Multiply each coordinate of the current point by each coordinate of + // `scale`. In linear algebra terms, multiply the point by the + // [scaling matrix](https://en.wikipedia.org/wiki/Scaling_%28geometry%29#Matrix_representation) + // defined by `scale`. + scaleBy: function (point) { + return new Point(this.x * point.x, this.y * point.y); + }, + + // @method unscaleBy(scale: Point): Point + // Inverse of `scaleBy`. Divide each coordinate of the current point by + // each coordinate of `scale`. + unscaleBy: function (point) { + return new Point(this.x / point.x, this.y / point.y); + }, + + // @method round(): Point + // Returns a copy of the current point with rounded coordinates. + round: function () { + return this.clone()._round(); + }, + + _round: function () { + this.x = Math.round(this.x); + this.y = Math.round(this.y); + return this; + }, + + // @method floor(): Point + // Returns a copy of the current point with floored coordinates (rounded down). + floor: function () { + return this.clone()._floor(); + }, + + _floor: function () { + this.x = Math.floor(this.x); + this.y = Math.floor(this.y); + return this; + }, + + // @method ceil(): Point + // Returns a copy of the current point with ceiled coordinates (rounded up). + ceil: function () { + return this.clone()._ceil(); + }, + + _ceil: function () { + this.x = Math.ceil(this.x); + this.y = Math.ceil(this.y); + return this; + }, + + // @method trunc(): Point + // Returns a copy of the current point with truncated coordinates (rounded towards zero). + trunc: function () { + return this.clone()._trunc(); + }, + + _trunc: function () { + this.x = trunc(this.x); + this.y = trunc(this.y); + return this; + }, + + // @method distanceTo(otherPoint: Point): Number + // Returns the cartesian distance between the current and the given points. + distanceTo: function (point) { + point = toPoint(point); + + var x = point.x - this.x, + y = point.y - this.y; + + return Math.sqrt(x * x + y * y); + }, + + // @method equals(otherPoint: Point): Boolean + // Returns `true` if the given point has the same coordinates. + equals: function (point) { + point = toPoint(point); + + return point.x === this.x && + point.y === this.y; + }, + + // @method contains(otherPoint: Point): Boolean + // Returns `true` if both coordinates of the given point are less than the corresponding current point coordinates (in absolute values). + contains: function (point) { + point = toPoint(point); + + return Math.abs(point.x) <= Math.abs(this.x) && + Math.abs(point.y) <= Math.abs(this.y); + }, + + // @method toString(): String + // Returns a string representation of the point for debugging purposes. + toString: function () { + return 'Point(' + + formatNum(this.x) + ', ' + + formatNum(this.y) + ')'; + } +}; + +// @factory L.point(x: Number, y: Number, round?: Boolean) +// Creates a Point object with the given `x` and `y` coordinates. If optional `round` is set to true, rounds the `x` and `y` values. + +// @alternative +// @factory L.point(coords: Number[]) +// Expects an array of the form `[x, y]` instead. + +// @alternative +// @factory L.point(coords: Object) +// Expects a plain object of the form `{x: Number, y: Number}` instead. +function toPoint(x, y, round) { + if (x instanceof Point) { + return x; + } + if (isArray(x)) { + return new Point(x[0], x[1]); + } + if (x === undefined || x === null) { + return x; + } + if (typeof x === 'object' && 'x' in x && 'y' in x) { + return new Point(x.x, x.y); + } + return new Point(x, y, round); +} + +/* + * @class Bounds + * @aka L.Bounds + * + * Represents a rectangular area in pixel coordinates. + * + * @example + * + * ```js + * var p1 = L.point(10, 10), + * p2 = L.point(40, 60), + * bounds = L.bounds(p1, p2); + * ``` + * + * All Leaflet methods that accept `Bounds` objects also accept them in a simple Array form (unless noted otherwise), so the bounds example above can be passed like this: + * + * ```js + * otherBounds.intersects([[10, 10], [40, 60]]); + * ``` + * + * Note that `Bounds` does not inherit from Leafet's `Class` object, + * which means new classes can't inherit from it, and new methods + * can't be added to it with the `include` function. + */ + +function Bounds(a, b) { + if (!a) { return; } + + var points = b ? [a, b] : a; + + for (var i = 0, len = points.length; i < len; i++) { + this.extend(points[i]); + } +} + +Bounds.prototype = { + // @method extend(point: Point): this + // Extends the bounds to contain the given point. + extend: function (point) { // (Point) + point = toPoint(point); + + // @property min: Point + // The top left corner of the rectangle. + // @property max: Point + // The bottom right corner of the rectangle. + if (!this.min && !this.max) { + this.min = point.clone(); + this.max = point.clone(); + } else { + this.min.x = Math.min(point.x, this.min.x); + this.max.x = Math.max(point.x, this.max.x); + this.min.y = Math.min(point.y, this.min.y); + this.max.y = Math.max(point.y, this.max.y); + } + return this; + }, + + // @method getCenter(round?: Boolean): Point + // Returns the center point of the bounds. + getCenter: function (round) { + return new Point( + (this.min.x + this.max.x) / 2, + (this.min.y + this.max.y) / 2, round); + }, + + // @method getBottomLeft(): Point + // Returns the bottom-left point of the bounds. + getBottomLeft: function () { + return new Point(this.min.x, this.max.y); + }, + + // @method getTopRight(): Point + // Returns the top-right point of the bounds. + getTopRight: function () { // -> Point + return new Point(this.max.x, this.min.y); + }, + + // @method getTopLeft(): Point + // Returns the top-left point of the bounds (i.e. [`this.min`](#bounds-min)). + getTopLeft: function () { + return this.min; // left, top + }, + + // @method getBottomRight(): Point + // Returns the bottom-right point of the bounds (i.e. [`this.max`](#bounds-max)). + getBottomRight: function () { + return this.max; // right, bottom + }, + + // @method getSize(): Point + // Returns the size of the given bounds + getSize: function () { + return this.max.subtract(this.min); + }, + + // @method contains(otherBounds: Bounds): Boolean + // Returns `true` if the rectangle contains the given one. + // @alternative + // @method contains(point: Point): Boolean + // Returns `true` if the rectangle contains the given point. + contains: function (obj) { + var min, max; + + if (typeof obj[0] === 'number' || obj instanceof Point) { + obj = toPoint(obj); + } else { + obj = toBounds(obj); + } + + if (obj instanceof Bounds) { + min = obj.min; + max = obj.max; + } else { + min = max = obj; + } + + return (min.x >= this.min.x) && + (max.x <= this.max.x) && + (min.y >= this.min.y) && + (max.y <= this.max.y); + }, + + // @method intersects(otherBounds: Bounds): Boolean + // Returns `true` if the rectangle intersects the given bounds. Two bounds + // intersect if they have at least one point in common. + intersects: function (bounds) { // (Bounds) -> Boolean + bounds = toBounds(bounds); + + var min = this.min, + max = this.max, + min2 = bounds.min, + max2 = bounds.max, + xIntersects = (max2.x >= min.x) && (min2.x <= max.x), + yIntersects = (max2.y >= min.y) && (min2.y <= max.y); + + return xIntersects && yIntersects; + }, + + // @method overlaps(otherBounds: Bounds): Boolean + // Returns `true` if the rectangle overlaps the given bounds. Two bounds + // overlap if their intersection is an area. + overlaps: function (bounds) { // (Bounds) -> Boolean + bounds = toBounds(bounds); + + var min = this.min, + max = this.max, + min2 = bounds.min, + max2 = bounds.max, + xOverlaps = (max2.x > min.x) && (min2.x < max.x), + yOverlaps = (max2.y > min.y) && (min2.y < max.y); + + return xOverlaps && yOverlaps; + }, + + isValid: function () { + return !!(this.min && this.max); + } +}; + + +// @factory L.bounds(corner1: Point, corner2: Point) +// Creates a Bounds object from two corners coordinate pairs. +// @alternative +// @factory L.bounds(points: Point[]) +// Creates a Bounds object from the given array of points. +function toBounds(a, b) { + if (!a || a instanceof Bounds) { + return a; + } + return new Bounds(a, b); +} + +/* + * @class LatLngBounds + * @aka L.LatLngBounds + * + * Represents a rectangular geographical area on a map. + * + * @example + * + * ```js + * var corner1 = L.latLng(40.712, -74.227), + * corner2 = L.latLng(40.774, -74.125), + * bounds = L.latLngBounds(corner1, corner2); + * ``` + * + * All Leaflet methods that accept LatLngBounds objects also accept them in a simple Array form (unless noted otherwise), so the bounds example above can be passed like this: + * + * ```js + * map.fitBounds([ + * [40.712, -74.227], + * [40.774, -74.125] + * ]); + * ``` + * + * Caution: if the area crosses the antimeridian (often confused with the International Date Line), you must specify corners _outside_ the [-180, 180] degrees longitude range. + * + * Note that `LatLngBounds` does not inherit from Leafet's `Class` object, + * which means new classes can't inherit from it, and new methods + * can't be added to it with the `include` function. + */ + +function LatLngBounds(corner1, corner2) { // (LatLng, LatLng) or (LatLng[]) + if (!corner1) { return; } + + var latlngs = corner2 ? [corner1, corner2] : corner1; + + for (var i = 0, len = latlngs.length; i < len; i++) { + this.extend(latlngs[i]); + } +} + +LatLngBounds.prototype = { + + // @method extend(latlng: LatLng): this + // Extend the bounds to contain the given point + + // @alternative + // @method extend(otherBounds: LatLngBounds): this + // Extend the bounds to contain the given bounds + extend: function (obj) { + var sw = this._southWest, + ne = this._northEast, + sw2, ne2; + + if (obj instanceof LatLng) { + sw2 = obj; + ne2 = obj; + + } else if (obj instanceof LatLngBounds) { + sw2 = obj._southWest; + ne2 = obj._northEast; + + if (!sw2 || !ne2) { return this; } + + } else { + return obj ? this.extend(toLatLng(obj) || toLatLngBounds(obj)) : this; + } + + if (!sw && !ne) { + this._southWest = new LatLng(sw2.lat, sw2.lng); + this._northEast = new LatLng(ne2.lat, ne2.lng); + } else { + sw.lat = Math.min(sw2.lat, sw.lat); + sw.lng = Math.min(sw2.lng, sw.lng); + ne.lat = Math.max(ne2.lat, ne.lat); + ne.lng = Math.max(ne2.lng, ne.lng); + } + + return this; + }, + + // @method pad(bufferRatio: Number): LatLngBounds + // Returns bounds created by extending or retracting the current bounds by a given ratio in each direction. + // For example, a ratio of 0.5 extends the bounds by 50% in each direction. + // Negative values will retract the bounds. + pad: function (bufferRatio) { + var sw = this._southWest, + ne = this._northEast, + heightBuffer = Math.abs(sw.lat - ne.lat) * bufferRatio, + widthBuffer = Math.abs(sw.lng - ne.lng) * bufferRatio; + + return new LatLngBounds( + new LatLng(sw.lat - heightBuffer, sw.lng - widthBuffer), + new LatLng(ne.lat + heightBuffer, ne.lng + widthBuffer)); + }, + + // @method getCenter(): LatLng + // Returns the center point of the bounds. + getCenter: function () { + return new LatLng( + (this._southWest.lat + this._northEast.lat) / 2, + (this._southWest.lng + this._northEast.lng) / 2); + }, + + // @method getSouthWest(): LatLng + // Returns the south-west point of the bounds. + getSouthWest: function () { + return this._southWest; + }, + + // @method getNorthEast(): LatLng + // Returns the north-east point of the bounds. + getNorthEast: function () { + return this._northEast; + }, + + // @method getNorthWest(): LatLng + // Returns the north-west point of the bounds. + getNorthWest: function () { + return new LatLng(this.getNorth(), this.getWest()); + }, + + // @method getSouthEast(): LatLng + // Returns the south-east point of the bounds. + getSouthEast: function () { + return new LatLng(this.getSouth(), this.getEast()); + }, + + // @method getWest(): Number + // Returns the west longitude of the bounds + getWest: function () { + return this._southWest.lng; + }, + + // @method getSouth(): Number + // Returns the south latitude of the bounds + getSouth: function () { + return this._southWest.lat; + }, + + // @method getEast(): Number + // Returns the east longitude of the bounds + getEast: function () { + return this._northEast.lng; + }, + + // @method getNorth(): Number + // Returns the north latitude of the bounds + getNorth: function () { + return this._northEast.lat; + }, + + // @method contains(otherBounds: LatLngBounds): Boolean + // Returns `true` if the rectangle contains the given one. + + // @alternative + // @method contains (latlng: LatLng): Boolean + // Returns `true` if the rectangle contains the given point. + contains: function (obj) { // (LatLngBounds) or (LatLng) -> Boolean + if (typeof obj[0] === 'number' || obj instanceof LatLng || 'lat' in obj) { + obj = toLatLng(obj); + } else { + obj = toLatLngBounds(obj); + } + + var sw = this._southWest, + ne = this._northEast, + sw2, ne2; + + if (obj instanceof LatLngBounds) { + sw2 = obj.getSouthWest(); + ne2 = obj.getNorthEast(); + } else { + sw2 = ne2 = obj; + } + + return (sw2.lat >= sw.lat) && (ne2.lat <= ne.lat) && + (sw2.lng >= sw.lng) && (ne2.lng <= ne.lng); + }, + + // @method intersects(otherBounds: LatLngBounds): Boolean + // Returns `true` if the rectangle intersects the given bounds. Two bounds intersect if they have at least one point in common. + intersects: function (bounds) { + bounds = toLatLngBounds(bounds); + + var sw = this._southWest, + ne = this._northEast, + sw2 = bounds.getSouthWest(), + ne2 = bounds.getNorthEast(), + + latIntersects = (ne2.lat >= sw.lat) && (sw2.lat <= ne.lat), + lngIntersects = (ne2.lng >= sw.lng) && (sw2.lng <= ne.lng); + + return latIntersects && lngIntersects; + }, + + // @method overlaps(otherBounds: Bounds): Boolean + // Returns `true` if the rectangle overlaps the given bounds. Two bounds overlap if their intersection is an area. + overlaps: function (bounds) { + bounds = toLatLngBounds(bounds); + + var sw = this._southWest, + ne = this._northEast, + sw2 = bounds.getSouthWest(), + ne2 = bounds.getNorthEast(), + + latOverlaps = (ne2.lat > sw.lat) && (sw2.lat < ne.lat), + lngOverlaps = (ne2.lng > sw.lng) && (sw2.lng < ne.lng); + + return latOverlaps && lngOverlaps; + }, + + // @method toBBoxString(): String + // Returns a string with bounding box coordinates in a 'southwest_lng,southwest_lat,northeast_lng,northeast_lat' format. Useful for sending requests to web services that return geo data. + toBBoxString: function () { + return [this.getWest(), this.getSouth(), this.getEast(), this.getNorth()].join(','); + }, + + // @method equals(otherBounds: LatLngBounds, maxMargin?: Number): Boolean + // Returns `true` if the rectangle is equivalent (within a small margin of error) to the given bounds. The margin of error can be overridden by setting `maxMargin` to a small number. + equals: function (bounds, maxMargin) { + if (!bounds) { return false; } + + bounds = toLatLngBounds(bounds); + + return this._southWest.equals(bounds.getSouthWest(), maxMargin) && + this._northEast.equals(bounds.getNorthEast(), maxMargin); + }, + + // @method isValid(): Boolean + // Returns `true` if the bounds are properly initialized. + isValid: function () { + return !!(this._southWest && this._northEast); + } +}; + +// TODO International date line? + +// @factory L.latLngBounds(corner1: LatLng, corner2: LatLng) +// Creates a `LatLngBounds` object by defining two diagonally opposite corners of the rectangle. + +// @alternative +// @factory L.latLngBounds(latlngs: LatLng[]) +// Creates a `LatLngBounds` object defined by the geographical points it contains. Very useful for zooming the map to fit a particular set of locations with [`fitBounds`](#map-fitbounds). +function toLatLngBounds(a, b) { + if (a instanceof LatLngBounds) { + return a; + } + return new LatLngBounds(a, b); +} + +/* @class LatLng + * @aka L.LatLng + * + * Represents a geographical point with a certain latitude and longitude. + * + * @example + * + * ``` + * var latlng = L.latLng(50.5, 30.5); + * ``` + * + * All Leaflet methods that accept LatLng objects also accept them in a simple Array form and simple object form (unless noted otherwise), so these lines are equivalent: + * + * ``` + * map.panTo([50, 30]); + * map.panTo({lon: 30, lat: 50}); + * map.panTo({lat: 50, lng: 30}); + * map.panTo(L.latLng(50, 30)); + * ``` + * + * Note that `LatLng` does not inherit from Leaflet's `Class` object, + * which means new classes can't inherit from it, and new methods + * can't be added to it with the `include` function. + */ + +function LatLng(lat, lng, alt) { + if (isNaN(lat) || isNaN(lng)) { + throw new Error('Invalid LatLng object: (' + lat + ', ' + lng + ')'); + } + + // @property lat: Number + // Latitude in degrees + this.lat = +lat; + + // @property lng: Number + // Longitude in degrees + this.lng = +lng; + + // @property alt: Number + // Altitude in meters (optional) + if (alt !== undefined) { + this.alt = +alt; + } +} + +LatLng.prototype = { + // @method equals(otherLatLng: LatLng, maxMargin?: Number): Boolean + // Returns `true` if the given `LatLng` point is at the same position (within a small margin of error). The margin of error can be overridden by setting `maxMargin` to a small number. + equals: function (obj, maxMargin) { + if (!obj) { return false; } + + obj = toLatLng(obj); + + var margin = Math.max( + Math.abs(this.lat - obj.lat), + Math.abs(this.lng - obj.lng)); + + return margin <= (maxMargin === undefined ? 1.0E-9 : maxMargin); + }, + + // @method toString(): String + // Returns a string representation of the point (for debugging purposes). + toString: function (precision) { + return 'LatLng(' + + formatNum(this.lat, precision) + ', ' + + formatNum(this.lng, precision) + ')'; + }, + + // @method distanceTo(otherLatLng: LatLng): Number + // Returns the distance (in meters) to the given `LatLng` calculated using the [Spherical Law of Cosines](https://en.wikipedia.org/wiki/Spherical_law_of_cosines). + distanceTo: function (other) { + return Earth.distance(this, toLatLng(other)); + }, + + // @method wrap(): LatLng + // Returns a new `LatLng` object with the longitude wrapped so it's always between -180 and +180 degrees. + wrap: function () { + return Earth.wrapLatLng(this); + }, + + // @method toBounds(sizeInMeters: Number): LatLngBounds + // Returns a new `LatLngBounds` object in which each boundary is `sizeInMeters/2` meters apart from the `LatLng`. + toBounds: function (sizeInMeters) { + var latAccuracy = 180 * sizeInMeters / 40075017, + lngAccuracy = latAccuracy / Math.cos((Math.PI / 180) * this.lat); + + return toLatLngBounds( + [this.lat - latAccuracy, this.lng - lngAccuracy], + [this.lat + latAccuracy, this.lng + lngAccuracy]); + }, + + clone: function () { + return new LatLng(this.lat, this.lng, this.alt); + } +}; + + + +// @factory L.latLng(latitude: Number, longitude: Number, altitude?: Number): LatLng +// Creates an object representing a geographical point with the given latitude and longitude (and optionally altitude). + +// @alternative +// @factory L.latLng(coords: Array): LatLng +// Expects an array of the form `[Number, Number]` or `[Number, Number, Number]` instead. + +// @alternative +// @factory L.latLng(coords: Object): LatLng +// Expects an plain object of the form `{lat: Number, lng: Number}` or `{lat: Number, lng: Number, alt: Number}` instead. + +function toLatLng(a, b, c) { + if (a instanceof LatLng) { + return a; + } + if (isArray(a) && typeof a[0] !== 'object') { + if (a.length === 3) { + return new LatLng(a[0], a[1], a[2]); + } + if (a.length === 2) { + return new LatLng(a[0], a[1]); + } + return null; + } + if (a === undefined || a === null) { + return a; + } + if (typeof a === 'object' && 'lat' in a) { + return new LatLng(a.lat, 'lng' in a ? a.lng : a.lon, a.alt); + } + if (b === undefined) { + return null; + } + return new LatLng(a, b, c); +} + +/* + * @namespace CRS + * @crs L.CRS.Base + * Object that defines coordinate reference systems for projecting + * geographical points into pixel (screen) coordinates and back (and to + * coordinates in other units for [WMS](https://en.wikipedia.org/wiki/Web_Map_Service) services). See + * [spatial reference system](http://en.wikipedia.org/wiki/Coordinate_reference_system). + * + * Leaflet defines the most usual CRSs by default. If you want to use a + * CRS not defined by default, take a look at the + * [Proj4Leaflet](https://github.com/kartena/Proj4Leaflet) plugin. + * + * Note that the CRS instances do not inherit from Leafet's `Class` object, + * and can't be instantiated. Also, new classes can't inherit from them, + * and methods can't be added to them with the `include` function. + */ + +var CRS = { + // @method latLngToPoint(latlng: LatLng, zoom: Number): Point + // Projects geographical coordinates into pixel coordinates for a given zoom. + latLngToPoint: function (latlng, zoom) { + var projectedPoint = this.projection.project(latlng), + scale = this.scale(zoom); + + return this.transformation._transform(projectedPoint, scale); + }, + + // @method pointToLatLng(point: Point, zoom: Number): LatLng + // The inverse of `latLngToPoint`. Projects pixel coordinates on a given + // zoom into geographical coordinates. + pointToLatLng: function (point, zoom) { + var scale = this.scale(zoom), + untransformedPoint = this.transformation.untransform(point, scale); + + return this.projection.unproject(untransformedPoint); + }, + + // @method project(latlng: LatLng): Point + // Projects geographical coordinates into coordinates in units accepted for + // this CRS (e.g. meters for EPSG:3857, for passing it to WMS services). + project: function (latlng) { + return this.projection.project(latlng); + }, + + // @method unproject(point: Point): LatLng + // Given a projected coordinate returns the corresponding LatLng. + // The inverse of `project`. + unproject: function (point) { + return this.projection.unproject(point); + }, + + // @method scale(zoom: Number): Number + // Returns the scale used when transforming projected coordinates into + // pixel coordinates for a particular zoom. For example, it returns + // `256 * 2^zoom` for Mercator-based CRS. + scale: function (zoom) { + return 256 * Math.pow(2, zoom); + }, + + // @method zoom(scale: Number): Number + // Inverse of `scale()`, returns the zoom level corresponding to a scale + // factor of `scale`. + zoom: function (scale) { + return Math.log(scale / 256) / Math.LN2; + }, + + // @method getProjectedBounds(zoom: Number): Bounds + // Returns the projection's bounds scaled and transformed for the provided `zoom`. + getProjectedBounds: function (zoom) { + if (this.infinite) { return null; } + + var b = this.projection.bounds, + s = this.scale(zoom), + min = this.transformation.transform(b.min, s), + max = this.transformation.transform(b.max, s); + + return new Bounds(min, max); + }, + + // @method distance(latlng1: LatLng, latlng2: LatLng): Number + // Returns the distance between two geographical coordinates. + + // @property code: String + // Standard code name of the CRS passed into WMS services (e.g. `'EPSG:3857'`) + // + // @property wrapLng: Number[] + // An array of two numbers defining whether the longitude (horizontal) coordinate + // axis wraps around a given range and how. Defaults to `[-180, 180]` in most + // geographical CRSs. If `undefined`, the longitude axis does not wrap around. + // + // @property wrapLat: Number[] + // Like `wrapLng`, but for the latitude (vertical) axis. + + // wrapLng: [min, max], + // wrapLat: [min, max], + + // @property infinite: Boolean + // If true, the coordinate space will be unbounded (infinite in both axes) + infinite: false, + + // @method wrapLatLng(latlng: LatLng): LatLng + // Returns a `LatLng` where lat and lng has been wrapped according to the + // CRS's `wrapLat` and `wrapLng` properties, if they are outside the CRS's bounds. + wrapLatLng: function (latlng) { + var lng = this.wrapLng ? wrapNum(latlng.lng, this.wrapLng, true) : latlng.lng, + lat = this.wrapLat ? wrapNum(latlng.lat, this.wrapLat, true) : latlng.lat, + alt = latlng.alt; + + return new LatLng(lat, lng, alt); + }, + + // @method wrapLatLngBounds(bounds: LatLngBounds): LatLngBounds + // Returns a `LatLngBounds` with the same size as the given one, ensuring + // that its center is within the CRS's bounds. + // Only accepts actual `L.LatLngBounds` instances, not arrays. + wrapLatLngBounds: function (bounds) { + var center = bounds.getCenter(), + newCenter = this.wrapLatLng(center), + latShift = center.lat - newCenter.lat, + lngShift = center.lng - newCenter.lng; + + if (latShift === 0 && lngShift === 0) { + return bounds; + } + + var sw = bounds.getSouthWest(), + ne = bounds.getNorthEast(), + newSw = new LatLng(sw.lat - latShift, sw.lng - lngShift), + newNe = new LatLng(ne.lat - latShift, ne.lng - lngShift); + + return new LatLngBounds(newSw, newNe); + } +}; + +/* + * @namespace CRS + * @crs L.CRS.Earth + * + * Serves as the base for CRS that are global such that they cover the earth. + * Can only be used as the base for other CRS and cannot be used directly, + * since it does not have a `code`, `projection` or `transformation`. `distance()` returns + * meters. + */ + +var Earth = extend({}, CRS, { + wrapLng: [-180, 180], + + // Mean Earth Radius, as recommended for use by + // the International Union of Geodesy and Geophysics, + // see http://rosettacode.org/wiki/Haversine_formula + R: 6371000, + + // distance between two geographical points using spherical law of cosines approximation + distance: function (latlng1, latlng2) { + var rad = Math.PI / 180, + lat1 = latlng1.lat * rad, + lat2 = latlng2.lat * rad, + sinDLat = Math.sin((latlng2.lat - latlng1.lat) * rad / 2), + sinDLon = Math.sin((latlng2.lng - latlng1.lng) * rad / 2), + a = sinDLat * sinDLat + Math.cos(lat1) * Math.cos(lat2) * sinDLon * sinDLon, + c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + return this.R * c; + } +}); + +/* + * @namespace Projection + * @projection L.Projection.SphericalMercator + * + * Spherical Mercator projection — the most common projection for online maps, + * used by almost all free and commercial tile providers. Assumes that Earth is + * a sphere. Used by the `EPSG:3857` CRS. + */ + +var earthRadius = 6378137; + +var SphericalMercator = { + + R: earthRadius, + MAX_LATITUDE: 85.0511287798, + + project: function (latlng) { + var d = Math.PI / 180, + max = this.MAX_LATITUDE, + lat = Math.max(Math.min(max, latlng.lat), -max), + sin = Math.sin(lat * d); + + return new Point( + this.R * latlng.lng * d, + this.R * Math.log((1 + sin) / (1 - sin)) / 2); + }, + + unproject: function (point) { + var d = 180 / Math.PI; + + return new LatLng( + (2 * Math.atan(Math.exp(point.y / this.R)) - (Math.PI / 2)) * d, + point.x * d / this.R); + }, + + bounds: (function () { + var d = earthRadius * Math.PI; + return new Bounds([-d, -d], [d, d]); + })() +}; + +/* + * @class Transformation + * @aka L.Transformation + * + * Represents an affine transformation: a set of coefficients `a`, `b`, `c`, `d` + * for transforming a point of a form `(x, y)` into `(a*x + b, c*y + d)` and doing + * the reverse. Used by Leaflet in its projections code. + * + * @example + * + * ```js + * var transformation = L.transformation(2, 5, -1, 10), + * p = L.point(1, 2), + * p2 = transformation.transform(p), // L.point(7, 8) + * p3 = transformation.untransform(p2); // L.point(1, 2) + * ``` + */ + + +// factory new L.Transformation(a: Number, b: Number, c: Number, d: Number) +// Creates a `Transformation` object with the given coefficients. +function Transformation(a, b, c, d) { + if (isArray(a)) { + // use array properties + this._a = a[0]; + this._b = a[1]; + this._c = a[2]; + this._d = a[3]; + return; + } + this._a = a; + this._b = b; + this._c = c; + this._d = d; +} + +Transformation.prototype = { + // @method transform(point: Point, scale?: Number): Point + // Returns a transformed point, optionally multiplied by the given scale. + // Only accepts actual `L.Point` instances, not arrays. + transform: function (point, scale) { // (Point, Number) -> Point + return this._transform(point.clone(), scale); + }, + + // destructive transform (faster) + _transform: function (point, scale) { + scale = scale || 1; + point.x = scale * (this._a * point.x + this._b); + point.y = scale * (this._c * point.y + this._d); + return point; + }, + + // @method untransform(point: Point, scale?: Number): Point + // Returns the reverse transformation of the given point, optionally divided + // by the given scale. Only accepts actual `L.Point` instances, not arrays. + untransform: function (point, scale) { + scale = scale || 1; + return new Point( + (point.x / scale - this._b) / this._a, + (point.y / scale - this._d) / this._c); + } +}; + +// factory L.transformation(a: Number, b: Number, c: Number, d: Number) + +// @factory L.transformation(a: Number, b: Number, c: Number, d: Number) +// Instantiates a Transformation object with the given coefficients. + +// @alternative +// @factory L.transformation(coefficients: Array): Transformation +// Expects an coefficients array of the form +// `[a: Number, b: Number, c: Number, d: Number]`. + +function toTransformation(a, b, c, d) { + return new Transformation(a, b, c, d); +} + +/* + * @namespace CRS + * @crs L.CRS.EPSG3857 + * + * The most common CRS for online maps, used by almost all free and commercial + * tile providers. Uses Spherical Mercator projection. Set in by default in + * Map's `crs` option. + */ + +var EPSG3857 = extend({}, Earth, { + code: 'EPSG:3857', + projection: SphericalMercator, + + transformation: (function () { + var scale = 0.5 / (Math.PI * SphericalMercator.R); + return toTransformation(scale, 0.5, -scale, 0.5); + }()) +}); + +var EPSG900913 = extend({}, EPSG3857, { + code: 'EPSG:900913' +}); + +// @namespace SVG; @section +// There are several static functions which can be called without instantiating L.SVG: + +// @function create(name: String): SVGElement +// Returns a instance of [SVGElement](https://developer.mozilla.org/docs/Web/API/SVGElement), +// corresponding to the class name passed. For example, using 'line' will return +// an instance of [SVGLineElement](https://developer.mozilla.org/docs/Web/API/SVGLineElement). +function svgCreate(name) { + return document.createElementNS('http://www.w3.org/2000/svg', name); +} + +// @function pointsToPath(rings: Point[], closed: Boolean): String +// Generates a SVG path string for multiple rings, with each ring turning +// into "M..L..L.." instructions +function pointsToPath(rings, closed) { + var str = '', + i, j, len, len2, points, p; + + for (i = 0, len = rings.length; i < len; i++) { + points = rings[i]; + + for (j = 0, len2 = points.length; j < len2; j++) { + p = points[j]; + str += (j ? 'L' : 'M') + p.x + ' ' + p.y; + } + + // closes the ring for polygons; "x" is VML syntax + str += closed ? (svg ? 'z' : 'x') : ''; + } + + // SVG complains about empty path strings + return str || 'M0 0'; +} + +/* + * @namespace Browser + * @aka L.Browser + * + * A namespace with static properties for browser/feature detection used by Leaflet internally. + * + * @example + * + * ```js + * if (L.Browser.ielt9) { + * alert('Upgrade your browser, dude!'); + * } + * ``` + */ + +var style$1 = document.documentElement.style; + +// @property ie: Boolean; `true` for all Internet Explorer versions (not Edge). +var ie = 'ActiveXObject' in window; + +// @property ielt9: Boolean; `true` for Internet Explorer versions less than 9. +var ielt9 = ie && !document.addEventListener; + +// @property edge: Boolean; `true` for the Edge web browser. +var edge = 'msLaunchUri' in navigator && !('documentMode' in document); + +// @property webkit: Boolean; +// `true` for webkit-based browsers like Chrome and Safari (including mobile versions). +var webkit = userAgentContains('webkit'); + +// @property android: Boolean +// `true` for any browser running on an Android platform. +var android = userAgentContains('android'); + +// @property android23: Boolean; `true` for browsers running on Android 2 or Android 3. +var android23 = userAgentContains('android 2') || userAgentContains('android 3'); + +/* See https://stackoverflow.com/a/17961266 for details on detecting stock Android */ +var webkitVer = parseInt(/WebKit\/([0-9]+)|$/.exec(navigator.userAgent)[1], 10); // also matches AppleWebKit +// @property androidStock: Boolean; `true` for the Android stock browser (i.e. not Chrome) +var androidStock = android && userAgentContains('Google') && webkitVer < 537 && !('AudioNode' in window); + +// @property opera: Boolean; `true` for the Opera browser +var opera = !!window.opera; + +// @property chrome: Boolean; `true` for the Chrome browser. +var chrome = userAgentContains('chrome'); + +// @property gecko: Boolean; `true` for gecko-based browsers like Firefox. +var gecko = userAgentContains('gecko') && !webkit && !opera && !ie; + +// @property safari: Boolean; `true` for the Safari browser. +var safari = !chrome && userAgentContains('safari'); + +var phantom = userAgentContains('phantom'); + +// @property opera12: Boolean +// `true` for the Opera browser supporting CSS transforms (version 12 or later). +var opera12 = 'OTransition' in style$1; + +// @property win: Boolean; `true` when the browser is running in a Windows platform +var win = navigator.platform.indexOf('Win') === 0; + +// @property ie3d: Boolean; `true` for all Internet Explorer versions supporting CSS transforms. +var ie3d = ie && ('transition' in style$1); + +// @property webkit3d: Boolean; `true` for webkit-based browsers supporting CSS transforms. +var webkit3d = ('WebKitCSSMatrix' in window) && ('m11' in new window.WebKitCSSMatrix()) && !android23; + +// @property gecko3d: Boolean; `true` for gecko-based browsers supporting CSS transforms. +var gecko3d = 'MozPerspective' in style$1; + +// @property any3d: Boolean +// `true` for all browsers supporting CSS transforms. +var any3d = !window.L_DISABLE_3D && (ie3d || webkit3d || gecko3d) && !opera12 && !phantom; + +// @property mobile: Boolean; `true` for all browsers running in a mobile device. +var mobile = typeof orientation !== 'undefined' || userAgentContains('mobile'); + +// @property mobileWebkit: Boolean; `true` for all webkit-based browsers in a mobile device. +var mobileWebkit = mobile && webkit; + +// @property mobileWebkit3d: Boolean +// `true` for all webkit-based browsers in a mobile device supporting CSS transforms. +var mobileWebkit3d = mobile && webkit3d; + +// @property msPointer: Boolean +// `true` for browsers implementing the Microsoft touch events model (notably IE10). +var msPointer = !window.PointerEvent && window.MSPointerEvent; + +// @property pointer: Boolean +// `true` for all browsers supporting [pointer events](https://msdn.microsoft.com/en-us/library/dn433244%28v=vs.85%29.aspx). +var pointer = !webkit && !!(window.PointerEvent || msPointer); + +// @property touch: Boolean +// `true` for all browsers supporting [touch events](https://developer.mozilla.org/docs/Web/API/Touch_events). +// This does not necessarily mean that the browser is running in a computer with +// a touchscreen, it only means that the browser is capable of understanding +// touch events. +var touch = !window.L_NO_TOUCH && (pointer || 'ontouchstart' in window || + (window.DocumentTouch && document instanceof window.DocumentTouch)); + +// @property mobileOpera: Boolean; `true` for the Opera browser in a mobile device. +var mobileOpera = mobile && opera; + +// @property mobileGecko: Boolean +// `true` for gecko-based browsers running in a mobile device. +var mobileGecko = mobile && gecko; + +// @property retina: Boolean +// `true` for browsers on a high-resolution "retina" screen or on any screen when browser's display zoom is more than 100%. +var retina = (window.devicePixelRatio || (window.screen.deviceXDPI / window.screen.logicalXDPI)) > 1; + +// @property passiveEvents: Boolean +// `true` for browsers that support passive events. +var passiveEvents = (function () { + var supportsPassiveOption = false; + try { + var opts = Object.defineProperty({}, 'passive', { + get: function () { + supportsPassiveOption = true; + } + }); + window.addEventListener('testPassiveEventSupport', falseFn, opts); + window.removeEventListener('testPassiveEventSupport', falseFn, opts); + } catch (e) { + // Errors can safely be ignored since this is only a browser support test. + } + return supportsPassiveOption; +}); + +// @property canvas: Boolean +// `true` when the browser supports [``](https://developer.mozilla.org/docs/Web/API/Canvas_API). +var canvas = (function () { + return !!document.createElement('canvas').getContext; +}()); + +// @property svg: Boolean +// `true` when the browser supports [SVG](https://developer.mozilla.org/docs/Web/SVG). +var svg = !!(document.createElementNS && svgCreate('svg').createSVGRect); + +// @property vml: Boolean +// `true` if the browser supports [VML](https://en.wikipedia.org/wiki/Vector_Markup_Language). +var vml = !svg && (function () { + try { + var div = document.createElement('div'); + div.innerHTML = ''; + + var shape = div.firstChild; + shape.style.behavior = 'url(#default#VML)'; + + return shape && (typeof shape.adj === 'object'); + + } catch (e) { + return false; + } +}()); + + +function userAgentContains(str) { + return navigator.userAgent.toLowerCase().indexOf(str) >= 0; +} + + +var Browser = (Object.freeze || Object)({ + ie: ie, + ielt9: ielt9, + edge: edge, + webkit: webkit, + android: android, + android23: android23, + androidStock: androidStock, + opera: opera, + chrome: chrome, + gecko: gecko, + safari: safari, + phantom: phantom, + opera12: opera12, + win: win, + ie3d: ie3d, + webkit3d: webkit3d, + gecko3d: gecko3d, + any3d: any3d, + mobile: mobile, + mobileWebkit: mobileWebkit, + mobileWebkit3d: mobileWebkit3d, + msPointer: msPointer, + pointer: pointer, + touch: touch, + mobileOpera: mobileOpera, + mobileGecko: mobileGecko, + retina: retina, + passiveEvents: passiveEvents, + canvas: canvas, + svg: svg, + vml: vml +}); + +/* + * Extends L.DomEvent to provide touch support for Internet Explorer and Windows-based devices. + */ + + +var POINTER_DOWN = msPointer ? 'MSPointerDown' : 'pointerdown'; +var POINTER_MOVE = msPointer ? 'MSPointerMove' : 'pointermove'; +var POINTER_UP = msPointer ? 'MSPointerUp' : 'pointerup'; +var POINTER_CANCEL = msPointer ? 'MSPointerCancel' : 'pointercancel'; +var TAG_WHITE_LIST = ['INPUT', 'SELECT', 'OPTION']; + +var _pointers = {}; +var _pointerDocListener = false; + +// DomEvent.DoubleTap needs to know about this +var _pointersCount = 0; + +// Provides a touch events wrapper for (ms)pointer events. +// ref http://www.w3.org/TR/pointerevents/ https://www.w3.org/Bugs/Public/show_bug.cgi?id=22890 + +function addPointerListener(obj, type, handler, id) { + if (type === 'touchstart') { + _addPointerStart(obj, handler, id); + + } else if (type === 'touchmove') { + _addPointerMove(obj, handler, id); + + } else if (type === 'touchend') { + _addPointerEnd(obj, handler, id); + } + + return this; +} + +function removePointerListener(obj, type, id) { + var handler = obj['_leaflet_' + type + id]; + + if (type === 'touchstart') { + obj.removeEventListener(POINTER_DOWN, handler, false); + + } else if (type === 'touchmove') { + obj.removeEventListener(POINTER_MOVE, handler, false); + + } else if (type === 'touchend') { + obj.removeEventListener(POINTER_UP, handler, false); + obj.removeEventListener(POINTER_CANCEL, handler, false); + } + + return this; +} + +function _addPointerStart(obj, handler, id) { + var onDown = bind(function (e) { + if (e.pointerType !== 'mouse' && e.MSPOINTER_TYPE_MOUSE && e.pointerType !== e.MSPOINTER_TYPE_MOUSE) { + // In IE11, some touch events needs to fire for form controls, or + // the controls will stop working. We keep a whitelist of tag names that + // need these events. For other target tags, we prevent default on the event. + if (TAG_WHITE_LIST.indexOf(e.target.tagName) < 0) { + preventDefault(e); + } else { + return; + } + } + + _handlePointer(e, handler); + }); + + obj['_leaflet_touchstart' + id] = onDown; + obj.addEventListener(POINTER_DOWN, onDown, false); + + // need to keep track of what pointers and how many are active to provide e.touches emulation + if (!_pointerDocListener) { + // we listen documentElement as any drags that end by moving the touch off the screen get fired there + document.documentElement.addEventListener(POINTER_DOWN, _globalPointerDown, true); + document.documentElement.addEventListener(POINTER_MOVE, _globalPointerMove, true); + document.documentElement.addEventListener(POINTER_UP, _globalPointerUp, true); + document.documentElement.addEventListener(POINTER_CANCEL, _globalPointerUp, true); + + _pointerDocListener = true; + } +} + +function _globalPointerDown(e) { + _pointers[e.pointerId] = e; + _pointersCount++; +} + +function _globalPointerMove(e) { + if (_pointers[e.pointerId]) { + _pointers[e.pointerId] = e; + } +} + +function _globalPointerUp(e) { + delete _pointers[e.pointerId]; + _pointersCount--; +} + +function _handlePointer(e, handler) { + e.touches = []; + for (var i in _pointers) { + e.touches.push(_pointers[i]); + } + e.changedTouches = [e]; + + handler(e); +} + +function _addPointerMove(obj, handler, id) { + var onMove = function (e) { + // don't fire touch moves when mouse isn't down + if ((e.pointerType === e.MSPOINTER_TYPE_MOUSE || e.pointerType === 'mouse') && e.buttons === 0) { return; } + + _handlePointer(e, handler); + }; + + obj['_leaflet_touchmove' + id] = onMove; + obj.addEventListener(POINTER_MOVE, onMove, false); +} + +function _addPointerEnd(obj, handler, id) { + var onUp = function (e) { + _handlePointer(e, handler); + }; + + obj['_leaflet_touchend' + id] = onUp; + obj.addEventListener(POINTER_UP, onUp, false); + obj.addEventListener(POINTER_CANCEL, onUp, false); +} + +/* + * Extends the event handling code with double tap support for mobile browsers. + */ + +var _touchstart = msPointer ? 'MSPointerDown' : pointer ? 'pointerdown' : 'touchstart'; +var _touchend = msPointer ? 'MSPointerUp' : pointer ? 'pointerup' : 'touchend'; +var _pre = '_leaflet_'; + +// inspired by Zepto touch code by Thomas Fuchs +function addDoubleTapListener(obj, handler, id) { + var last, touch$$1, + doubleTap = false, + delay = 250; + + function onTouchStart(e) { + var count; + + if (pointer) { + if ((!edge) || e.pointerType === 'mouse') { return; } + count = _pointersCount; + } else { + count = e.touches.length; + } + + if (count > 1) { return; } + + var now = Date.now(), + delta = now - (last || now); + + touch$$1 = e.touches ? e.touches[0] : e; + doubleTap = (delta > 0 && delta <= delay); + last = now; + } + + function onTouchEnd(e) { + if (doubleTap && !touch$$1.cancelBubble) { + if (pointer) { + if ((!edge) || e.pointerType === 'mouse') { return; } + // work around .type being readonly with MSPointer* events + var newTouch = {}, + prop, i; + + for (i in touch$$1) { + prop = touch$$1[i]; + newTouch[i] = prop && prop.bind ? prop.bind(touch$$1) : prop; + } + touch$$1 = newTouch; + } + touch$$1.type = 'dblclick'; + touch$$1.button = 0; + handler(touch$$1); + last = null; + } + } + + obj[_pre + _touchstart + id] = onTouchStart; + obj[_pre + _touchend + id] = onTouchEnd; + obj[_pre + 'dblclick' + id] = handler; + + obj.addEventListener(_touchstart, onTouchStart, passiveEvents ? {passive: false} : false); + obj.addEventListener(_touchend, onTouchEnd, passiveEvents ? {passive: false} : false); + + // On some platforms (notably, chrome<55 on win10 + touchscreen + mouse), + // the browser doesn't fire touchend/pointerup events but does fire + // native dblclicks. See #4127. + // Edge 14 also fires native dblclicks, but only for pointerType mouse, see #5180. + obj.addEventListener('dblclick', handler, false); + + return this; +} + +function removeDoubleTapListener(obj, id) { + var touchstart = obj[_pre + _touchstart + id], + touchend = obj[_pre + _touchend + id], + dblclick = obj[_pre + 'dblclick' + id]; + + obj.removeEventListener(_touchstart, touchstart, passiveEvents ? {passive: false} : false); + obj.removeEventListener(_touchend, touchend, passiveEvents ? {passive: false} : false); + if (!edge) { + obj.removeEventListener('dblclick', dblclick, false); + } + + return this; +} + +/* + * @namespace DomUtil + * + * Utility functions to work with the [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model) + * tree, used by Leaflet internally. + * + * Most functions expecting or returning a `HTMLElement` also work for + * SVG elements. The only difference is that classes refer to CSS classes + * in HTML and SVG classes in SVG. + */ + + +// @property TRANSFORM: String +// Vendor-prefixed transform style name (e.g. `'webkitTransform'` for WebKit). +var TRANSFORM = testProp( + ['transform', 'webkitTransform', 'OTransform', 'MozTransform', 'msTransform']); + +// webkitTransition comes first because some browser versions that drop vendor prefix don't do +// the same for the transitionend event, in particular the Android 4.1 stock browser + +// @property TRANSITION: String +// Vendor-prefixed transition style name. +var TRANSITION = testProp( + ['webkitTransition', 'transition', 'OTransition', 'MozTransition', 'msTransition']); + +// @property TRANSITION_END: String +// Vendor-prefixed transitionend event name. +var TRANSITION_END = + TRANSITION === 'webkitTransition' || TRANSITION === 'OTransition' ? TRANSITION + 'End' : 'transitionend'; + + +// @function get(id: String|HTMLElement): HTMLElement +// Returns an element given its DOM id, or returns the element itself +// if it was passed directly. +function get(id) { + return typeof id === 'string' ? document.getElementById(id) : id; +} + +// @function getStyle(el: HTMLElement, styleAttrib: String): String +// Returns the value for a certain style attribute on an element, +// including computed values or values set through CSS. +function getStyle(el, style) { + var value = el.style[style] || (el.currentStyle && el.currentStyle[style]); + + if ((!value || value === 'auto') && document.defaultView) { + var css = document.defaultView.getComputedStyle(el, null); + value = css ? css[style] : null; + } + return value === 'auto' ? null : value; +} + +// @function create(tagName: String, className?: String, container?: HTMLElement): HTMLElement +// Creates an HTML element with `tagName`, sets its class to `className`, and optionally appends it to `container` element. +function create$1(tagName, className, container) { + var el = document.createElement(tagName); + el.className = className || ''; + + if (container) { + container.appendChild(el); + } + return el; +} + +// @function remove(el: HTMLElement) +// Removes `el` from its parent element +function remove(el) { + var parent = el.parentNode; + if (parent) { + parent.removeChild(el); + } +} + +// @function empty(el: HTMLElement) +// Removes all of `el`'s children elements from `el` +function empty(el) { + while (el.firstChild) { + el.removeChild(el.firstChild); + } +} + +// @function toFront(el: HTMLElement) +// Makes `el` the last child of its parent, so it renders in front of the other children. +function toFront(el) { + var parent = el.parentNode; + if (parent && parent.lastChild !== el) { + parent.appendChild(el); + } +} + +// @function toBack(el: HTMLElement) +// Makes `el` the first child of its parent, so it renders behind the other children. +function toBack(el) { + var parent = el.parentNode; + if (parent && parent.firstChild !== el) { + parent.insertBefore(el, parent.firstChild); + } +} + +// @function hasClass(el: HTMLElement, name: String): Boolean +// Returns `true` if the element's class attribute contains `name`. +function hasClass(el, name) { + if (el.classList !== undefined) { + return el.classList.contains(name); + } + var className = getClass(el); + return className.length > 0 && new RegExp('(^|\\s)' + name + '(\\s|$)').test(className); +} + +// @function addClass(el: HTMLElement, name: String) +// Adds `name` to the element's class attribute. +function addClass(el, name) { + if (el.classList !== undefined) { + var classes = splitWords(name); + for (var i = 0, len = classes.length; i < len; i++) { + el.classList.add(classes[i]); + } + } else if (!hasClass(el, name)) { + var className = getClass(el); + setClass(el, (className ? className + ' ' : '') + name); + } +} + +// @function removeClass(el: HTMLElement, name: String) +// Removes `name` from the element's class attribute. +function removeClass(el, name) { + if (el.classList !== undefined) { + el.classList.remove(name); + } else { + setClass(el, trim((' ' + getClass(el) + ' ').replace(' ' + name + ' ', ' '))); + } +} + +// @function setClass(el: HTMLElement, name: String) +// Sets the element's class. +function setClass(el, name) { + if (el.className.baseVal === undefined) { + el.className = name; + } else { + // in case of SVG element + el.className.baseVal = name; + } +} + +// @function getClass(el: HTMLElement): String +// Returns the element's class. +function getClass(el) { + // Check if the element is an SVGElementInstance and use the correspondingElement instead + // (Required for linked SVG elements in IE11.) + if (el.correspondingElement) { + el = el.correspondingElement; + } + return el.className.baseVal === undefined ? el.className : el.className.baseVal; +} + +// @function setOpacity(el: HTMLElement, opacity: Number) +// Set the opacity of an element (including old IE support). +// `opacity` must be a number from `0` to `1`. +function setOpacity(el, value) { + if ('opacity' in el.style) { + el.style.opacity = value; + } else if ('filter' in el.style) { + _setOpacityIE(el, value); + } +} + +function _setOpacityIE(el, value) { + var filter = false, + filterName = 'DXImageTransform.Microsoft.Alpha'; + + // filters collection throws an error if we try to retrieve a filter that doesn't exist + try { + filter = el.filters.item(filterName); + } catch (e) { + // don't set opacity to 1 if we haven't already set an opacity, + // it isn't needed and breaks transparent pngs. + if (value === 1) { return; } + } + + value = Math.round(value * 100); + + if (filter) { + filter.Enabled = (value !== 100); + filter.Opacity = value; + } else { + el.style.filter += ' progid:' + filterName + '(opacity=' + value + ')'; + } +} + +// @function testProp(props: String[]): String|false +// Goes through the array of style names and returns the first name +// that is a valid style name for an element. If no such name is found, +// it returns false. Useful for vendor-prefixed styles like `transform`. +function testProp(props) { + var style = document.documentElement.style; + + for (var i = 0; i < props.length; i++) { + if (props[i] in style) { + return props[i]; + } + } + return false; +} + +// @function setTransform(el: HTMLElement, offset: Point, scale?: Number) +// Resets the 3D CSS transform of `el` so it is translated by `offset` pixels +// and optionally scaled by `scale`. Does not have an effect if the +// browser doesn't support 3D CSS transforms. +function setTransform(el, offset, scale) { + var pos = offset || new Point(0, 0); + + el.style[TRANSFORM] = + (ie3d ? + 'translate(' + pos.x + 'px,' + pos.y + 'px)' : + 'translate3d(' + pos.x + 'px,' + pos.y + 'px,0)') + + (scale ? ' scale(' + scale + ')' : ''); +} + +// @function setPosition(el: HTMLElement, position: Point) +// Sets the position of `el` to coordinates specified by `position`, +// using CSS translate or top/left positioning depending on the browser +// (used by Leaflet internally to position its layers). +function setPosition(el, point) { + + /*eslint-disable */ + el._leaflet_pos = point; + /* eslint-enable */ + + if (any3d) { + setTransform(el, point); + } else { + el.style.left = point.x + 'px'; + el.style.top = point.y + 'px'; + } +} + +// @function getPosition(el: HTMLElement): Point +// Returns the coordinates of an element previously positioned with setPosition. +function getPosition(el) { + // this method is only used for elements previously positioned using setPosition, + // so it's safe to cache the position for performance + + return el._leaflet_pos || new Point(0, 0); +} + +// @function disableTextSelection() +// Prevents the user from generating `selectstart` DOM events, usually generated +// when the user drags the mouse through a page with text. Used internally +// by Leaflet to override the behaviour of any click-and-drag interaction on +// the map. Affects drag interactions on the whole document. + +// @function enableTextSelection() +// Cancels the effects of a previous [`L.DomUtil.disableTextSelection`](#domutil-disabletextselection). +var disableTextSelection; +var enableTextSelection; +var _userSelect; +if ('onselectstart' in document) { + disableTextSelection = function () { + on(window, 'selectstart', preventDefault); + }; + enableTextSelection = function () { + off(window, 'selectstart', preventDefault); + }; +} else { + var userSelectProperty = testProp( + ['userSelect', 'WebkitUserSelect', 'OUserSelect', 'MozUserSelect', 'msUserSelect']); + + disableTextSelection = function () { + if (userSelectProperty) { + var style = document.documentElement.style; + _userSelect = style[userSelectProperty]; + style[userSelectProperty] = 'none'; + } + }; + enableTextSelection = function () { + if (userSelectProperty) { + document.documentElement.style[userSelectProperty] = _userSelect; + _userSelect = undefined; + } + }; +} + +// @function disableImageDrag() +// As [`L.DomUtil.disableTextSelection`](#domutil-disabletextselection), but +// for `dragstart` DOM events, usually generated when the user drags an image. +function disableImageDrag() { + on(window, 'dragstart', preventDefault); +} + +// @function enableImageDrag() +// Cancels the effects of a previous [`L.DomUtil.disableImageDrag`](#domutil-disabletextselection). +function enableImageDrag() { + off(window, 'dragstart', preventDefault); +} + +var _outlineElement; +var _outlineStyle; +// @function preventOutline(el: HTMLElement) +// Makes the [outline](https://developer.mozilla.org/docs/Web/CSS/outline) +// of the element `el` invisible. Used internally by Leaflet to prevent +// focusable elements from displaying an outline when the user performs a +// drag interaction on them. +function preventOutline(element) { + while (element.tabIndex === -1) { + element = element.parentNode; + } + if (!element.style) { return; } + restoreOutline(); + _outlineElement = element; + _outlineStyle = element.style.outline; + element.style.outline = 'none'; + on(window, 'keydown', restoreOutline); +} + +// @function restoreOutline() +// Cancels the effects of a previous [`L.DomUtil.preventOutline`](). +function restoreOutline() { + if (!_outlineElement) { return; } + _outlineElement.style.outline = _outlineStyle; + _outlineElement = undefined; + _outlineStyle = undefined; + off(window, 'keydown', restoreOutline); +} + +// @function getSizedParentNode(el: HTMLElement): HTMLElement +// Finds the closest parent node which size (width and height) is not null. +function getSizedParentNode(element) { + do { + element = element.parentNode; + } while ((!element.offsetWidth || !element.offsetHeight) && element !== document.body); + return element; +} + +// @function getScale(el: HTMLElement): Object +// Computes the CSS scale currently applied on the element. +// Returns an object with `x` and `y` members as horizontal and vertical scales respectively, +// and `boundingClientRect` as the result of [`getBoundingClientRect()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect). +function getScale(element) { + var rect = element.getBoundingClientRect(); // Read-only in old browsers. + + return { + x: rect.width / element.offsetWidth || 1, + y: rect.height / element.offsetHeight || 1, + boundingClientRect: rect + }; +} + + +var DomUtil = (Object.freeze || Object)({ + TRANSFORM: TRANSFORM, + TRANSITION: TRANSITION, + TRANSITION_END: TRANSITION_END, + get: get, + getStyle: getStyle, + create: create$1, + remove: remove, + empty: empty, + toFront: toFront, + toBack: toBack, + hasClass: hasClass, + addClass: addClass, + removeClass: removeClass, + setClass: setClass, + getClass: getClass, + setOpacity: setOpacity, + testProp: testProp, + setTransform: setTransform, + setPosition: setPosition, + getPosition: getPosition, + disableTextSelection: disableTextSelection, + enableTextSelection: enableTextSelection, + disableImageDrag: disableImageDrag, + enableImageDrag: enableImageDrag, + preventOutline: preventOutline, + restoreOutline: restoreOutline, + getSizedParentNode: getSizedParentNode, + getScale: getScale +}); + +/* + * @namespace DomEvent + * Utility functions to work with the [DOM events](https://developer.mozilla.org/docs/Web/API/Event), used by Leaflet internally. + */ + +// Inspired by John Resig, Dean Edwards and YUI addEvent implementations. + +// @function on(el: HTMLElement, types: String, fn: Function, context?: Object): this +// Adds a listener function (`fn`) to a particular DOM event type of the +// element `el`. You can optionally specify the context of the listener +// (object the `this` keyword will point to). You can also pass several +// space-separated types (e.g. `'click dblclick'`). + +// @alternative +// @function on(el: HTMLElement, eventMap: Object, context?: Object): this +// Adds a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}` +function on(obj, types, fn, context) { + + if (typeof types === 'object') { + for (var type in types) { + addOne(obj, type, types[type], fn); + } + } else { + types = splitWords(types); + + for (var i = 0, len = types.length; i < len; i++) { + addOne(obj, types[i], fn, context); + } + } + + return this; +} + +var eventsKey = '_leaflet_events'; + +// @function off(el: HTMLElement, types: String, fn: Function, context?: Object): this +// Removes a previously added listener function. +// Note that if you passed a custom context to on, you must pass the same +// context to `off` in order to remove the listener. + +// @alternative +// @function off(el: HTMLElement, eventMap: Object, context?: Object): this +// Removes a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}` +function off(obj, types, fn, context) { + + if (typeof types === 'object') { + for (var type in types) { + removeOne(obj, type, types[type], fn); + } + } else if (types) { + types = splitWords(types); + + for (var i = 0, len = types.length; i < len; i++) { + removeOne(obj, types[i], fn, context); + } + } else { + for (var j in obj[eventsKey]) { + removeOne(obj, j, obj[eventsKey][j]); + } + delete obj[eventsKey]; + } + + return this; +} + +function addOne(obj, type, fn, context) { + var id = type + stamp(fn) + (context ? '_' + stamp(context) : ''); + + if (obj[eventsKey] && obj[eventsKey][id]) { return this; } + + var handler = function (e) { + return fn.call(context || obj, e || window.event); + }; + + var originalHandler = handler; + + if (pointer && type.indexOf('touch') === 0) { + // Needs DomEvent.Pointer.js + addPointerListener(obj, type, handler, id); + + } else if (touch && (type === 'dblclick') && addDoubleTapListener && + !(pointer && chrome)) { + // Chrome >55 does not need the synthetic dblclicks from addDoubleTapListener + // See #5180 + addDoubleTapListener(obj, handler, id); + + } else if ('addEventListener' in obj) { + + if (type === 'mousewheel') { + obj.addEventListener('onwheel' in obj ? 'wheel' : 'mousewheel', handler, passiveEvents ? {passive: false} : false); + + } else if ((type === 'mouseenter') || (type === 'mouseleave')) { + handler = function (e) { + e = e || window.event; + if (isExternalTarget(obj, e)) { + originalHandler(e); + } + }; + obj.addEventListener(type === 'mouseenter' ? 'mouseover' : 'mouseout', handler, false); + + } else { + if (type === 'click' && android) { + handler = function (e) { + filterClick(e, originalHandler); + }; + } + obj.addEventListener(type, handler, false); + } + + } else if ('attachEvent' in obj) { + obj.attachEvent('on' + type, handler); + } + + obj[eventsKey] = obj[eventsKey] || {}; + obj[eventsKey][id] = handler; +} + +function removeOne(obj, type, fn, context) { + + var id = type + stamp(fn) + (context ? '_' + stamp(context) : ''), + handler = obj[eventsKey] && obj[eventsKey][id]; + + if (!handler) { return this; } + + if (pointer && type.indexOf('touch') === 0) { + removePointerListener(obj, type, id); + + } else if (touch && (type === 'dblclick') && removeDoubleTapListener && + !(pointer && chrome)) { + removeDoubleTapListener(obj, id); + + } else if ('removeEventListener' in obj) { + + if (type === 'mousewheel') { + obj.removeEventListener('onwheel' in obj ? 'wheel' : 'mousewheel', handler, passiveEvents ? {passive: false} : false); + + } else { + obj.removeEventListener( + type === 'mouseenter' ? 'mouseover' : + type === 'mouseleave' ? 'mouseout' : type, handler, false); + } + + } else if ('detachEvent' in obj) { + obj.detachEvent('on' + type, handler); + } + + obj[eventsKey][id] = null; +} + +// @function stopPropagation(ev: DOMEvent): this +// Stop the given event from propagation to parent elements. Used inside the listener functions: +// ```js +// L.DomEvent.on(div, 'click', function (ev) { +// L.DomEvent.stopPropagation(ev); +// }); +// ``` +function stopPropagation(e) { + + if (e.stopPropagation) { + e.stopPropagation(); + } else if (e.originalEvent) { // In case of Leaflet event. + e.originalEvent._stopped = true; + } else { + e.cancelBubble = true; + } + skipped(e); + + return this; +} + +// @function disableScrollPropagation(el: HTMLElement): this +// Adds `stopPropagation` to the element's `'mousewheel'` events (plus browser variants). +function disableScrollPropagation(el) { + addOne(el, 'mousewheel', stopPropagation); + return this; +} + +// @function disableClickPropagation(el: HTMLElement): this +// Adds `stopPropagation` to the element's `'click'`, `'doubleclick'`, +// `'mousedown'` and `'touchstart'` events (plus browser variants). +function disableClickPropagation(el) { + on(el, 'mousedown touchstart dblclick', stopPropagation); + addOne(el, 'click', fakeStop); + return this; +} + +// @function preventDefault(ev: DOMEvent): this +// Prevents the default action of the DOM Event `ev` from happening (such as +// following a link in the href of the a element, or doing a POST request +// with page reload when a `
` is submitted). +// Use it inside listener functions. +function preventDefault(e) { + if (e.preventDefault) { + e.preventDefault(); + } else { + e.returnValue = false; + } + return this; +} + +// @function stop(ev: DOMEvent): this +// Does `stopPropagation` and `preventDefault` at the same time. +function stop(e) { + preventDefault(e); + stopPropagation(e); + return this; +} + +// @function getMousePosition(ev: DOMEvent, container?: HTMLElement): Point +// Gets normalized mouse position from a DOM event relative to the +// `container` (border excluded) or to the whole page if not specified. +function getMousePosition(e, container) { + if (!container) { + return new Point(e.clientX, e.clientY); + } + + var scale = getScale(container), + offset = scale.boundingClientRect; // left and top values are in page scale (like the event clientX/Y) + + return new Point( + // offset.left/top values are in page scale (like clientX/Y), + // whereas clientLeft/Top (border width) values are the original values (before CSS scale applies). + (e.clientX - offset.left) / scale.x - container.clientLeft, + (e.clientY - offset.top) / scale.y - container.clientTop + ); +} + +// Chrome on Win scrolls double the pixels as in other platforms (see #4538), +// and Firefox scrolls device pixels, not CSS pixels +var wheelPxFactor = + (win && chrome) ? 2 * window.devicePixelRatio : + gecko ? window.devicePixelRatio : 1; + +// @function getWheelDelta(ev: DOMEvent): Number +// Gets normalized wheel delta from a mousewheel DOM event, in vertical +// pixels scrolled (negative if scrolling down). +// Events from pointing devices without precise scrolling are mapped to +// a best guess of 60 pixels. +function getWheelDelta(e) { + return (edge) ? e.wheelDeltaY / 2 : // Don't trust window-geometry-based delta + (e.deltaY && e.deltaMode === 0) ? -e.deltaY / wheelPxFactor : // Pixels + (e.deltaY && e.deltaMode === 1) ? -e.deltaY * 20 : // Lines + (e.deltaY && e.deltaMode === 2) ? -e.deltaY * 60 : // Pages + (e.deltaX || e.deltaZ) ? 0 : // Skip horizontal/depth wheel events + e.wheelDelta ? (e.wheelDeltaY || e.wheelDelta) / 2 : // Legacy IE pixels + (e.detail && Math.abs(e.detail) < 32765) ? -e.detail * 20 : // Legacy Moz lines + e.detail ? e.detail / -32765 * 60 : // Legacy Moz pages + 0; +} + +var skipEvents = {}; + +function fakeStop(e) { + // fakes stopPropagation by setting a special event flag, checked/reset with skipped(e) + skipEvents[e.type] = true; +} + +function skipped(e) { + var events = skipEvents[e.type]; + // reset when checking, as it's only used in map container and propagates outside of the map + skipEvents[e.type] = false; + return events; +} + +// check if element really left/entered the event target (for mouseenter/mouseleave) +function isExternalTarget(el, e) { + + var related = e.relatedTarget; + + if (!related) { return true; } + + try { + while (related && (related !== el)) { + related = related.parentNode; + } + } catch (err) { + return false; + } + return (related !== el); +} + +var lastClick; + +// this is a horrible workaround for a bug in Android where a single touch triggers two click events +function filterClick(e, handler) { + var timeStamp = (e.timeStamp || (e.originalEvent && e.originalEvent.timeStamp)), + elapsed = lastClick && (timeStamp - lastClick); + + // are they closer together than 500ms yet more than 100ms? + // Android typically triggers them ~300ms apart while multiple listeners + // on the same event should be triggered far faster; + // or check if click is simulated on the element, and if it is, reject any non-simulated events + + if ((elapsed && elapsed > 100 && elapsed < 500) || (e.target._simulatedClick && !e._simulated)) { + stop(e); + return; + } + lastClick = timeStamp; + + handler(e); +} + + + + +var DomEvent = (Object.freeze || Object)({ + on: on, + off: off, + stopPropagation: stopPropagation, + disableScrollPropagation: disableScrollPropagation, + disableClickPropagation: disableClickPropagation, + preventDefault: preventDefault, + stop: stop, + getMousePosition: getMousePosition, + getWheelDelta: getWheelDelta, + fakeStop: fakeStop, + skipped: skipped, + isExternalTarget: isExternalTarget, + addListener: on, + removeListener: off +}); + +/* + * @class PosAnimation + * @aka L.PosAnimation + * @inherits Evented + * Used internally for panning animations, utilizing CSS3 Transitions for modern browsers and a timer fallback for IE6-9. + * + * @example + * ```js + * var fx = new L.PosAnimation(); + * fx.run(el, [300, 500], 0.5); + * ``` + * + * @constructor L.PosAnimation() + * Creates a `PosAnimation` object. + * + */ + +var PosAnimation = Evented.extend({ + + // @method run(el: HTMLElement, newPos: Point, duration?: Number, easeLinearity?: Number) + // Run an animation of a given element to a new position, optionally setting + // duration in seconds (`0.25` by default) and easing linearity factor (3rd + // argument of the [cubic bezier curve](http://cubic-bezier.com/#0,0,.5,1), + // `0.5` by default). + run: function (el, newPos, duration, easeLinearity) { + this.stop(); + + this._el = el; + this._inProgress = true; + this._duration = duration || 0.25; + this._easeOutPower = 1 / Math.max(easeLinearity || 0.5, 0.2); + + this._startPos = getPosition(el); + this._offset = newPos.subtract(this._startPos); + this._startTime = +new Date(); + + // @event start: Event + // Fired when the animation starts + this.fire('start'); + + this._animate(); + }, + + // @method stop() + // Stops the animation (if currently running). + stop: function () { + if (!this._inProgress) { return; } + + this._step(true); + this._complete(); + }, + + _animate: function () { + // animation loop + this._animId = requestAnimFrame(this._animate, this); + this._step(); + }, + + _step: function (round) { + var elapsed = (+new Date()) - this._startTime, + duration = this._duration * 1000; + + if (elapsed < duration) { + this._runFrame(this._easeOut(elapsed / duration), round); + } else { + this._runFrame(1); + this._complete(); + } + }, + + _runFrame: function (progress, round) { + var pos = this._startPos.add(this._offset.multiplyBy(progress)); + if (round) { + pos._round(); + } + setPosition(this._el, pos); + + // @event step: Event + // Fired continuously during the animation. + this.fire('step'); + }, + + _complete: function () { + cancelAnimFrame(this._animId); + + this._inProgress = false; + // @event end: Event + // Fired when the animation ends. + this.fire('end'); + }, + + _easeOut: function (t) { + return 1 - Math.pow(1 - t, this._easeOutPower); + } +}); + +/* + * @class Map + * @aka L.Map + * @inherits Evented + * + * The central class of the API — it is used to create a map on a page and manipulate it. + * + * @example + * + * ```js + * // initialize the map on the "map" div with a given center and zoom + * var map = L.map('map', { + * center: [51.505, -0.09], + * zoom: 13 + * }); + * ``` + * + */ + +var Map = Evented.extend({ + + options: { + // @section Map State Options + // @option crs: CRS = L.CRS.EPSG3857 + // The [Coordinate Reference System](#crs) to use. Don't change this if you're not + // sure what it means. + crs: EPSG3857, + + // @option center: LatLng = undefined + // Initial geographic center of the map + center: undefined, + + // @option zoom: Number = undefined + // Initial map zoom level + zoom: undefined, + + // @option minZoom: Number = * + // Minimum zoom level of the map. + // If not specified and at least one `GridLayer` or `TileLayer` is in the map, + // the lowest of their `minZoom` options will be used instead. + minZoom: undefined, + + // @option maxZoom: Number = * + // Maximum zoom level of the map. + // If not specified and at least one `GridLayer` or `TileLayer` is in the map, + // the highest of their `maxZoom` options will be used instead. + maxZoom: undefined, + + // @option layers: Layer[] = [] + // Array of layers that will be added to the map initially + layers: [], + + // @option maxBounds: LatLngBounds = null + // When this option is set, the map restricts the view to the given + // geographical bounds, bouncing the user back if the user tries to pan + // outside the view. To set the restriction dynamically, use + // [`setMaxBounds`](#map-setmaxbounds) method. + maxBounds: undefined, + + // @option renderer: Renderer = * + // The default method for drawing vector layers on the map. `L.SVG` + // or `L.Canvas` by default depending on browser support. + renderer: undefined, + + + // @section Animation Options + // @option zoomAnimation: Boolean = true + // Whether the map zoom animation is enabled. By default it's enabled + // in all browsers that support CSS3 Transitions except Android. + zoomAnimation: true, + + // @option zoomAnimationThreshold: Number = 4 + // Won't animate zoom if the zoom difference exceeds this value. + zoomAnimationThreshold: 4, + + // @option fadeAnimation: Boolean = true + // Whether the tile fade animation is enabled. By default it's enabled + // in all browsers that support CSS3 Transitions except Android. + fadeAnimation: true, + + // @option markerZoomAnimation: Boolean = true + // Whether markers animate their zoom with the zoom animation, if disabled + // they will disappear for the length of the animation. By default it's + // enabled in all browsers that support CSS3 Transitions except Android. + markerZoomAnimation: true, + + // @option transform3DLimit: Number = 2^23 + // Defines the maximum size of a CSS translation transform. The default + // value should not be changed unless a web browser positions layers in + // the wrong place after doing a large `panBy`. + transform3DLimit: 8388608, // Precision limit of a 32-bit float + + // @section Interaction Options + // @option zoomSnap: Number = 1 + // Forces the map's zoom level to always be a multiple of this, particularly + // right after a [`fitBounds()`](#map-fitbounds) or a pinch-zoom. + // By default, the zoom level snaps to the nearest integer; lower values + // (e.g. `0.5` or `0.1`) allow for greater granularity. A value of `0` + // means the zoom level will not be snapped after `fitBounds` or a pinch-zoom. + zoomSnap: 1, + + // @option zoomDelta: Number = 1 + // Controls how much the map's zoom level will change after a + // [`zoomIn()`](#map-zoomin), [`zoomOut()`](#map-zoomout), pressing `+` + // or `-` on the keyboard, or using the [zoom controls](#control-zoom). + // Values smaller than `1` (e.g. `0.5`) allow for greater granularity. + zoomDelta: 1, + + // @option trackResize: Boolean = true + // Whether the map automatically handles browser window resize to update itself. + trackResize: true + }, + + initialize: function (id, options) { // (HTMLElement or String, Object) + options = setOptions(this, options); + + // Make sure to assign internal flags at the beginning, + // to avoid inconsistent state in some edge cases. + this._handlers = []; + this._layers = {}; + this._zoomBoundLayers = {}; + this._sizeChanged = true; + + this._initContainer(id); + this._initLayout(); + + // hack for https://github.com/Leaflet/Leaflet/issues/1980 + this._onResize = bind(this._onResize, this); + + this._initEvents(); + + if (options.maxBounds) { + this.setMaxBounds(options.maxBounds); + } + + if (options.zoom !== undefined) { + this._zoom = this._limitZoom(options.zoom); + } + + if (options.center && options.zoom !== undefined) { + this.setView(toLatLng(options.center), options.zoom, {reset: true}); + } + + this.callInitHooks(); + + // don't animate on browsers without hardware-accelerated transitions or old Android/Opera + this._zoomAnimated = TRANSITION && any3d && !mobileOpera && + this.options.zoomAnimation; + + // zoom transitions run with the same duration for all layers, so if one of transitionend events + // happens after starting zoom animation (propagating to the map pane), we know that it ended globally + if (this._zoomAnimated) { + this._createAnimProxy(); + on(this._proxy, TRANSITION_END, this._catchTransitionEnd, this); + } + + this._addLayers(this.options.layers); + }, + + + // @section Methods for modifying map state + + // @method setView(center: LatLng, zoom: Number, options?: Zoom/pan options): this + // Sets the view of the map (geographical center and zoom) with the given + // animation options. + setView: function (center, zoom, options) { + + zoom = zoom === undefined ? this._zoom : this._limitZoom(zoom); + center = this._limitCenter(toLatLng(center), zoom, this.options.maxBounds); + options = options || {}; + + this._stop(); + + if (this._loaded && !options.reset && options !== true) { + + if (options.animate !== undefined) { + options.zoom = extend({animate: options.animate}, options.zoom); + options.pan = extend({animate: options.animate, duration: options.duration}, options.pan); + } + + // try animating pan or zoom + var moved = (this._zoom !== zoom) ? + this._tryAnimatedZoom && this._tryAnimatedZoom(center, zoom, options.zoom) : + this._tryAnimatedPan(center, options.pan); + + if (moved) { + // prevent resize handler call, the view will refresh after animation anyway + clearTimeout(this._sizeTimer); + return this; + } + } + + // animation didn't start, just reset the map view + this._resetView(center, zoom); + + return this; + }, + + // @method setZoom(zoom: Number, options?: Zoom/pan options): this + // Sets the zoom of the map. + setZoom: function (zoom, options) { + if (!this._loaded) { + this._zoom = zoom; + return this; + } + return this.setView(this.getCenter(), zoom, {zoom: options}); + }, + + // @method zoomIn(delta?: Number, options?: Zoom options): this + // Increases the zoom of the map by `delta` ([`zoomDelta`](#map-zoomdelta) by default). + zoomIn: function (delta, options) { + delta = delta || (any3d ? this.options.zoomDelta : 1); + return this.setZoom(this._zoom + delta, options); + }, + + // @method zoomOut(delta?: Number, options?: Zoom options): this + // Decreases the zoom of the map by `delta` ([`zoomDelta`](#map-zoomdelta) by default). + zoomOut: function (delta, options) { + delta = delta || (any3d ? this.options.zoomDelta : 1); + return this.setZoom(this._zoom - delta, options); + }, + + // @method setZoomAround(latlng: LatLng, zoom: Number, options: Zoom options): this + // Zooms the map while keeping a specified geographical point on the map + // stationary (e.g. used internally for scroll zoom and double-click zoom). + // @alternative + // @method setZoomAround(offset: Point, zoom: Number, options: Zoom options): this + // Zooms the map while keeping a specified pixel on the map (relative to the top-left corner) stationary. + setZoomAround: function (latlng, zoom, options) { + var scale = this.getZoomScale(zoom), + viewHalf = this.getSize().divideBy(2), + containerPoint = latlng instanceof Point ? latlng : this.latLngToContainerPoint(latlng), + + centerOffset = containerPoint.subtract(viewHalf).multiplyBy(1 - 1 / scale), + newCenter = this.containerPointToLatLng(viewHalf.add(centerOffset)); + + return this.setView(newCenter, zoom, {zoom: options}); + }, + + _getBoundsCenterZoom: function (bounds, options) { + + options = options || {}; + bounds = bounds.getBounds ? bounds.getBounds() : toLatLngBounds(bounds); + + var paddingTL = toPoint(options.paddingTopLeft || options.padding || [0, 0]), + paddingBR = toPoint(options.paddingBottomRight || options.padding || [0, 0]), + + zoom = this.getBoundsZoom(bounds, false, paddingTL.add(paddingBR)); + + zoom = (typeof options.maxZoom === 'number') ? Math.min(options.maxZoom, zoom) : zoom; + + if (zoom === Infinity) { + return { + center: bounds.getCenter(), + zoom: zoom + }; + } + + var paddingOffset = paddingBR.subtract(paddingTL).divideBy(2), + + swPoint = this.project(bounds.getSouthWest(), zoom), + nePoint = this.project(bounds.getNorthEast(), zoom), + center = this.unproject(swPoint.add(nePoint).divideBy(2).add(paddingOffset), zoom); + + return { + center: center, + zoom: zoom + }; + }, + + // @method fitBounds(bounds: LatLngBounds, options?: fitBounds options): this + // Sets a map view that contains the given geographical bounds with the + // maximum zoom level possible. + fitBounds: function (bounds, options) { + + bounds = toLatLngBounds(bounds); + + if (!bounds.isValid()) { + throw new Error('Bounds are not valid.'); + } + + var target = this._getBoundsCenterZoom(bounds, options); + return this.setView(target.center, target.zoom, options); + }, + + // @method fitWorld(options?: fitBounds options): this + // Sets a map view that mostly contains the whole world with the maximum + // zoom level possible. + fitWorld: function (options) { + return this.fitBounds([[-90, -180], [90, 180]], options); + }, + + // @method panTo(latlng: LatLng, options?: Pan options): this + // Pans the map to a given center. + panTo: function (center, options) { // (LatLng) + return this.setView(center, this._zoom, {pan: options}); + }, + + // @method panBy(offset: Point, options?: Pan options): this + // Pans the map by a given number of pixels (animated). + panBy: function (offset, options) { + offset = toPoint(offset).round(); + options = options || {}; + + if (!offset.x && !offset.y) { + return this.fire('moveend'); + } + // If we pan too far, Chrome gets issues with tiles + // and makes them disappear or appear in the wrong place (slightly offset) #2602 + if (options.animate !== true && !this.getSize().contains(offset)) { + this._resetView(this.unproject(this.project(this.getCenter()).add(offset)), this.getZoom()); + return this; + } + + if (!this._panAnim) { + this._panAnim = new PosAnimation(); + + this._panAnim.on({ + 'step': this._onPanTransitionStep, + 'end': this._onPanTransitionEnd + }, this); + } + + // don't fire movestart if animating inertia + if (!options.noMoveStart) { + this.fire('movestart'); + } + + // animate pan unless animate: false specified + if (options.animate !== false) { + addClass(this._mapPane, 'leaflet-pan-anim'); + + var newPos = this._getMapPanePos().subtract(offset).round(); + this._panAnim.run(this._mapPane, newPos, options.duration || 0.25, options.easeLinearity); + } else { + this._rawPanBy(offset); + this.fire('move').fire('moveend'); + } + + return this; + }, + + // @method flyTo(latlng: LatLng, zoom?: Number, options?: Zoom/pan options): this + // Sets the view of the map (geographical center and zoom) performing a smooth + // pan-zoom animation. + flyTo: function (targetCenter, targetZoom, options) { + + options = options || {}; + if (options.animate === false || !any3d) { + return this.setView(targetCenter, targetZoom, options); + } + + this._stop(); + + var from = this.project(this.getCenter()), + to = this.project(targetCenter), + size = this.getSize(), + startZoom = this._zoom; + + targetCenter = toLatLng(targetCenter); + targetZoom = targetZoom === undefined ? startZoom : targetZoom; + + var w0 = Math.max(size.x, size.y), + w1 = w0 * this.getZoomScale(startZoom, targetZoom), + u1 = (to.distanceTo(from)) || 1, + rho = 1.42, + rho2 = rho * rho; + + function r(i) { + var s1 = i ? -1 : 1, + s2 = i ? w1 : w0, + t1 = w1 * w1 - w0 * w0 + s1 * rho2 * rho2 * u1 * u1, + b1 = 2 * s2 * rho2 * u1, + b = t1 / b1, + sq = Math.sqrt(b * b + 1) - b; + + // workaround for floating point precision bug when sq = 0, log = -Infinite, + // thus triggering an infinite loop in flyTo + var log = sq < 0.000000001 ? -18 : Math.log(sq); + + return log; + } + + function sinh(n) { return (Math.exp(n) - Math.exp(-n)) / 2; } + function cosh(n) { return (Math.exp(n) + Math.exp(-n)) / 2; } + function tanh(n) { return sinh(n) / cosh(n); } + + var r0 = r(0); + + function w(s) { return w0 * (cosh(r0) / cosh(r0 + rho * s)); } + function u(s) { return w0 * (cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2; } + + function easeOut(t) { return 1 - Math.pow(1 - t, 1.5); } + + var start = Date.now(), + S = (r(1) - r0) / rho, + duration = options.duration ? 1000 * options.duration : 1000 * S * 0.8; + + function frame() { + var t = (Date.now() - start) / duration, + s = easeOut(t) * S; + + if (t <= 1) { + this._flyToFrame = requestAnimFrame(frame, this); + + this._move( + this.unproject(from.add(to.subtract(from).multiplyBy(u(s) / u1)), startZoom), + this.getScaleZoom(w0 / w(s), startZoom), + {flyTo: true}); + + } else { + this + ._move(targetCenter, targetZoom) + ._moveEnd(true); + } + } + + this._moveStart(true, options.noMoveStart); + + frame.call(this); + return this; + }, + + // @method flyToBounds(bounds: LatLngBounds, options?: fitBounds options): this + // Sets the view of the map with a smooth animation like [`flyTo`](#map-flyto), + // but takes a bounds parameter like [`fitBounds`](#map-fitbounds). + flyToBounds: function (bounds, options) { + var target = this._getBoundsCenterZoom(bounds, options); + return this.flyTo(target.center, target.zoom, options); + }, + + // @method setMaxBounds(bounds: Bounds): this + // Restricts the map view to the given bounds (see the [maxBounds](#map-maxbounds) option). + setMaxBounds: function (bounds) { + bounds = toLatLngBounds(bounds); + + if (!bounds.isValid()) { + this.options.maxBounds = null; + return this.off('moveend', this._panInsideMaxBounds); + } else if (this.options.maxBounds) { + this.off('moveend', this._panInsideMaxBounds); + } + + this.options.maxBounds = bounds; + + if (this._loaded) { + this._panInsideMaxBounds(); + } + + return this.on('moveend', this._panInsideMaxBounds); + }, + + // @method setMinZoom(zoom: Number): this + // Sets the lower limit for the available zoom levels (see the [minZoom](#map-minzoom) option). + setMinZoom: function (zoom) { + var oldZoom = this.options.minZoom; + this.options.minZoom = zoom; + + if (this._loaded && oldZoom !== zoom) { + this.fire('zoomlevelschange'); + + if (this.getZoom() < this.options.minZoom) { + return this.setZoom(zoom); + } + } + + return this; + }, + + // @method setMaxZoom(zoom: Number): this + // Sets the upper limit for the available zoom levels (see the [maxZoom](#map-maxzoom) option). + setMaxZoom: function (zoom) { + var oldZoom = this.options.maxZoom; + this.options.maxZoom = zoom; + + if (this._loaded && oldZoom !== zoom) { + this.fire('zoomlevelschange'); + + if (this.getZoom() > this.options.maxZoom) { + return this.setZoom(zoom); + } + } + + return this; + }, + + // @method panInsideBounds(bounds: LatLngBounds, options?: Pan options): this + // Pans the map to the closest view that would lie inside the given bounds (if it's not already), controlling the animation using the options specific, if any. + panInsideBounds: function (bounds, options) { + this._enforcingBounds = true; + var center = this.getCenter(), + newCenter = this._limitCenter(center, this._zoom, toLatLngBounds(bounds)); + + if (!center.equals(newCenter)) { + this.panTo(newCenter, options); + } + + this._enforcingBounds = false; + return this; + }, + + // @method panInside(latlng: LatLng, options?: options): this + // Pans the map the minimum amount to make the `latlng` visible. Use + // `padding`, `paddingTopLeft` and `paddingTopRight` options to fit + // the display to more restricted bounds, like [`fitBounds`](#map-fitbounds). + // If `latlng` is already within the (optionally padded) display bounds, + // the map will not be panned. + panInside: function (latlng, options) { + options = options || {}; + + var paddingTL = toPoint(options.paddingTopLeft || options.padding || [0, 0]), + paddingBR = toPoint(options.paddingBottomRight || options.padding || [0, 0]), + center = this.getCenter(), + pixelCenter = this.project(center), + pixelPoint = this.project(latlng), + pixelBounds = this.getPixelBounds(), + halfPixelBounds = pixelBounds.getSize().divideBy(2), + paddedBounds = toBounds([pixelBounds.min.add(paddingTL), pixelBounds.max.subtract(paddingBR)]); + + if (!paddedBounds.contains(pixelPoint)) { + this._enforcingBounds = true; + var diff = pixelCenter.subtract(pixelPoint), + newCenter = toPoint(pixelPoint.x + diff.x, pixelPoint.y + diff.y); + + if (pixelPoint.x < paddedBounds.min.x || pixelPoint.x > paddedBounds.max.x) { + newCenter.x = pixelCenter.x - diff.x; + if (diff.x > 0) { + newCenter.x += halfPixelBounds.x - paddingTL.x; + } else { + newCenter.x -= halfPixelBounds.x - paddingBR.x; + } + } + if (pixelPoint.y < paddedBounds.min.y || pixelPoint.y > paddedBounds.max.y) { + newCenter.y = pixelCenter.y - diff.y; + if (diff.y > 0) { + newCenter.y += halfPixelBounds.y - paddingTL.y; + } else { + newCenter.y -= halfPixelBounds.y - paddingBR.y; + } + } + this.panTo(this.unproject(newCenter), options); + this._enforcingBounds = false; + } + return this; + }, + + // @method invalidateSize(options: Zoom/pan options): this + // Checks if the map container size changed and updates the map if so — + // call it after you've changed the map size dynamically, also animating + // pan by default. If `options.pan` is `false`, panning will not occur. + // If `options.debounceMoveend` is `true`, it will delay `moveend` event so + // that it doesn't happen often even if the method is called many + // times in a row. + + // @alternative + // @method invalidateSize(animate: Boolean): this + // Checks if the map container size changed and updates the map if so — + // call it after you've changed the map size dynamically, also animating + // pan by default. + invalidateSize: function (options) { + if (!this._loaded) { return this; } + + options = extend({ + animate: false, + pan: true + }, options === true ? {animate: true} : options); + + var oldSize = this.getSize(); + this._sizeChanged = true; + this._lastCenter = null; + + var newSize = this.getSize(), + oldCenter = oldSize.divideBy(2).round(), + newCenter = newSize.divideBy(2).round(), + offset = oldCenter.subtract(newCenter); + + if (!offset.x && !offset.y) { return this; } + + if (options.animate && options.pan) { + this.panBy(offset); + + } else { + if (options.pan) { + this._rawPanBy(offset); + } + + this.fire('move'); + + if (options.debounceMoveend) { + clearTimeout(this._sizeTimer); + this._sizeTimer = setTimeout(bind(this.fire, this, 'moveend'), 200); + } else { + this.fire('moveend'); + } + } + + // @section Map state change events + // @event resize: ResizeEvent + // Fired when the map is resized. + return this.fire('resize', { + oldSize: oldSize, + newSize: newSize + }); + }, + + // @section Methods for modifying map state + // @method stop(): this + // Stops the currently running `panTo` or `flyTo` animation, if any. + stop: function () { + this.setZoom(this._limitZoom(this._zoom)); + if (!this.options.zoomSnap) { + this.fire('viewreset'); + } + return this._stop(); + }, + + // @section Geolocation methods + // @method locate(options?: Locate options): this + // Tries to locate the user using the Geolocation API, firing a [`locationfound`](#map-locationfound) + // event with location data on success or a [`locationerror`](#map-locationerror) event on failure, + // and optionally sets the map view to the user's location with respect to + // detection accuracy (or to the world view if geolocation failed). + // Note that, if your page doesn't use HTTPS, this method will fail in + // modern browsers ([Chrome 50 and newer](https://sites.google.com/a/chromium.org/dev/Home/chromium-security/deprecating-powerful-features-on-insecure-origins)) + // See `Locate options` for more details. + locate: function (options) { + + options = this._locateOptions = extend({ + timeout: 10000, + watch: false + // setView: false + // maxZoom: + // maximumAge: 0 + // enableHighAccuracy: false + }, options); + + if (!('geolocation' in navigator)) { + this._handleGeolocationError({ + code: 0, + message: 'Geolocation not supported.' + }); + return this; + } + + var onResponse = bind(this._handleGeolocationResponse, this), + onError = bind(this._handleGeolocationError, this); + + if (options.watch) { + this._locationWatchId = + navigator.geolocation.watchPosition(onResponse, onError, options); + } else { + navigator.geolocation.getCurrentPosition(onResponse, onError, options); + } + return this; + }, + + // @method stopLocate(): this + // Stops watching location previously initiated by `map.locate({watch: true})` + // and aborts resetting the map view if map.locate was called with + // `{setView: true}`. + stopLocate: function () { + if (navigator.geolocation && navigator.geolocation.clearWatch) { + navigator.geolocation.clearWatch(this._locationWatchId); + } + if (this._locateOptions) { + this._locateOptions.setView = false; + } + return this; + }, + + _handleGeolocationError: function (error) { + var c = error.code, + message = error.message || + (c === 1 ? 'permission denied' : + (c === 2 ? 'position unavailable' : 'timeout')); + + if (this._locateOptions.setView && !this._loaded) { + this.fitWorld(); + } + + // @section Location events + // @event locationerror: ErrorEvent + // Fired when geolocation (using the [`locate`](#map-locate) method) failed. + this.fire('locationerror', { + code: c, + message: 'Geolocation error: ' + message + '.' + }); + }, + + _handleGeolocationResponse: function (pos) { + var lat = pos.coords.latitude, + lng = pos.coords.longitude, + latlng = new LatLng(lat, lng), + bounds = latlng.toBounds(pos.coords.accuracy * 2), + options = this._locateOptions; + + if (options.setView) { + var zoom = this.getBoundsZoom(bounds); + this.setView(latlng, options.maxZoom ? Math.min(zoom, options.maxZoom) : zoom); + } + + var data = { + latlng: latlng, + bounds: bounds, + timestamp: pos.timestamp + }; + + for (var i in pos.coords) { + if (typeof pos.coords[i] === 'number') { + data[i] = pos.coords[i]; + } + } + + // @event locationfound: LocationEvent + // Fired when geolocation (using the [`locate`](#map-locate) method) + // went successfully. + this.fire('locationfound', data); + }, + + // TODO Appropriate docs section? + // @section Other Methods + // @method addHandler(name: String, HandlerClass: Function): this + // Adds a new `Handler` to the map, given its name and constructor function. + addHandler: function (name, HandlerClass) { + if (!HandlerClass) { return this; } + + var handler = this[name] = new HandlerClass(this); + + this._handlers.push(handler); + + if (this.options[name]) { + handler.enable(); + } + + return this; + }, + + // @method remove(): this + // Destroys the map and clears all related event listeners. + remove: function () { + + this._initEvents(true); + + if (this._containerId !== this._container._leaflet_id) { + throw new Error('Map container is being reused by another instance'); + } + + try { + // throws error in IE6-8 + delete this._container._leaflet_id; + delete this._containerId; + } catch (e) { + /*eslint-disable */ + this._container._leaflet_id = undefined; + /* eslint-enable */ + this._containerId = undefined; + } + + if (this._locationWatchId !== undefined) { + this.stopLocate(); + } + + this._stop(); + + remove(this._mapPane); + + if (this._clearControlPos) { + this._clearControlPos(); + } + if (this._resizeRequest) { + cancelAnimFrame(this._resizeRequest); + this._resizeRequest = null; + } + + this._clearHandlers(); + + if (this._loaded) { + // @section Map state change events + // @event unload: Event + // Fired when the map is destroyed with [remove](#map-remove) method. + this.fire('unload'); + } + + var i; + for (i in this._layers) { + this._layers[i].remove(); + } + for (i in this._panes) { + remove(this._panes[i]); + } + + this._layers = []; + this._panes = []; + delete this._mapPane; + delete this._renderer; + + return this; + }, + + // @section Other Methods + // @method createPane(name: String, container?: HTMLElement): HTMLElement + // Creates a new [map pane](#map-pane) with the given name if it doesn't exist already, + // then returns it. The pane is created as a child of `container`, or + // as a child of the main map pane if not set. + createPane: function (name, container) { + var className = 'leaflet-pane' + (name ? ' leaflet-' + name.replace('Pane', '') + '-pane' : ''), + pane = create$1('div', className, container || this._mapPane); + + if (name) { + this._panes[name] = pane; + } + return pane; + }, + + // @section Methods for Getting Map State + + // @method getCenter(): LatLng + // Returns the geographical center of the map view + getCenter: function () { + this._checkIfLoaded(); + + if (this._lastCenter && !this._moved()) { + return this._lastCenter; + } + return this.layerPointToLatLng(this._getCenterLayerPoint()); + }, + + // @method getZoom(): Number + // Returns the current zoom level of the map view + getZoom: function () { + return this._zoom; + }, + + // @method getBounds(): LatLngBounds + // Returns the geographical bounds visible in the current map view + getBounds: function () { + var bounds = this.getPixelBounds(), + sw = this.unproject(bounds.getBottomLeft()), + ne = this.unproject(bounds.getTopRight()); + + return new LatLngBounds(sw, ne); + }, + + // @method getMinZoom(): Number + // Returns the minimum zoom level of the map (if set in the `minZoom` option of the map or of any layers), or `0` by default. + getMinZoom: function () { + return this.options.minZoom === undefined ? this._layersMinZoom || 0 : this.options.minZoom; + }, + + // @method getMaxZoom(): Number + // Returns the maximum zoom level of the map (if set in the `maxZoom` option of the map or of any layers). + getMaxZoom: function () { + return this.options.maxZoom === undefined ? + (this._layersMaxZoom === undefined ? Infinity : this._layersMaxZoom) : + this.options.maxZoom; + }, + + // @method getBoundsZoom(bounds: LatLngBounds, inside?: Boolean, padding?: Point): Number + // Returns the maximum zoom level on which the given bounds fit to the map + // view in its entirety. If `inside` (optional) is set to `true`, the method + // instead returns the minimum zoom level on which the map view fits into + // the given bounds in its entirety. + getBoundsZoom: function (bounds, inside, padding) { // (LatLngBounds[, Boolean, Point]) -> Number + bounds = toLatLngBounds(bounds); + padding = toPoint(padding || [0, 0]); + + var zoom = this.getZoom() || 0, + min = this.getMinZoom(), + max = this.getMaxZoom(), + nw = bounds.getNorthWest(), + se = bounds.getSouthEast(), + size = this.getSize().subtract(padding), + boundsSize = toBounds(this.project(se, zoom), this.project(nw, zoom)).getSize(), + snap = any3d ? this.options.zoomSnap : 1, + scalex = size.x / boundsSize.x, + scaley = size.y / boundsSize.y, + scale = inside ? Math.max(scalex, scaley) : Math.min(scalex, scaley); + + zoom = this.getScaleZoom(scale, zoom); + + if (snap) { + zoom = Math.round(zoom / (snap / 100)) * (snap / 100); // don't jump if within 1% of a snap level + zoom = inside ? Math.ceil(zoom / snap) * snap : Math.floor(zoom / snap) * snap; + } + + return Math.max(min, Math.min(max, zoom)); + }, + + // @method getSize(): Point + // Returns the current size of the map container (in pixels). + getSize: function () { + if (!this._size || this._sizeChanged) { + this._size = new Point( + this._container.clientWidth || 0, + this._container.clientHeight || 0); + + this._sizeChanged = false; + } + return this._size.clone(); + }, + + // @method getPixelBounds(): Bounds + // Returns the bounds of the current map view in projected pixel + // coordinates (sometimes useful in layer and overlay implementations). + getPixelBounds: function (center, zoom) { + var topLeftPoint = this._getTopLeftPoint(center, zoom); + return new Bounds(topLeftPoint, topLeftPoint.add(this.getSize())); + }, + + // TODO: Check semantics - isn't the pixel origin the 0,0 coord relative to + // the map pane? "left point of the map layer" can be confusing, specially + // since there can be negative offsets. + // @method getPixelOrigin(): Point + // Returns the projected pixel coordinates of the top left point of + // the map layer (useful in custom layer and overlay implementations). + getPixelOrigin: function () { + this._checkIfLoaded(); + return this._pixelOrigin; + }, + + // @method getPixelWorldBounds(zoom?: Number): Bounds + // Returns the world's bounds in pixel coordinates for zoom level `zoom`. + // If `zoom` is omitted, the map's current zoom level is used. + getPixelWorldBounds: function (zoom) { + return this.options.crs.getProjectedBounds(zoom === undefined ? this.getZoom() : zoom); + }, + + // @section Other Methods + + // @method getPane(pane: String|HTMLElement): HTMLElement + // Returns a [map pane](#map-pane), given its name or its HTML element (its identity). + getPane: function (pane) { + return typeof pane === 'string' ? this._panes[pane] : pane; + }, + + // @method getPanes(): Object + // Returns a plain object containing the names of all [panes](#map-pane) as keys and + // the panes as values. + getPanes: function () { + return this._panes; + }, + + // @method getContainer: HTMLElement + // Returns the HTML element that contains the map. + getContainer: function () { + return this._container; + }, + + + // @section Conversion Methods + + // @method getZoomScale(toZoom: Number, fromZoom: Number): Number + // Returns the scale factor to be applied to a map transition from zoom level + // `fromZoom` to `toZoom`. Used internally to help with zoom animations. + getZoomScale: function (toZoom, fromZoom) { + // TODO replace with universal implementation after refactoring projections + var crs = this.options.crs; + fromZoom = fromZoom === undefined ? this._zoom : fromZoom; + return crs.scale(toZoom) / crs.scale(fromZoom); + }, + + // @method getScaleZoom(scale: Number, fromZoom: Number): Number + // Returns the zoom level that the map would end up at, if it is at `fromZoom` + // level and everything is scaled by a factor of `scale`. Inverse of + // [`getZoomScale`](#map-getZoomScale). + getScaleZoom: function (scale, fromZoom) { + var crs = this.options.crs; + fromZoom = fromZoom === undefined ? this._zoom : fromZoom; + var zoom = crs.zoom(scale * crs.scale(fromZoom)); + return isNaN(zoom) ? Infinity : zoom; + }, + + // @method project(latlng: LatLng, zoom: Number): Point + // Projects a geographical coordinate `LatLng` according to the projection + // of the map's CRS, then scales it according to `zoom` and the CRS's + // `Transformation`. The result is pixel coordinate relative to + // the CRS origin. + project: function (latlng, zoom) { + zoom = zoom === undefined ? this._zoom : zoom; + return this.options.crs.latLngToPoint(toLatLng(latlng), zoom); + }, + + // @method unproject(point: Point, zoom: Number): LatLng + // Inverse of [`project`](#map-project). + unproject: function (point, zoom) { + zoom = zoom === undefined ? this._zoom : zoom; + return this.options.crs.pointToLatLng(toPoint(point), zoom); + }, + + // @method layerPointToLatLng(point: Point): LatLng + // Given a pixel coordinate relative to the [origin pixel](#map-getpixelorigin), + // returns the corresponding geographical coordinate (for the current zoom level). + layerPointToLatLng: function (point) { + var projectedPoint = toPoint(point).add(this.getPixelOrigin()); + return this.unproject(projectedPoint); + }, + + // @method latLngToLayerPoint(latlng: LatLng): Point + // Given a geographical coordinate, returns the corresponding pixel coordinate + // relative to the [origin pixel](#map-getpixelorigin). + latLngToLayerPoint: function (latlng) { + var projectedPoint = this.project(toLatLng(latlng))._round(); + return projectedPoint._subtract(this.getPixelOrigin()); + }, + + // @method wrapLatLng(latlng: LatLng): LatLng + // Returns a `LatLng` where `lat` and `lng` has been wrapped according to the + // map's CRS's `wrapLat` and `wrapLng` properties, if they are outside the + // CRS's bounds. + // By default this means longitude is wrapped around the dateline so its + // value is between -180 and +180 degrees. + wrapLatLng: function (latlng) { + return this.options.crs.wrapLatLng(toLatLng(latlng)); + }, + + // @method wrapLatLngBounds(bounds: LatLngBounds): LatLngBounds + // Returns a `LatLngBounds` with the same size as the given one, ensuring that + // its center is within the CRS's bounds. + // By default this means the center longitude is wrapped around the dateline so its + // value is between -180 and +180 degrees, and the majority of the bounds + // overlaps the CRS's bounds. + wrapLatLngBounds: function (latlng) { + return this.options.crs.wrapLatLngBounds(toLatLngBounds(latlng)); + }, + + // @method distance(latlng1: LatLng, latlng2: LatLng): Number + // Returns the distance between two geographical coordinates according to + // the map's CRS. By default this measures distance in meters. + distance: function (latlng1, latlng2) { + return this.options.crs.distance(toLatLng(latlng1), toLatLng(latlng2)); + }, + + // @method containerPointToLayerPoint(point: Point): Point + // Given a pixel coordinate relative to the map container, returns the corresponding + // pixel coordinate relative to the [origin pixel](#map-getpixelorigin). + containerPointToLayerPoint: function (point) { // (Point) + return toPoint(point).subtract(this._getMapPanePos()); + }, + + // @method layerPointToContainerPoint(point: Point): Point + // Given a pixel coordinate relative to the [origin pixel](#map-getpixelorigin), + // returns the corresponding pixel coordinate relative to the map container. + layerPointToContainerPoint: function (point) { // (Point) + return toPoint(point).add(this._getMapPanePos()); + }, + + // @method containerPointToLatLng(point: Point): LatLng + // Given a pixel coordinate relative to the map container, returns + // the corresponding geographical coordinate (for the current zoom level). + containerPointToLatLng: function (point) { + var layerPoint = this.containerPointToLayerPoint(toPoint(point)); + return this.layerPointToLatLng(layerPoint); + }, + + // @method latLngToContainerPoint(latlng: LatLng): Point + // Given a geographical coordinate, returns the corresponding pixel coordinate + // relative to the map container. + latLngToContainerPoint: function (latlng) { + return this.layerPointToContainerPoint(this.latLngToLayerPoint(toLatLng(latlng))); + }, + + // @method mouseEventToContainerPoint(ev: MouseEvent): Point + // Given a MouseEvent object, returns the pixel coordinate relative to the + // map container where the event took place. + mouseEventToContainerPoint: function (e) { + return getMousePosition(e, this._container); + }, + + // @method mouseEventToLayerPoint(ev: MouseEvent): Point + // Given a MouseEvent object, returns the pixel coordinate relative to + // the [origin pixel](#map-getpixelorigin) where the event took place. + mouseEventToLayerPoint: function (e) { + return this.containerPointToLayerPoint(this.mouseEventToContainerPoint(e)); + }, + + // @method mouseEventToLatLng(ev: MouseEvent): LatLng + // Given a MouseEvent object, returns geographical coordinate where the + // event took place. + mouseEventToLatLng: function (e) { // (MouseEvent) + return this.layerPointToLatLng(this.mouseEventToLayerPoint(e)); + }, + + + // map initialization methods + + _initContainer: function (id) { + var container = this._container = get(id); + + if (!container) { + throw new Error('Map container not found.'); + } else if (container._leaflet_id) { + throw new Error('Map container is already initialized.'); + } + + on(container, 'scroll', this._onScroll, this); + this._containerId = stamp(container); + }, + + _initLayout: function () { + var container = this._container; + + this._fadeAnimated = this.options.fadeAnimation && any3d; + + addClass(container, 'leaflet-container' + + (touch ? ' leaflet-touch' : '') + + (retina ? ' leaflet-retina' : '') + + (ielt9 ? ' leaflet-oldie' : '') + + (safari ? ' leaflet-safari' : '') + + (this._fadeAnimated ? ' leaflet-fade-anim' : '')); + + var position = getStyle(container, 'position'); + + if (position !== 'absolute' && position !== 'relative' && position !== 'fixed') { + container.style.position = 'relative'; + } + + this._initPanes(); + + if (this._initControlPos) { + this._initControlPos(); + } + }, + + _initPanes: function () { + var panes = this._panes = {}; + this._paneRenderers = {}; + + // @section + // + // Panes are DOM elements used to control the ordering of layers on the map. You + // can access panes with [`map.getPane`](#map-getpane) or + // [`map.getPanes`](#map-getpanes) methods. New panes can be created with the + // [`map.createPane`](#map-createpane) method. + // + // Every map has the following default panes that differ only in zIndex. + // + // @pane mapPane: HTMLElement = 'auto' + // Pane that contains all other map panes + + this._mapPane = this.createPane('mapPane', this._container); + setPosition(this._mapPane, new Point(0, 0)); + + // @pane tilePane: HTMLElement = 200 + // Pane for `GridLayer`s and `TileLayer`s + this.createPane('tilePane'); + // @pane overlayPane: HTMLElement = 400 + // Pane for vectors (`Path`s, like `Polyline`s and `Polygon`s), `ImageOverlay`s and `VideoOverlay`s + this.createPane('shadowPane'); + // @pane shadowPane: HTMLElement = 500 + // Pane for overlay shadows (e.g. `Marker` shadows) + this.createPane('overlayPane'); + // @pane markerPane: HTMLElement = 600 + // Pane for `Icon`s of `Marker`s + this.createPane('markerPane'); + // @pane tooltipPane: HTMLElement = 650 + // Pane for `Tooltip`s. + this.createPane('tooltipPane'); + // @pane popupPane: HTMLElement = 700 + // Pane for `Popup`s. + this.createPane('popupPane'); + + if (!this.options.markerZoomAnimation) { + addClass(panes.markerPane, 'leaflet-zoom-hide'); + addClass(panes.shadowPane, 'leaflet-zoom-hide'); + } + }, + + + // private methods that modify map state + + // @section Map state change events + _resetView: function (center, zoom) { + setPosition(this._mapPane, new Point(0, 0)); + + var loading = !this._loaded; + this._loaded = true; + zoom = this._limitZoom(zoom); + + this.fire('viewprereset'); + + var zoomChanged = this._zoom !== zoom; + this + ._moveStart(zoomChanged, false) + ._move(center, zoom) + ._moveEnd(zoomChanged); + + // @event viewreset: Event + // Fired when the map needs to redraw its content (this usually happens + // on map zoom or load). Very useful for creating custom overlays. + this.fire('viewreset'); + + // @event load: Event + // Fired when the map is initialized (when its center and zoom are set + // for the first time). + if (loading) { + this.fire('load'); + } + }, + + _moveStart: function (zoomChanged, noMoveStart) { + // @event zoomstart: Event + // Fired when the map zoom is about to change (e.g. before zoom animation). + // @event movestart: Event + // Fired when the view of the map starts changing (e.g. user starts dragging the map). + if (zoomChanged) { + this.fire('zoomstart'); + } + if (!noMoveStart) { + this.fire('movestart'); + } + return this; + }, + + _move: function (center, zoom, data) { + if (zoom === undefined) { + zoom = this._zoom; + } + var zoomChanged = this._zoom !== zoom; + + this._zoom = zoom; + this._lastCenter = center; + this._pixelOrigin = this._getNewPixelOrigin(center); + + // @event zoom: Event + // Fired repeatedly during any change in zoom level, including zoom + // and fly animations. + if (zoomChanged || (data && data.pinch)) { // Always fire 'zoom' if pinching because #3530 + this.fire('zoom', data); + } + + // @event move: Event + // Fired repeatedly during any movement of the map, including pan and + // fly animations. + return this.fire('move', data); + }, + + _moveEnd: function (zoomChanged) { + // @event zoomend: Event + // Fired when the map has changed, after any animations. + if (zoomChanged) { + this.fire('zoomend'); + } + + // @event moveend: Event + // Fired when the center of the map stops changing (e.g. user stopped + // dragging the map). + return this.fire('moveend'); + }, + + _stop: function () { + cancelAnimFrame(this._flyToFrame); + if (this._panAnim) { + this._panAnim.stop(); + } + return this; + }, + + _rawPanBy: function (offset) { + setPosition(this._mapPane, this._getMapPanePos().subtract(offset)); + }, + + _getZoomSpan: function () { + return this.getMaxZoom() - this.getMinZoom(); + }, + + _panInsideMaxBounds: function () { + if (!this._enforcingBounds) { + this.panInsideBounds(this.options.maxBounds); + } + }, + + _checkIfLoaded: function () { + if (!this._loaded) { + throw new Error('Set map center and zoom first.'); + } + }, + + // DOM event handling + + // @section Interaction events + _initEvents: function (remove$$1) { + this._targets = {}; + this._targets[stamp(this._container)] = this; + + var onOff = remove$$1 ? off : on; + + // @event click: MouseEvent + // Fired when the user clicks (or taps) the map. + // @event dblclick: MouseEvent + // Fired when the user double-clicks (or double-taps) the map. + // @event mousedown: MouseEvent + // Fired when the user pushes the mouse button on the map. + // @event mouseup: MouseEvent + // Fired when the user releases the mouse button on the map. + // @event mouseover: MouseEvent + // Fired when the mouse enters the map. + // @event mouseout: MouseEvent + // Fired when the mouse leaves the map. + // @event mousemove: MouseEvent + // Fired while the mouse moves over the map. + // @event contextmenu: MouseEvent + // Fired when the user pushes the right mouse button on the map, prevents + // default browser context menu from showing if there are listeners on + // this event. Also fired on mobile when the user holds a single touch + // for a second (also called long press). + // @event keypress: KeyboardEvent + // Fired when the user presses a key from the keyboard that produces a character value while the map is focused. + // @event keydown: KeyboardEvent + // Fired when the user presses a key from the keyboard while the map is focused. Unlike the `keypress` event, + // the `keydown` event is fired for keys that produce a character value and for keys + // that do not produce a character value. + // @event keyup: KeyboardEvent + // Fired when the user releases a key from the keyboard while the map is focused. + onOff(this._container, 'click dblclick mousedown mouseup ' + + 'mouseover mouseout mousemove contextmenu keypress keydown keyup', this._handleDOMEvent, this); + + if (this.options.trackResize) { + onOff(window, 'resize', this._onResize, this); + } + + if (any3d && this.options.transform3DLimit) { + (remove$$1 ? this.off : this.on).call(this, 'moveend', this._onMoveEnd); + } + }, + + _onResize: function () { + cancelAnimFrame(this._resizeRequest); + this._resizeRequest = requestAnimFrame( + function () { this.invalidateSize({debounceMoveend: true}); }, this); + }, + + _onScroll: function () { + this._container.scrollTop = 0; + this._container.scrollLeft = 0; + }, + + _onMoveEnd: function () { + var pos = this._getMapPanePos(); + if (Math.max(Math.abs(pos.x), Math.abs(pos.y)) >= this.options.transform3DLimit) { + // https://bugzilla.mozilla.org/show_bug.cgi?id=1203873 but Webkit also have + // a pixel offset on very high values, see: http://jsfiddle.net/dg6r5hhb/ + this._resetView(this.getCenter(), this.getZoom()); + } + }, + + _findEventTargets: function (e, type) { + var targets = [], + target, + isHover = type === 'mouseout' || type === 'mouseover', + src = e.target || e.srcElement, + dragging = false; + + while (src) { + target = this._targets[stamp(src)]; + if (target && (type === 'click' || type === 'preclick') && !e._simulated && this._draggableMoved(target)) { + // Prevent firing click after you just dragged an object. + dragging = true; + break; + } + if (target && target.listens(type, true)) { + if (isHover && !isExternalTarget(src, e)) { break; } + targets.push(target); + if (isHover) { break; } + } + if (src === this._container) { break; } + src = src.parentNode; + } + if (!targets.length && !dragging && !isHover && isExternalTarget(src, e)) { + targets = [this]; + } + return targets; + }, + + _handleDOMEvent: function (e) { + if (!this._loaded || skipped(e)) { return; } + + var type = e.type; + + if (type === 'mousedown' || type === 'keypress' || type === 'keyup' || type === 'keydown') { + // prevents outline when clicking on keyboard-focusable element + preventOutline(e.target || e.srcElement); + } + + this._fireDOMEvent(e, type); + }, + + _mouseEvents: ['click', 'dblclick', 'mouseover', 'mouseout', 'contextmenu'], + + _fireDOMEvent: function (e, type, targets) { + + if (e.type === 'click') { + // Fire a synthetic 'preclick' event which propagates up (mainly for closing popups). + // @event preclick: MouseEvent + // Fired before mouse click on the map (sometimes useful when you + // want something to happen on click before any existing click + // handlers start running). + var synth = extend({}, e); + synth.type = 'preclick'; + this._fireDOMEvent(synth, synth.type, targets); + } + + if (e._stopped) { return; } + + // Find the layer the event is propagating from and its parents. + targets = (targets || []).concat(this._findEventTargets(e, type)); + + if (!targets.length) { return; } + + var target = targets[0]; + if (type === 'contextmenu' && target.listens(type, true)) { + preventDefault(e); + } + + var data = { + originalEvent: e + }; + + if (e.type !== 'keypress' && e.type !== 'keydown' && e.type !== 'keyup') { + var isMarker = target.getLatLng && (!target._radius || target._radius <= 10); + data.containerPoint = isMarker ? + this.latLngToContainerPoint(target.getLatLng()) : this.mouseEventToContainerPoint(e); + data.layerPoint = this.containerPointToLayerPoint(data.containerPoint); + data.latlng = isMarker ? target.getLatLng() : this.layerPointToLatLng(data.layerPoint); + } + + for (var i = 0; i < targets.length; i++) { + targets[i].fire(type, data, true); + if (data.originalEvent._stopped || + (targets[i].options.bubblingMouseEvents === false && indexOf(this._mouseEvents, type) !== -1)) { return; } + } + }, + + _draggableMoved: function (obj) { + obj = obj.dragging && obj.dragging.enabled() ? obj : this; + return (obj.dragging && obj.dragging.moved()) || (this.boxZoom && this.boxZoom.moved()); + }, + + _clearHandlers: function () { + for (var i = 0, len = this._handlers.length; i < len; i++) { + this._handlers[i].disable(); + } + }, + + // @section Other Methods + + // @method whenReady(fn: Function, context?: Object): this + // Runs the given function `fn` when the map gets initialized with + // a view (center and zoom) and at least one layer, or immediately + // if it's already initialized, optionally passing a function context. + whenReady: function (callback, context) { + if (this._loaded) { + callback.call(context || this, {target: this}); + } else { + this.on('load', callback, context); + } + return this; + }, + + + // private methods for getting map state + + _getMapPanePos: function () { + return getPosition(this._mapPane) || new Point(0, 0); + }, + + _moved: function () { + var pos = this._getMapPanePos(); + return pos && !pos.equals([0, 0]); + }, + + _getTopLeftPoint: function (center, zoom) { + var pixelOrigin = center && zoom !== undefined ? + this._getNewPixelOrigin(center, zoom) : + this.getPixelOrigin(); + return pixelOrigin.subtract(this._getMapPanePos()); + }, + + _getNewPixelOrigin: function (center, zoom) { + var viewHalf = this.getSize()._divideBy(2); + return this.project(center, zoom)._subtract(viewHalf)._add(this._getMapPanePos())._round(); + }, + + _latLngToNewLayerPoint: function (latlng, zoom, center) { + var topLeft = this._getNewPixelOrigin(center, zoom); + return this.project(latlng, zoom)._subtract(topLeft); + }, + + _latLngBoundsToNewLayerBounds: function (latLngBounds, zoom, center) { + var topLeft = this._getNewPixelOrigin(center, zoom); + return toBounds([ + this.project(latLngBounds.getSouthWest(), zoom)._subtract(topLeft), + this.project(latLngBounds.getNorthWest(), zoom)._subtract(topLeft), + this.project(latLngBounds.getSouthEast(), zoom)._subtract(topLeft), + this.project(latLngBounds.getNorthEast(), zoom)._subtract(topLeft) + ]); + }, + + // layer point of the current center + _getCenterLayerPoint: function () { + return this.containerPointToLayerPoint(this.getSize()._divideBy(2)); + }, + + // offset of the specified place to the current center in pixels + _getCenterOffset: function (latlng) { + return this.latLngToLayerPoint(latlng).subtract(this._getCenterLayerPoint()); + }, + + // adjust center for view to get inside bounds + _limitCenter: function (center, zoom, bounds) { + + if (!bounds) { return center; } + + var centerPoint = this.project(center, zoom), + viewHalf = this.getSize().divideBy(2), + viewBounds = new Bounds(centerPoint.subtract(viewHalf), centerPoint.add(viewHalf)), + offset = this._getBoundsOffset(viewBounds, bounds, zoom); + + // If offset is less than a pixel, ignore. + // This prevents unstable projections from getting into + // an infinite loop of tiny offsets. + if (offset.round().equals([0, 0])) { + return center; + } + + return this.unproject(centerPoint.add(offset), zoom); + }, + + // adjust offset for view to get inside bounds + _limitOffset: function (offset, bounds) { + if (!bounds) { return offset; } + + var viewBounds = this.getPixelBounds(), + newBounds = new Bounds(viewBounds.min.add(offset), viewBounds.max.add(offset)); + + return offset.add(this._getBoundsOffset(newBounds, bounds)); + }, + + // returns offset needed for pxBounds to get inside maxBounds at a specified zoom + _getBoundsOffset: function (pxBounds, maxBounds, zoom) { + var projectedMaxBounds = toBounds( + this.project(maxBounds.getNorthEast(), zoom), + this.project(maxBounds.getSouthWest(), zoom) + ), + minOffset = projectedMaxBounds.min.subtract(pxBounds.min), + maxOffset = projectedMaxBounds.max.subtract(pxBounds.max), + + dx = this._rebound(minOffset.x, -maxOffset.x), + dy = this._rebound(minOffset.y, -maxOffset.y); + + return new Point(dx, dy); + }, + + _rebound: function (left, right) { + return left + right > 0 ? + Math.round(left - right) / 2 : + Math.max(0, Math.ceil(left)) - Math.max(0, Math.floor(right)); + }, + + _limitZoom: function (zoom) { + var min = this.getMinZoom(), + max = this.getMaxZoom(), + snap = any3d ? this.options.zoomSnap : 1; + if (snap) { + zoom = Math.round(zoom / snap) * snap; + } + return Math.max(min, Math.min(max, zoom)); + }, + + _onPanTransitionStep: function () { + this.fire('move'); + }, + + _onPanTransitionEnd: function () { + removeClass(this._mapPane, 'leaflet-pan-anim'); + this.fire('moveend'); + }, + + _tryAnimatedPan: function (center, options) { + // difference between the new and current centers in pixels + var offset = this._getCenterOffset(center)._trunc(); + + // don't animate too far unless animate: true specified in options + if ((options && options.animate) !== true && !this.getSize().contains(offset)) { return false; } + + this.panBy(offset, options); + + return true; + }, + + _createAnimProxy: function () { + + var proxy = this._proxy = create$1('div', 'leaflet-proxy leaflet-zoom-animated'); + this._panes.mapPane.appendChild(proxy); + + this.on('zoomanim', function (e) { + var prop = TRANSFORM, + transform = this._proxy.style[prop]; + + setTransform(this._proxy, this.project(e.center, e.zoom), this.getZoomScale(e.zoom, 1)); + + // workaround for case when transform is the same and so transitionend event is not fired + if (transform === this._proxy.style[prop] && this._animatingZoom) { + this._onZoomTransitionEnd(); + } + }, this); + + this.on('load moveend', this._animMoveEnd, this); + + this._on('unload', this._destroyAnimProxy, this); + }, + + _destroyAnimProxy: function () { + remove(this._proxy); + this.off('load moveend', this._animMoveEnd, this); + delete this._proxy; + }, + + _animMoveEnd: function () { + var c = this.getCenter(), + z = this.getZoom(); + setTransform(this._proxy, this.project(c, z), this.getZoomScale(z, 1)); + }, + + _catchTransitionEnd: function (e) { + if (this._animatingZoom && e.propertyName.indexOf('transform') >= 0) { + this._onZoomTransitionEnd(); + } + }, + + _nothingToAnimate: function () { + return !this._container.getElementsByClassName('leaflet-zoom-animated').length; + }, + + _tryAnimatedZoom: function (center, zoom, options) { + + if (this._animatingZoom) { return true; } + + options = options || {}; + + // don't animate if disabled, not supported or zoom difference is too large + if (!this._zoomAnimated || options.animate === false || this._nothingToAnimate() || + Math.abs(zoom - this._zoom) > this.options.zoomAnimationThreshold) { return false; } + + // offset is the pixel coords of the zoom origin relative to the current center + var scale = this.getZoomScale(zoom), + offset = this._getCenterOffset(center)._divideBy(1 - 1 / scale); + + // don't animate if the zoom origin isn't within one screen from the current center, unless forced + if (options.animate !== true && !this.getSize().contains(offset)) { return false; } + + requestAnimFrame(function () { + this + ._moveStart(true, false) + ._animateZoom(center, zoom, true); + }, this); + + return true; + }, + + _animateZoom: function (center, zoom, startAnim, noUpdate) { + if (!this._mapPane) { return; } + + if (startAnim) { + this._animatingZoom = true; + + // remember what center/zoom to set after animation + this._animateToCenter = center; + this._animateToZoom = zoom; + + addClass(this._mapPane, 'leaflet-zoom-anim'); + } + + // @section Other Events + // @event zoomanim: ZoomAnimEvent + // Fired at least once per zoom animation. For continuous zoom, like pinch zooming, fired once per frame during zoom. + this.fire('zoomanim', { + center: center, + zoom: zoom, + noUpdate: noUpdate + }); + + // Work around webkit not firing 'transitionend', see https://github.com/Leaflet/Leaflet/issues/3689, 2693 + setTimeout(bind(this._onZoomTransitionEnd, this), 250); + }, + + _onZoomTransitionEnd: function () { + if (!this._animatingZoom) { return; } + + if (this._mapPane) { + removeClass(this._mapPane, 'leaflet-zoom-anim'); + } + + this._animatingZoom = false; + + this._move(this._animateToCenter, this._animateToZoom); + + // This anim frame should prevent an obscure iOS webkit tile loading race condition. + requestAnimFrame(function () { + this._moveEnd(true); + }, this); + } +}); + +// @section + +// @factory L.map(id: String, options?: Map options) +// Instantiates a map object given the DOM ID of a `
` element +// and optionally an object literal with `Map options`. +// +// @alternative +// @factory L.map(el: HTMLElement, options?: Map options) +// Instantiates a map object given an instance of a `
` HTML element +// and optionally an object literal with `Map options`. +function createMap(id, options) { + return new Map(id, options); +} + +/* + * @class Control + * @aka L.Control + * @inherits Class + * + * L.Control is a base class for implementing map controls. Handles positioning. + * All other controls extend from this class. + */ + +var Control = Class.extend({ + // @section + // @aka Control options + options: { + // @option position: String = 'topright' + // The position of the control (one of the map corners). Possible values are `'topleft'`, + // `'topright'`, `'bottomleft'` or `'bottomright'` + position: 'topright' + }, + + initialize: function (options) { + setOptions(this, options); + }, + + /* @section + * Classes extending L.Control will inherit the following methods: + * + * @method getPosition: string + * Returns the position of the control. + */ + getPosition: function () { + return this.options.position; + }, + + // @method setPosition(position: string): this + // Sets the position of the control. + setPosition: function (position) { + var map = this._map; + + if (map) { + map.removeControl(this); + } + + this.options.position = position; + + if (map) { + map.addControl(this); + } + + return this; + }, + + // @method getContainer: HTMLElement + // Returns the HTMLElement that contains the control. + getContainer: function () { + return this._container; + }, + + // @method addTo(map: Map): this + // Adds the control to the given map. + addTo: function (map) { + this.remove(); + this._map = map; + + var container = this._container = this.onAdd(map), + pos = this.getPosition(), + corner = map._controlCorners[pos]; + + addClass(container, 'leaflet-control'); + + if (pos.indexOf('bottom') !== -1) { + corner.insertBefore(container, corner.firstChild); + } else { + corner.appendChild(container); + } + + this._map.on('unload', this.remove, this); + + return this; + }, + + // @method remove: this + // Removes the control from the map it is currently active on. + remove: function () { + if (!this._map) { + return this; + } + + remove(this._container); + + if (this.onRemove) { + this.onRemove(this._map); + } + + this._map.off('unload', this.remove, this); + this._map = null; + + return this; + }, + + _refocusOnMap: function (e) { + // if map exists and event is not a keyboard event + if (this._map && e && e.screenX > 0 && e.screenY > 0) { + this._map.getContainer().focus(); + } + } +}); + +var control = function (options) { + return new Control(options); +}; + +/* @section Extension methods + * @uninheritable + * + * Every control should extend from `L.Control` and (re-)implement the following methods. + * + * @method onAdd(map: Map): HTMLElement + * Should return the container DOM element for the control and add listeners on relevant map events. Called on [`control.addTo(map)`](#control-addTo). + * + * @method onRemove(map: Map) + * Optional method. Should contain all clean up code that removes the listeners previously added in [`onAdd`](#control-onadd). Called on [`control.remove()`](#control-remove). + */ + +/* @namespace Map + * @section Methods for Layers and Controls + */ +Map.include({ + // @method addControl(control: Control): this + // Adds the given control to the map + addControl: function (control) { + control.addTo(this); + return this; + }, + + // @method removeControl(control: Control): this + // Removes the given control from the map + removeControl: function (control) { + control.remove(); + return this; + }, + + _initControlPos: function () { + var corners = this._controlCorners = {}, + l = 'leaflet-', + container = this._controlContainer = + create$1('div', l + 'control-container', this._container); + + function createCorner(vSide, hSide) { + var className = l + vSide + ' ' + l + hSide; + + corners[vSide + hSide] = create$1('div', className, container); + } + + createCorner('top', 'left'); + createCorner('top', 'right'); + createCorner('bottom', 'left'); + createCorner('bottom', 'right'); + }, + + _clearControlPos: function () { + for (var i in this._controlCorners) { + remove(this._controlCorners[i]); + } + remove(this._controlContainer); + delete this._controlCorners; + delete this._controlContainer; + } +}); + +/* + * @class Control.Layers + * @aka L.Control.Layers + * @inherits Control + * + * The layers control gives users the ability to switch between different base layers and switch overlays on/off (check out the [detailed example](http://leafletjs.com/examples/layers-control/)). Extends `Control`. + * + * @example + * + * ```js + * var baseLayers = { + * "Mapbox": mapbox, + * "OpenStreetMap": osm + * }; + * + * var overlays = { + * "Marker": marker, + * "Roads": roadsLayer + * }; + * + * L.control.layers(baseLayers, overlays).addTo(map); + * ``` + * + * The `baseLayers` and `overlays` parameters are object literals with layer names as keys and `Layer` objects as values: + * + * ```js + * { + * "": layer1, + * "": layer2 + * } + * ``` + * + * The layer names can contain HTML, which allows you to add additional styling to the items: + * + * ```js + * {" My Layer": myLayer} + * ``` + */ + +var Layers = Control.extend({ + // @section + // @aka Control.Layers options + options: { + // @option collapsed: Boolean = true + // If `true`, the control will be collapsed into an icon and expanded on mouse hover or touch. + collapsed: true, + position: 'topright', + + // @option autoZIndex: Boolean = true + // If `true`, the control will assign zIndexes in increasing order to all of its layers so that the order is preserved when switching them on/off. + autoZIndex: true, + + // @option hideSingleBase: Boolean = false + // If `true`, the base layers in the control will be hidden when there is only one. + hideSingleBase: false, + + // @option sortLayers: Boolean = false + // Whether to sort the layers. When `false`, layers will keep the order + // in which they were added to the control. + sortLayers: false, + + // @option sortFunction: Function = * + // A [compare function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) + // that will be used for sorting the layers, when `sortLayers` is `true`. + // The function receives both the `L.Layer` instances and their names, as in + // `sortFunction(layerA, layerB, nameA, nameB)`. + // By default, it sorts layers alphabetically by their name. + sortFunction: function (layerA, layerB, nameA, nameB) { + return nameA < nameB ? -1 : (nameB < nameA ? 1 : 0); + } + }, + + initialize: function (baseLayers, overlays, options) { + setOptions(this, options); + + this._layerControlInputs = []; + this._layers = []; + this._lastZIndex = 0; + this._handlingClick = false; + + for (var i in baseLayers) { + this._addLayer(baseLayers[i], i); + } + + for (i in overlays) { + this._addLayer(overlays[i], i, true); + } + }, + + onAdd: function (map) { + this._initLayout(); + this._update(); + + this._map = map; + map.on('zoomend', this._checkDisabledLayers, this); + + for (var i = 0; i < this._layers.length; i++) { + this._layers[i].layer.on('add remove', this._onLayerChange, this); + } + + return this._container; + }, + + addTo: function (map) { + Control.prototype.addTo.call(this, map); + // Trigger expand after Layers Control has been inserted into DOM so that is now has an actual height. + return this._expandIfNotCollapsed(); + }, + + onRemove: function () { + this._map.off('zoomend', this._checkDisabledLayers, this); + + for (var i = 0; i < this._layers.length; i++) { + this._layers[i].layer.off('add remove', this._onLayerChange, this); + } + }, + + // @method addBaseLayer(layer: Layer, name: String): this + // Adds a base layer (radio button entry) with the given name to the control. + addBaseLayer: function (layer, name) { + this._addLayer(layer, name); + return (this._map) ? this._update() : this; + }, + + // @method addOverlay(layer: Layer, name: String): this + // Adds an overlay (checkbox entry) with the given name to the control. + addOverlay: function (layer, name) { + this._addLayer(layer, name, true); + return (this._map) ? this._update() : this; + }, + + // @method removeLayer(layer: Layer): this + // Remove the given layer from the control. + removeLayer: function (layer) { + layer.off('add remove', this._onLayerChange, this); + + var obj = this._getLayer(stamp(layer)); + if (obj) { + this._layers.splice(this._layers.indexOf(obj), 1); + } + return (this._map) ? this._update() : this; + }, + + // @method expand(): this + // Expand the control container if collapsed. + expand: function () { + addClass(this._container, 'leaflet-control-layers-expanded'); + this._section.style.height = null; + var acceptableHeight = this._map.getSize().y - (this._container.offsetTop + 50); + if (acceptableHeight < this._section.clientHeight) { + addClass(this._section, 'leaflet-control-layers-scrollbar'); + this._section.style.height = acceptableHeight + 'px'; + } else { + removeClass(this._section, 'leaflet-control-layers-scrollbar'); + } + this._checkDisabledLayers(); + return this; + }, + + // @method collapse(): this + // Collapse the control container if expanded. + collapse: function () { + removeClass(this._container, 'leaflet-control-layers-expanded'); + return this; + }, + + _initLayout: function () { + var className = 'leaflet-control-layers', + container = this._container = create$1('div', className), + collapsed = this.options.collapsed; + + // makes this work on IE touch devices by stopping it from firing a mouseout event when the touch is released + container.setAttribute('aria-haspopup', true); + + disableClickPropagation(container); + disableScrollPropagation(container); + + var section = this._section = create$1('section', className + '-list'); + + if (collapsed) { + this._map.on('click', this.collapse, this); + + if (!android) { + on(container, { + mouseenter: this.expand, + mouseleave: this.collapse + }, this); + } + } + + var link = this._layersLink = create$1('a', className + '-toggle', container); + link.href = '#'; + link.title = 'Layers'; + + if (touch) { + on(link, 'click', stop); + on(link, 'click', this.expand, this); + } else { + on(link, 'focus', this.expand, this); + } + + if (!collapsed) { + this.expand(); + } + + this._baseLayersList = create$1('div', className + '-base', section); + this._separator = create$1('div', className + '-separator', section); + this._overlaysList = create$1('div', className + '-overlays', section); + + container.appendChild(section); + }, + + _getLayer: function (id) { + for (var i = 0; i < this._layers.length; i++) { + + if (this._layers[i] && stamp(this._layers[i].layer) === id) { + return this._layers[i]; + } + } + }, + + _addLayer: function (layer, name, overlay) { + if (this._map) { + layer.on('add remove', this._onLayerChange, this); + } + + this._layers.push({ + layer: layer, + name: name, + overlay: overlay + }); + + if (this.options.sortLayers) { + this._layers.sort(bind(function (a, b) { + return this.options.sortFunction(a.layer, b.layer, a.name, b.name); + }, this)); + } + + if (this.options.autoZIndex && layer.setZIndex) { + this._lastZIndex++; + layer.setZIndex(this._lastZIndex); + } + + this._expandIfNotCollapsed(); + }, + + _update: function () { + if (!this._container) { return this; } + + empty(this._baseLayersList); + empty(this._overlaysList); + + this._layerControlInputs = []; + var baseLayersPresent, overlaysPresent, i, obj, baseLayersCount = 0; + + for (i = 0; i < this._layers.length; i++) { + obj = this._layers[i]; + this._addItem(obj); + overlaysPresent = overlaysPresent || obj.overlay; + baseLayersPresent = baseLayersPresent || !obj.overlay; + baseLayersCount += !obj.overlay ? 1 : 0; + } + + // Hide base layers section if there's only one layer. + if (this.options.hideSingleBase) { + baseLayersPresent = baseLayersPresent && baseLayersCount > 1; + this._baseLayersList.style.display = baseLayersPresent ? '' : 'none'; + } + + this._separator.style.display = overlaysPresent && baseLayersPresent ? '' : 'none'; + + return this; + }, + + _onLayerChange: function (e) { + if (!this._handlingClick) { + this._update(); + } + + var obj = this._getLayer(stamp(e.target)); + + // @namespace Map + // @section Layer events + // @event baselayerchange: LayersControlEvent + // Fired when the base layer is changed through the [layer control](#control-layers). + // @event overlayadd: LayersControlEvent + // Fired when an overlay is selected through the [layer control](#control-layers). + // @event overlayremove: LayersControlEvent + // Fired when an overlay is deselected through the [layer control](#control-layers). + // @namespace Control.Layers + var type = obj.overlay ? + (e.type === 'add' ? 'overlayadd' : 'overlayremove') : + (e.type === 'add' ? 'baselayerchange' : null); + + if (type) { + this._map.fire(type, obj); + } + }, + + // IE7 bugs out if you create a radio dynamically, so you have to do it this hacky way (see http://bit.ly/PqYLBe) + _createRadioElement: function (name, checked) { + + var radioHtml = ''; + + var radioFragment = document.createElement('div'); + radioFragment.innerHTML = radioHtml; + + return radioFragment.firstChild; + }, + + _addItem: function (obj) { + var label = document.createElement('label'), + checked = this._map.hasLayer(obj.layer), + input; + + if (obj.overlay) { + input = document.createElement('input'); + input.type = 'checkbox'; + input.className = 'leaflet-control-layers-selector'; + input.defaultChecked = checked; + } else { + input = this._createRadioElement('leaflet-base-layers_' + stamp(this), checked); + } + + this._layerControlInputs.push(input); + input.layerId = stamp(obj.layer); + + on(input, 'click', this._onInputClick, this); + + var name = document.createElement('span'); + name.innerHTML = ' ' + obj.name; + + // Helps from preventing layer control flicker when checkboxes are disabled + // https://github.com/Leaflet/Leaflet/issues/2771 + var holder = document.createElement('div'); + + label.appendChild(holder); + holder.appendChild(input); + holder.appendChild(name); + + var container = obj.overlay ? this._overlaysList : this._baseLayersList; + container.appendChild(label); + + this._checkDisabledLayers(); + return label; + }, + + _onInputClick: function () { + var inputs = this._layerControlInputs, + input, layer; + var addedLayers = [], + removedLayers = []; + + this._handlingClick = true; + + for (var i = inputs.length - 1; i >= 0; i--) { + input = inputs[i]; + layer = this._getLayer(input.layerId).layer; + + if (input.checked) { + addedLayers.push(layer); + } else if (!input.checked) { + removedLayers.push(layer); + } + } + + // Bugfix issue 2318: Should remove all old layers before readding new ones + for (i = 0; i < removedLayers.length; i++) { + if (this._map.hasLayer(removedLayers[i])) { + this._map.removeLayer(removedLayers[i]); + } + } + for (i = 0; i < addedLayers.length; i++) { + if (!this._map.hasLayer(addedLayers[i])) { + this._map.addLayer(addedLayers[i]); + } + } + + this._handlingClick = false; + + this._refocusOnMap(); + }, + + _checkDisabledLayers: function () { + var inputs = this._layerControlInputs, + input, + layer, + zoom = this._map.getZoom(); + + for (var i = inputs.length - 1; i >= 0; i--) { + input = inputs[i]; + layer = this._getLayer(input.layerId).layer; + input.disabled = (layer.options.minZoom !== undefined && zoom < layer.options.minZoom) || + (layer.options.maxZoom !== undefined && zoom > layer.options.maxZoom); + + } + }, + + _expandIfNotCollapsed: function () { + if (this._map && !this.options.collapsed) { + this.expand(); + } + return this; + }, + + _expand: function () { + // Backward compatibility, remove me in 1.1. + return this.expand(); + }, + + _collapse: function () { + // Backward compatibility, remove me in 1.1. + return this.collapse(); + } + +}); + + +// @factory L.control.layers(baselayers?: Object, overlays?: Object, options?: Control.Layers options) +// Creates a layers control with the given layers. Base layers will be switched with radio buttons, while overlays will be switched with checkboxes. Note that all base layers should be passed in the base layers object, but only one should be added to the map during map instantiation. +var layers = function (baseLayers, overlays, options) { + return new Layers(baseLayers, overlays, options); +}; + +/* + * @class Control.Zoom + * @aka L.Control.Zoom + * @inherits Control + * + * A basic zoom control with two buttons (zoom in and zoom out). It is put on the map by default unless you set its [`zoomControl` option](#map-zoomcontrol) to `false`. Extends `Control`. + */ + +var Zoom = Control.extend({ + // @section + // @aka Control.Zoom options + options: { + position: 'topleft', + + // @option zoomInText: String = '+' + // The text set on the 'zoom in' button. + zoomInText: '+', + + // @option zoomInTitle: String = 'Zoom in' + // The title set on the 'zoom in' button. + zoomInTitle: 'Zoom in', + + // @option zoomOutText: String = '−' + // The text set on the 'zoom out' button. + zoomOutText: '−', + + // @option zoomOutTitle: String = 'Zoom out' + // The title set on the 'zoom out' button. + zoomOutTitle: 'Zoom out' + }, + + onAdd: function (map) { + var zoomName = 'leaflet-control-zoom', + container = create$1('div', zoomName + ' leaflet-bar'), + options = this.options; + + this._zoomInButton = this._createButton(options.zoomInText, options.zoomInTitle, + zoomName + '-in', container, this._zoomIn); + this._zoomOutButton = this._createButton(options.zoomOutText, options.zoomOutTitle, + zoomName + '-out', container, this._zoomOut); + + this._updateDisabled(); + map.on('zoomend zoomlevelschange', this._updateDisabled, this); + + return container; + }, + + onRemove: function (map) { + map.off('zoomend zoomlevelschange', this._updateDisabled, this); + }, + + disable: function () { + this._disabled = true; + this._updateDisabled(); + return this; + }, + + enable: function () { + this._disabled = false; + this._updateDisabled(); + return this; + }, + + _zoomIn: function (e) { + if (!this._disabled && this._map._zoom < this._map.getMaxZoom()) { + this._map.zoomIn(this._map.options.zoomDelta * (e.shiftKey ? 3 : 1)); + } + }, + + _zoomOut: function (e) { + if (!this._disabled && this._map._zoom > this._map.getMinZoom()) { + this._map.zoomOut(this._map.options.zoomDelta * (e.shiftKey ? 3 : 1)); + } + }, + + _createButton: function (html, title, className, container, fn) { + var link = create$1('a', className, container); + link.innerHTML = html; + link.href = '#'; + link.title = title; + + /* + * Will force screen readers like VoiceOver to read this as "Zoom in - button" + */ + link.setAttribute('role', 'button'); + link.setAttribute('aria-label', title); + + disableClickPropagation(link); + on(link, 'click', stop); + on(link, 'click', fn, this); + on(link, 'click', this._refocusOnMap, this); + + return link; + }, + + _updateDisabled: function () { + var map = this._map, + className = 'leaflet-disabled'; + + removeClass(this._zoomInButton, className); + removeClass(this._zoomOutButton, className); + + if (this._disabled || map._zoom === map.getMinZoom()) { + addClass(this._zoomOutButton, className); + } + if (this._disabled || map._zoom === map.getMaxZoom()) { + addClass(this._zoomInButton, className); + } + } +}); + +// @namespace Map +// @section Control options +// @option zoomControl: Boolean = true +// Whether a [zoom control](#control-zoom) is added to the map by default. +Map.mergeOptions({ + zoomControl: true +}); + +Map.addInitHook(function () { + if (this.options.zoomControl) { + // @section Controls + // @property zoomControl: Control.Zoom + // The default zoom control (only available if the + // [`zoomControl` option](#map-zoomcontrol) was `true` when creating the map). + this.zoomControl = new Zoom(); + this.addControl(this.zoomControl); + } +}); + +// @namespace Control.Zoom +// @factory L.control.zoom(options: Control.Zoom options) +// Creates a zoom control +var zoom = function (options) { + return new Zoom(options); +}; + +/* + * @class Control.Scale + * @aka L.Control.Scale + * @inherits Control + * + * A simple scale control that shows the scale of the current center of screen in metric (m/km) and imperial (mi/ft) systems. Extends `Control`. + * + * @example + * + * ```js + * L.control.scale().addTo(map); + * ``` + */ + +var Scale = Control.extend({ + // @section + // @aka Control.Scale options + options: { + position: 'bottomleft', + + // @option maxWidth: Number = 100 + // Maximum width of the control in pixels. The width is set dynamically to show round values (e.g. 100, 200, 500). + maxWidth: 100, + + // @option metric: Boolean = True + // Whether to show the metric scale line (m/km). + metric: true, + + // @option imperial: Boolean = True + // Whether to show the imperial scale line (mi/ft). + imperial: true + + // @option updateWhenIdle: Boolean = false + // If `true`, the control is updated on [`moveend`](#map-moveend), otherwise it's always up-to-date (updated on [`move`](#map-move)). + }, + + onAdd: function (map) { + var className = 'leaflet-control-scale', + container = create$1('div', className), + options = this.options; + + this._addScales(options, className + '-line', container); + + map.on(options.updateWhenIdle ? 'moveend' : 'move', this._update, this); + map.whenReady(this._update, this); + + return container; + }, + + onRemove: function (map) { + map.off(this.options.updateWhenIdle ? 'moveend' : 'move', this._update, this); + }, + + _addScales: function (options, className, container) { + if (options.metric) { + this._mScale = create$1('div', className, container); + } + if (options.imperial) { + this._iScale = create$1('div', className, container); + } + }, + + _update: function () { + var map = this._map, + y = map.getSize().y / 2; + + var maxMeters = map.distance( + map.containerPointToLatLng([0, y]), + map.containerPointToLatLng([this.options.maxWidth, y])); + + this._updateScales(maxMeters); + }, + + _updateScales: function (maxMeters) { + if (this.options.metric && maxMeters) { + this._updateMetric(maxMeters); + } + if (this.options.imperial && maxMeters) { + this._updateImperial(maxMeters); + } + }, + + _updateMetric: function (maxMeters) { + var meters = this._getRoundNum(maxMeters), + label = meters < 1000 ? meters + ' m' : (meters / 1000) + ' km'; + + this._updateScale(this._mScale, label, meters / maxMeters); + }, + + _updateImperial: function (maxMeters) { + var maxFeet = maxMeters * 3.2808399, + maxMiles, miles, feet; + + if (maxFeet > 5280) { + maxMiles = maxFeet / 5280; + miles = this._getRoundNum(maxMiles); + this._updateScale(this._iScale, miles + ' mi', miles / maxMiles); + + } else { + feet = this._getRoundNum(maxFeet); + this._updateScale(this._iScale, feet + ' ft', feet / maxFeet); + } + }, + + _updateScale: function (scale, text, ratio) { + scale.style.width = Math.round(this.options.maxWidth * ratio) + 'px'; + scale.innerHTML = text; + }, + + _getRoundNum: function (num) { + var pow10 = Math.pow(10, (Math.floor(num) + '').length - 1), + d = num / pow10; + + d = d >= 10 ? 10 : + d >= 5 ? 5 : + d >= 3 ? 3 : + d >= 2 ? 2 : 1; + + return pow10 * d; + } +}); + + +// @factory L.control.scale(options?: Control.Scale options) +// Creates an scale control with the given options. +var scale = function (options) { + return new Scale(options); +}; + +/* + * @class Control.Attribution + * @aka L.Control.Attribution + * @inherits Control + * + * The attribution control allows you to display attribution data in a small text box on a map. It is put on the map by default unless you set its [`attributionControl` option](#map-attributioncontrol) to `false`, and it fetches attribution texts from layers with the [`getAttribution` method](#layer-getattribution) automatically. Extends Control. + */ + +var Attribution = Control.extend({ + // @section + // @aka Control.Attribution options + options: { + position: 'bottomright', + + // @option prefix: String = 'Leaflet' + // The HTML text shown before the attributions. Pass `false` to disable. + prefix: 'Leaflet' + }, + + initialize: function (options) { + setOptions(this, options); + + this._attributions = {}; + }, + + onAdd: function (map) { + map.attributionControl = this; + this._container = create$1('div', 'leaflet-control-attribution'); + disableClickPropagation(this._container); + + // TODO ugly, refactor + for (var i in map._layers) { + if (map._layers[i].getAttribution) { + this.addAttribution(map._layers[i].getAttribution()); + } + } + + this._update(); + + return this._container; + }, + + // @method setPrefix(prefix: String): this + // Sets the text before the attributions. + setPrefix: function (prefix) { + this.options.prefix = prefix; + this._update(); + return this; + }, + + // @method addAttribution(text: String): this + // Adds an attribution text (e.g. `'Vector data © Mapbox'`). + addAttribution: function (text) { + if (!text) { return this; } + + if (!this._attributions[text]) { + this._attributions[text] = 0; + } + this._attributions[text]++; + + this._update(); + + return this; + }, + + // @method removeAttribution(text: String): this + // Removes an attribution text. + removeAttribution: function (text) { + if (!text) { return this; } + + if (this._attributions[text]) { + this._attributions[text]--; + this._update(); + } + + return this; + }, + + _update: function () { + if (!this._map) { return; } + + var attribs = []; + + for (var i in this._attributions) { + if (this._attributions[i]) { + attribs.push(i); + } + } + + var prefixAndAttribs = []; + + if (this.options.prefix) { + prefixAndAttribs.push(this.options.prefix); + } + if (attribs.length) { + prefixAndAttribs.push(attribs.join(', ')); + } + + this._container.innerHTML = prefixAndAttribs.join(' | '); + } +}); + +// @namespace Map +// @section Control options +// @option attributionControl: Boolean = true +// Whether a [attribution control](#control-attribution) is added to the map by default. +Map.mergeOptions({ + attributionControl: true +}); + +Map.addInitHook(function () { + if (this.options.attributionControl) { + new Attribution().addTo(this); + } +}); + +// @namespace Control.Attribution +// @factory L.control.attribution(options: Control.Attribution options) +// Creates an attribution control. +var attribution = function (options) { + return new Attribution(options); +}; + +Control.Layers = Layers; +Control.Zoom = Zoom; +Control.Scale = Scale; +Control.Attribution = Attribution; + +control.layers = layers; +control.zoom = zoom; +control.scale = scale; +control.attribution = attribution; + +/* + L.Handler is a base class for handler classes that are used internally to inject + interaction features like dragging to classes like Map and Marker. +*/ + +// @class Handler +// @aka L.Handler +// Abstract class for map interaction handlers + +var Handler = Class.extend({ + initialize: function (map) { + this._map = map; + }, + + // @method enable(): this + // Enables the handler + enable: function () { + if (this._enabled) { return this; } + + this._enabled = true; + this.addHooks(); + return this; + }, + + // @method disable(): this + // Disables the handler + disable: function () { + if (!this._enabled) { return this; } + + this._enabled = false; + this.removeHooks(); + return this; + }, + + // @method enabled(): Boolean + // Returns `true` if the handler is enabled + enabled: function () { + return !!this._enabled; + } + + // @section Extension methods + // Classes inheriting from `Handler` must implement the two following methods: + // @method addHooks() + // Called when the handler is enabled, should add event hooks. + // @method removeHooks() + // Called when the handler is disabled, should remove the event hooks added previously. +}); + +// @section There is static function which can be called without instantiating L.Handler: +// @function addTo(map: Map, name: String): this +// Adds a new Handler to the given map with the given name. +Handler.addTo = function (map, name) { + map.addHandler(name, this); + return this; +}; + +var Mixin = {Events: Events}; + +/* + * @class Draggable + * @aka L.Draggable + * @inherits Evented + * + * A class for making DOM elements draggable (including touch support). + * Used internally for map and marker dragging. Only works for elements + * that were positioned with [`L.DomUtil.setPosition`](#domutil-setposition). + * + * @example + * ```js + * var draggable = new L.Draggable(elementToDrag); + * draggable.enable(); + * ``` + */ + +var START = touch ? 'touchstart mousedown' : 'mousedown'; +var END = { + mousedown: 'mouseup', + touchstart: 'touchend', + pointerdown: 'touchend', + MSPointerDown: 'touchend' +}; +var MOVE = { + mousedown: 'mousemove', + touchstart: 'touchmove', + pointerdown: 'touchmove', + MSPointerDown: 'touchmove' +}; + + +var Draggable = Evented.extend({ + + options: { + // @section + // @aka Draggable options + // @option clickTolerance: Number = 3 + // The max number of pixels a user can shift the mouse pointer during a click + // for it to be considered a valid click (as opposed to a mouse drag). + clickTolerance: 3 + }, + + // @constructor L.Draggable(el: HTMLElement, dragHandle?: HTMLElement, preventOutline?: Boolean, options?: Draggable options) + // Creates a `Draggable` object for moving `el` when you start dragging the `dragHandle` element (equals `el` itself by default). + initialize: function (element, dragStartTarget, preventOutline$$1, options) { + setOptions(this, options); + + this._element = element; + this._dragStartTarget = dragStartTarget || element; + this._preventOutline = preventOutline$$1; + }, + + // @method enable() + // Enables the dragging ability + enable: function () { + if (this._enabled) { return; } + + on(this._dragStartTarget, START, this._onDown, this); + + this._enabled = true; + }, + + // @method disable() + // Disables the dragging ability + disable: function () { + if (!this._enabled) { return; } + + // If we're currently dragging this draggable, + // disabling it counts as first ending the drag. + if (Draggable._dragging === this) { + this.finishDrag(); + } + + off(this._dragStartTarget, START, this._onDown, this); + + this._enabled = false; + this._moved = false; + }, + + _onDown: function (e) { + // Ignore simulated events, since we handle both touch and + // mouse explicitly; otherwise we risk getting duplicates of + // touch events, see #4315. + // Also ignore the event if disabled; this happens in IE11 + // under some circumstances, see #3666. + if (e._simulated || !this._enabled) { return; } + + this._moved = false; + + if (hasClass(this._element, 'leaflet-zoom-anim')) { return; } + + if (Draggable._dragging || e.shiftKey || ((e.which !== 1) && (e.button !== 1) && !e.touches)) { return; } + Draggable._dragging = this; // Prevent dragging multiple objects at once. + + if (this._preventOutline) { + preventOutline(this._element); + } + + disableImageDrag(); + disableTextSelection(); + + if (this._moving) { return; } + + // @event down: Event + // Fired when a drag is about to start. + this.fire('down'); + + var first = e.touches ? e.touches[0] : e, + sizedParent = getSizedParentNode(this._element); + + this._startPoint = new Point(first.clientX, first.clientY); + + // Cache the scale, so that we can continuously compensate for it during drag (_onMove). + this._parentScale = getScale(sizedParent); + + on(document, MOVE[e.type], this._onMove, this); + on(document, END[e.type], this._onUp, this); + }, + + _onMove: function (e) { + // Ignore simulated events, since we handle both touch and + // mouse explicitly; otherwise we risk getting duplicates of + // touch events, see #4315. + // Also ignore the event if disabled; this happens in IE11 + // under some circumstances, see #3666. + if (e._simulated || !this._enabled) { return; } + + if (e.touches && e.touches.length > 1) { + this._moved = true; + return; + } + + var first = (e.touches && e.touches.length === 1 ? e.touches[0] : e), + offset = new Point(first.clientX, first.clientY)._subtract(this._startPoint); + + if (!offset.x && !offset.y) { return; } + if (Math.abs(offset.x) + Math.abs(offset.y) < this.options.clickTolerance) { return; } + + // We assume that the parent container's position, border and scale do not change for the duration of the drag. + // Therefore there is no need to account for the position and border (they are eliminated by the subtraction) + // and we can use the cached value for the scale. + offset.x /= this._parentScale.x; + offset.y /= this._parentScale.y; + + preventDefault(e); + + if (!this._moved) { + // @event dragstart: Event + // Fired when a drag starts + this.fire('dragstart'); + + this._moved = true; + this._startPos = getPosition(this._element).subtract(offset); + + addClass(document.body, 'leaflet-dragging'); + + this._lastTarget = e.target || e.srcElement; + // IE and Edge do not give the element, so fetch it + // if necessary + if ((window.SVGElementInstance) && (this._lastTarget instanceof SVGElementInstance)) { + this._lastTarget = this._lastTarget.correspondingUseElement; + } + addClass(this._lastTarget, 'leaflet-drag-target'); + } + + this._newPos = this._startPos.add(offset); + this._moving = true; + + cancelAnimFrame(this._animRequest); + this._lastEvent = e; + this._animRequest = requestAnimFrame(this._updatePosition, this, true); + }, + + _updatePosition: function () { + var e = {originalEvent: this._lastEvent}; + + // @event predrag: Event + // Fired continuously during dragging *before* each corresponding + // update of the element's position. + this.fire('predrag', e); + setPosition(this._element, this._newPos); + + // @event drag: Event + // Fired continuously during dragging. + this.fire('drag', e); + }, + + _onUp: function (e) { + // Ignore simulated events, since we handle both touch and + // mouse explicitly; otherwise we risk getting duplicates of + // touch events, see #4315. + // Also ignore the event if disabled; this happens in IE11 + // under some circumstances, see #3666. + if (e._simulated || !this._enabled) { return; } + this.finishDrag(); + }, + + finishDrag: function () { + removeClass(document.body, 'leaflet-dragging'); + + if (this._lastTarget) { + removeClass(this._lastTarget, 'leaflet-drag-target'); + this._lastTarget = null; + } + + for (var i in MOVE) { + off(document, MOVE[i], this._onMove, this); + off(document, END[i], this._onUp, this); + } + + enableImageDrag(); + enableTextSelection(); + + if (this._moved && this._moving) { + // ensure drag is not fired after dragend + cancelAnimFrame(this._animRequest); + + // @event dragend: DragEndEvent + // Fired when the drag ends. + this.fire('dragend', { + distance: this._newPos.distanceTo(this._startPos) + }); + } + + this._moving = false; + Draggable._dragging = false; + } + +}); + +/* + * @namespace LineUtil + * + * Various utility functions for polyline points processing, used by Leaflet internally to make polylines lightning-fast. + */ + +// Simplify polyline with vertex reduction and Douglas-Peucker simplification. +// Improves rendering performance dramatically by lessening the number of points to draw. + +// @function simplify(points: Point[], tolerance: Number): Point[] +// Dramatically reduces the number of points in a polyline while retaining +// its shape and returns a new array of simplified points, using the +// [Douglas-Peucker algorithm](http://en.wikipedia.org/wiki/Douglas-Peucker_algorithm). +// Used for a huge performance boost when processing/displaying Leaflet polylines for +// each zoom level and also reducing visual noise. tolerance affects the amount of +// simplification (lesser value means higher quality but slower and with more points). +// Also released as a separated micro-library [Simplify.js](http://mourner.github.com/simplify-js/). +function simplify(points, tolerance) { + if (!tolerance || !points.length) { + return points.slice(); + } + + var sqTolerance = tolerance * tolerance; + + // stage 1: vertex reduction + points = _reducePoints(points, sqTolerance); + + // stage 2: Douglas-Peucker simplification + points = _simplifyDP(points, sqTolerance); + + return points; +} + +// @function pointToSegmentDistance(p: Point, p1: Point, p2: Point): Number +// Returns the distance between point `p` and segment `p1` to `p2`. +function pointToSegmentDistance(p, p1, p2) { + return Math.sqrt(_sqClosestPointOnSegment(p, p1, p2, true)); +} + +// @function closestPointOnSegment(p: Point, p1: Point, p2: Point): Number +// Returns the closest point from a point `p` on a segment `p1` to `p2`. +function closestPointOnSegment(p, p1, p2) { + return _sqClosestPointOnSegment(p, p1, p2); +} + +// Douglas-Peucker simplification, see http://en.wikipedia.org/wiki/Douglas-Peucker_algorithm +function _simplifyDP(points, sqTolerance) { + + var len = points.length, + ArrayConstructor = typeof Uint8Array !== undefined + '' ? Uint8Array : Array, + markers = new ArrayConstructor(len); + + markers[0] = markers[len - 1] = 1; + + _simplifyDPStep(points, markers, sqTolerance, 0, len - 1); + + var i, + newPoints = []; + + for (i = 0; i < len; i++) { + if (markers[i]) { + newPoints.push(points[i]); + } + } + + return newPoints; +} + +function _simplifyDPStep(points, markers, sqTolerance, first, last) { + + var maxSqDist = 0, + index, i, sqDist; + + for (i = first + 1; i <= last - 1; i++) { + sqDist = _sqClosestPointOnSegment(points[i], points[first], points[last], true); + + if (sqDist > maxSqDist) { + index = i; + maxSqDist = sqDist; + } + } + + if (maxSqDist > sqTolerance) { + markers[index] = 1; + + _simplifyDPStep(points, markers, sqTolerance, first, index); + _simplifyDPStep(points, markers, sqTolerance, index, last); + } +} + +// reduce points that are too close to each other to a single point +function _reducePoints(points, sqTolerance) { + var reducedPoints = [points[0]]; + + for (var i = 1, prev = 0, len = points.length; i < len; i++) { + if (_sqDist(points[i], points[prev]) > sqTolerance) { + reducedPoints.push(points[i]); + prev = i; + } + } + if (prev < len - 1) { + reducedPoints.push(points[len - 1]); + } + return reducedPoints; +} + +var _lastCode; + +// @function clipSegment(a: Point, b: Point, bounds: Bounds, useLastCode?: Boolean, round?: Boolean): Point[]|Boolean +// Clips the segment a to b by rectangular bounds with the +// [Cohen-Sutherland algorithm](https://en.wikipedia.org/wiki/Cohen%E2%80%93Sutherland_algorithm) +// (modifying the segment points directly!). Used by Leaflet to only show polyline +// points that are on the screen or near, increasing performance. +function clipSegment(a, b, bounds, useLastCode, round) { + var codeA = useLastCode ? _lastCode : _getBitCode(a, bounds), + codeB = _getBitCode(b, bounds), + + codeOut, p, newCode; + + // save 2nd code to avoid calculating it on the next segment + _lastCode = codeB; + + while (true) { + // if a,b is inside the clip window (trivial accept) + if (!(codeA | codeB)) { + return [a, b]; + } + + // if a,b is outside the clip window (trivial reject) + if (codeA & codeB) { + return false; + } + + // other cases + codeOut = codeA || codeB; + p = _getEdgeIntersection(a, b, codeOut, bounds, round); + newCode = _getBitCode(p, bounds); + + if (codeOut === codeA) { + a = p; + codeA = newCode; + } else { + b = p; + codeB = newCode; + } + } +} + +function _getEdgeIntersection(a, b, code, bounds, round) { + var dx = b.x - a.x, + dy = b.y - a.y, + min = bounds.min, + max = bounds.max, + x, y; + + if (code & 8) { // top + x = a.x + dx * (max.y - a.y) / dy; + y = max.y; + + } else if (code & 4) { // bottom + x = a.x + dx * (min.y - a.y) / dy; + y = min.y; + + } else if (code & 2) { // right + x = max.x; + y = a.y + dy * (max.x - a.x) / dx; + + } else if (code & 1) { // left + x = min.x; + y = a.y + dy * (min.x - a.x) / dx; + } + + return new Point(x, y, round); +} + +function _getBitCode(p, bounds) { + var code = 0; + + if (p.x < bounds.min.x) { // left + code |= 1; + } else if (p.x > bounds.max.x) { // right + code |= 2; + } + + if (p.y < bounds.min.y) { // bottom + code |= 4; + } else if (p.y > bounds.max.y) { // top + code |= 8; + } + + return code; +} + +// square distance (to avoid unnecessary Math.sqrt calls) +function _sqDist(p1, p2) { + var dx = p2.x - p1.x, + dy = p2.y - p1.y; + return dx * dx + dy * dy; +} + +// return closest point on segment or distance to that point +function _sqClosestPointOnSegment(p, p1, p2, sqDist) { + var x = p1.x, + y = p1.y, + dx = p2.x - x, + dy = p2.y - y, + dot = dx * dx + dy * dy, + t; + + if (dot > 0) { + t = ((p.x - x) * dx + (p.y - y) * dy) / dot; + + if (t > 1) { + x = p2.x; + y = p2.y; + } else if (t > 0) { + x += dx * t; + y += dy * t; + } + } + + dx = p.x - x; + dy = p.y - y; + + return sqDist ? dx * dx + dy * dy : new Point(x, y); +} + + +// @function isFlat(latlngs: LatLng[]): Boolean +// Returns true if `latlngs` is a flat array, false is nested. +function isFlat(latlngs) { + return !isArray(latlngs[0]) || (typeof latlngs[0][0] !== 'object' && typeof latlngs[0][0] !== 'undefined'); +} + +function _flat(latlngs) { + console.warn('Deprecated use of _flat, please use L.LineUtil.isFlat instead.'); + return isFlat(latlngs); +} + + +var LineUtil = (Object.freeze || Object)({ + simplify: simplify, + pointToSegmentDistance: pointToSegmentDistance, + closestPointOnSegment: closestPointOnSegment, + clipSegment: clipSegment, + _getEdgeIntersection: _getEdgeIntersection, + _getBitCode: _getBitCode, + _sqClosestPointOnSegment: _sqClosestPointOnSegment, + isFlat: isFlat, + _flat: _flat +}); + +/* + * @namespace PolyUtil + * Various utility functions for polygon geometries. + */ + +/* @function clipPolygon(points: Point[], bounds: Bounds, round?: Boolean): Point[] + * Clips the polygon geometry defined by the given `points` by the given bounds (using the [Sutherland-Hodgman algorithm](https://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman_algorithm)). + * Used by Leaflet to only show polygon points that are on the screen or near, increasing + * performance. Note that polygon points needs different algorithm for clipping + * than polyline, so there's a separate method for it. + */ +function clipPolygon(points, bounds, round) { + var clippedPoints, + edges = [1, 4, 2, 8], + i, j, k, + a, b, + len, edge, p; + + for (i = 0, len = points.length; i < len; i++) { + points[i]._code = _getBitCode(points[i], bounds); + } + + // for each edge (left, bottom, right, top) + for (k = 0; k < 4; k++) { + edge = edges[k]; + clippedPoints = []; + + for (i = 0, len = points.length, j = len - 1; i < len; j = i++) { + a = points[i]; + b = points[j]; + + // if a is inside the clip window + if (!(a._code & edge)) { + // if b is outside the clip window (a->b goes out of screen) + if (b._code & edge) { + p = _getEdgeIntersection(b, a, edge, bounds, round); + p._code = _getBitCode(p, bounds); + clippedPoints.push(p); + } + clippedPoints.push(a); + + // else if b is inside the clip window (a->b enters the screen) + } else if (!(b._code & edge)) { + p = _getEdgeIntersection(b, a, edge, bounds, round); + p._code = _getBitCode(p, bounds); + clippedPoints.push(p); + } + } + points = clippedPoints; + } + + return points; +} + + +var PolyUtil = (Object.freeze || Object)({ + clipPolygon: clipPolygon +}); + +/* + * @namespace Projection + * @section + * Leaflet comes with a set of already defined Projections out of the box: + * + * @projection L.Projection.LonLat + * + * Equirectangular, or Plate Carree projection — the most simple projection, + * mostly used by GIS enthusiasts. Directly maps `x` as longitude, and `y` as + * latitude. Also suitable for flat worlds, e.g. game maps. Used by the + * `EPSG:4326` and `Simple` CRS. + */ + +var LonLat = { + project: function (latlng) { + return new Point(latlng.lng, latlng.lat); + }, + + unproject: function (point) { + return new LatLng(point.y, point.x); + }, + + bounds: new Bounds([-180, -90], [180, 90]) +}; + +/* + * @namespace Projection + * @projection L.Projection.Mercator + * + * Elliptical Mercator projection — more complex than Spherical Mercator. Assumes that Earth is an ellipsoid. Used by the EPSG:3395 CRS. + */ + +var Mercator = { + R: 6378137, + R_MINOR: 6356752.314245179, + + bounds: new Bounds([-20037508.34279, -15496570.73972], [20037508.34279, 18764656.23138]), + + project: function (latlng) { + var d = Math.PI / 180, + r = this.R, + y = latlng.lat * d, + tmp = this.R_MINOR / r, + e = Math.sqrt(1 - tmp * tmp), + con = e * Math.sin(y); + + var ts = Math.tan(Math.PI / 4 - y / 2) / Math.pow((1 - con) / (1 + con), e / 2); + y = -r * Math.log(Math.max(ts, 1E-10)); + + return new Point(latlng.lng * d * r, y); + }, + + unproject: function (point) { + var d = 180 / Math.PI, + r = this.R, + tmp = this.R_MINOR / r, + e = Math.sqrt(1 - tmp * tmp), + ts = Math.exp(-point.y / r), + phi = Math.PI / 2 - 2 * Math.atan(ts); + + for (var i = 0, dphi = 0.1, con; i < 15 && Math.abs(dphi) > 1e-7; i++) { + con = e * Math.sin(phi); + con = Math.pow((1 - con) / (1 + con), e / 2); + dphi = Math.PI / 2 - 2 * Math.atan(ts * con) - phi; + phi += dphi; + } + + return new LatLng(phi * d, point.x * d / r); + } +}; + +/* + * @class Projection + + * An object with methods for projecting geographical coordinates of the world onto + * a flat surface (and back). See [Map projection](http://en.wikipedia.org/wiki/Map_projection). + + * @property bounds: Bounds + * The bounds (specified in CRS units) where the projection is valid + + * @method project(latlng: LatLng): Point + * Projects geographical coordinates into a 2D point. + * Only accepts actual `L.LatLng` instances, not arrays. + + * @method unproject(point: Point): LatLng + * The inverse of `project`. Projects a 2D point into a geographical location. + * Only accepts actual `L.Point` instances, not arrays. + + * Note that the projection instances do not inherit from Leafet's `Class` object, + * and can't be instantiated. Also, new classes can't inherit from them, + * and methods can't be added to them with the `include` function. + + */ + + + + +var index = (Object.freeze || Object)({ + LonLat: LonLat, + Mercator: Mercator, + SphericalMercator: SphericalMercator +}); + +/* + * @namespace CRS + * @crs L.CRS.EPSG3395 + * + * Rarely used by some commercial tile providers. Uses Elliptical Mercator projection. + */ +var EPSG3395 = extend({}, Earth, { + code: 'EPSG:3395', + projection: Mercator, + + transformation: (function () { + var scale = 0.5 / (Math.PI * Mercator.R); + return toTransformation(scale, 0.5, -scale, 0.5); + }()) +}); + +/* + * @namespace CRS + * @crs L.CRS.EPSG4326 + * + * A common CRS among GIS enthusiasts. Uses simple Equirectangular projection. + * + * Leaflet 1.0.x complies with the [TMS coordinate scheme for EPSG:4326](https://wiki.osgeo.org/wiki/Tile_Map_Service_Specification#global-geodetic), + * which is a breaking change from 0.7.x behaviour. If you are using a `TileLayer` + * with this CRS, ensure that there are two 256x256 pixel tiles covering the + * whole earth at zoom level zero, and that the tile coordinate origin is (-180,+90), + * or (-180,-90) for `TileLayer`s with [the `tms` option](#tilelayer-tms) set. + */ + +var EPSG4326 = extend({}, Earth, { + code: 'EPSG:4326', + projection: LonLat, + transformation: toTransformation(1 / 180, 1, -1 / 180, 0.5) +}); + +/* + * @namespace CRS + * @crs L.CRS.Simple + * + * A simple CRS that maps longitude and latitude into `x` and `y` directly. + * May be used for maps of flat surfaces (e.g. game maps). Note that the `y` + * axis should still be inverted (going from bottom to top). `distance()` returns + * simple euclidean distance. + */ + +var Simple = extend({}, CRS, { + projection: LonLat, + transformation: toTransformation(1, 0, -1, 0), + + scale: function (zoom) { + return Math.pow(2, zoom); + }, + + zoom: function (scale) { + return Math.log(scale) / Math.LN2; + }, + + distance: function (latlng1, latlng2) { + var dx = latlng2.lng - latlng1.lng, + dy = latlng2.lat - latlng1.lat; + + return Math.sqrt(dx * dx + dy * dy); + }, + + infinite: true +}); + +CRS.Earth = Earth; +CRS.EPSG3395 = EPSG3395; +CRS.EPSG3857 = EPSG3857; +CRS.EPSG900913 = EPSG900913; +CRS.EPSG4326 = EPSG4326; +CRS.Simple = Simple; + +/* + * @class Layer + * @inherits Evented + * @aka L.Layer + * @aka ILayer + * + * A set of methods from the Layer base class that all Leaflet layers use. + * Inherits all methods, options and events from `L.Evented`. + * + * @example + * + * ```js + * var layer = L.marker(latlng).addTo(map); + * layer.addTo(map); + * layer.remove(); + * ``` + * + * @event add: Event + * Fired after the layer is added to a map + * + * @event remove: Event + * Fired after the layer is removed from a map + */ + + +var Layer = Evented.extend({ + + // Classes extending `L.Layer` will inherit the following options: + options: { + // @option pane: String = 'overlayPane' + // By default the layer will be added to the map's [overlay pane](#map-overlaypane). Overriding this option will cause the layer to be placed on another pane by default. + pane: 'overlayPane', + + // @option attribution: String = null + // String to be shown in the attribution control, e.g. "© OpenStreetMap contributors". It describes the layer data and is often a legal obligation towards copyright holders and tile providers. + attribution: null, + + bubblingMouseEvents: true + }, + + /* @section + * Classes extending `L.Layer` will inherit the following methods: + * + * @method addTo(map: Map|LayerGroup): this + * Adds the layer to the given map or layer group. + */ + addTo: function (map) { + map.addLayer(this); + return this; + }, + + // @method remove: this + // Removes the layer from the map it is currently active on. + remove: function () { + return this.removeFrom(this._map || this._mapToAdd); + }, + + // @method removeFrom(map: Map): this + // Removes the layer from the given map + removeFrom: function (obj) { + if (obj) { + obj.removeLayer(this); + } + return this; + }, + + // @method getPane(name? : String): HTMLElement + // Returns the `HTMLElement` representing the named pane on the map. If `name` is omitted, returns the pane for this layer. + getPane: function (name) { + return this._map.getPane(name ? (this.options[name] || name) : this.options.pane); + }, + + addInteractiveTarget: function (targetEl) { + this._map._targets[stamp(targetEl)] = this; + return this; + }, + + removeInteractiveTarget: function (targetEl) { + delete this._map._targets[stamp(targetEl)]; + return this; + }, + + // @method getAttribution: String + // Used by the `attribution control`, returns the [attribution option](#gridlayer-attribution). + getAttribution: function () { + return this.options.attribution; + }, + + _layerAdd: function (e) { + var map = e.target; + + // check in case layer gets added and then removed before the map is ready + if (!map.hasLayer(this)) { return; } + + this._map = map; + this._zoomAnimated = map._zoomAnimated; + + if (this.getEvents) { + var events = this.getEvents(); + map.on(events, this); + this.once('remove', function () { + map.off(events, this); + }, this); + } + + this.onAdd(map); + + if (this.getAttribution && map.attributionControl) { + map.attributionControl.addAttribution(this.getAttribution()); + } + + this.fire('add'); + map.fire('layeradd', {layer: this}); + } +}); + +/* @section Extension methods + * @uninheritable + * + * Every layer should extend from `L.Layer` and (re-)implement the following methods. + * + * @method onAdd(map: Map): this + * Should contain code that creates DOM elements for the layer, adds them to `map panes` where they should belong and puts listeners on relevant map events. Called on [`map.addLayer(layer)`](#map-addlayer). + * + * @method onRemove(map: Map): this + * Should contain all clean up code that removes the layer's elements from the DOM and removes listeners previously added in [`onAdd`](#layer-onadd). Called on [`map.removeLayer(layer)`](#map-removelayer). + * + * @method getEvents(): Object + * This optional method should return an object like `{ viewreset: this._reset }` for [`addEventListener`](#evented-addeventlistener). The event handlers in this object will be automatically added and removed from the map with your layer. + * + * @method getAttribution(): String + * This optional method should return a string containing HTML to be shown on the `Attribution control` whenever the layer is visible. + * + * @method beforeAdd(map: Map): this + * Optional method. Called on [`map.addLayer(layer)`](#map-addlayer), before the layer is added to the map, before events are initialized, without waiting until the map is in a usable state. Use for early initialization only. + */ + + +/* @namespace Map + * @section Layer events + * + * @event layeradd: LayerEvent + * Fired when a new layer is added to the map. + * + * @event layerremove: LayerEvent + * Fired when some layer is removed from the map + * + * @section Methods for Layers and Controls + */ +Map.include({ + // @method addLayer(layer: Layer): this + // Adds the given layer to the map + addLayer: function (layer) { + if (!layer._layerAdd) { + throw new Error('The provided object is not a Layer.'); + } + + var id = stamp(layer); + if (this._layers[id]) { return this; } + this._layers[id] = layer; + + layer._mapToAdd = this; + + if (layer.beforeAdd) { + layer.beforeAdd(this); + } + + this.whenReady(layer._layerAdd, layer); + + return this; + }, + + // @method removeLayer(layer: Layer): this + // Removes the given layer from the map. + removeLayer: function (layer) { + var id = stamp(layer); + + if (!this._layers[id]) { return this; } + + if (this._loaded) { + layer.onRemove(this); + } + + if (layer.getAttribution && this.attributionControl) { + this.attributionControl.removeAttribution(layer.getAttribution()); + } + + delete this._layers[id]; + + if (this._loaded) { + this.fire('layerremove', {layer: layer}); + layer.fire('remove'); + } + + layer._map = layer._mapToAdd = null; + + return this; + }, + + // @method hasLayer(layer: Layer): Boolean + // Returns `true` if the given layer is currently added to the map + hasLayer: function (layer) { + return !!layer && (stamp(layer) in this._layers); + }, + + /* @method eachLayer(fn: Function, context?: Object): this + * Iterates over the layers of the map, optionally specifying context of the iterator function. + * ``` + * map.eachLayer(function(layer){ + * layer.bindPopup('Hello'); + * }); + * ``` + */ + eachLayer: function (method, context) { + for (var i in this._layers) { + method.call(context, this._layers[i]); + } + return this; + }, + + _addLayers: function (layers) { + layers = layers ? (isArray(layers) ? layers : [layers]) : []; + + for (var i = 0, len = layers.length; i < len; i++) { + this.addLayer(layers[i]); + } + }, + + _addZoomLimit: function (layer) { + if (isNaN(layer.options.maxZoom) || !isNaN(layer.options.minZoom)) { + this._zoomBoundLayers[stamp(layer)] = layer; + this._updateZoomLevels(); + } + }, + + _removeZoomLimit: function (layer) { + var id = stamp(layer); + + if (this._zoomBoundLayers[id]) { + delete this._zoomBoundLayers[id]; + this._updateZoomLevels(); + } + }, + + _updateZoomLevels: function () { + var minZoom = Infinity, + maxZoom = -Infinity, + oldZoomSpan = this._getZoomSpan(); + + for (var i in this._zoomBoundLayers) { + var options = this._zoomBoundLayers[i].options; + + minZoom = options.minZoom === undefined ? minZoom : Math.min(minZoom, options.minZoom); + maxZoom = options.maxZoom === undefined ? maxZoom : Math.max(maxZoom, options.maxZoom); + } + + this._layersMaxZoom = maxZoom === -Infinity ? undefined : maxZoom; + this._layersMinZoom = minZoom === Infinity ? undefined : minZoom; + + // @section Map state change events + // @event zoomlevelschange: Event + // Fired when the number of zoomlevels on the map is changed due + // to adding or removing a layer. + if (oldZoomSpan !== this._getZoomSpan()) { + this.fire('zoomlevelschange'); + } + + if (this.options.maxZoom === undefined && this._layersMaxZoom && this.getZoom() > this._layersMaxZoom) { + this.setZoom(this._layersMaxZoom); + } + if (this.options.minZoom === undefined && this._layersMinZoom && this.getZoom() < this._layersMinZoom) { + this.setZoom(this._layersMinZoom); + } + } +}); + +/* + * @class LayerGroup + * @aka L.LayerGroup + * @inherits Layer + * + * Used to group several layers and handle them as one. If you add it to the map, + * any layers added or removed from the group will be added/removed on the map as + * well. Extends `Layer`. + * + * @example + * + * ```js + * L.layerGroup([marker1, marker2]) + * .addLayer(polyline) + * .addTo(map); + * ``` + */ + +var LayerGroup = Layer.extend({ + + initialize: function (layers, options) { + setOptions(this, options); + + this._layers = {}; + + var i, len; + + if (layers) { + for (i = 0, len = layers.length; i < len; i++) { + this.addLayer(layers[i]); + } + } + }, + + // @method addLayer(layer: Layer): this + // Adds the given layer to the group. + addLayer: function (layer) { + var id = this.getLayerId(layer); + + this._layers[id] = layer; + + if (this._map) { + this._map.addLayer(layer); + } + + return this; + }, + + // @method removeLayer(layer: Layer): this + // Removes the given layer from the group. + // @alternative + // @method removeLayer(id: Number): this + // Removes the layer with the given internal ID from the group. + removeLayer: function (layer) { + var id = layer in this._layers ? layer : this.getLayerId(layer); + + if (this._map && this._layers[id]) { + this._map.removeLayer(this._layers[id]); + } + + delete this._layers[id]; + + return this; + }, + + // @method hasLayer(layer: Layer): Boolean + // Returns `true` if the given layer is currently added to the group. + // @alternative + // @method hasLayer(id: Number): Boolean + // Returns `true` if the given internal ID is currently added to the group. + hasLayer: function (layer) { + return !!layer && (layer in this._layers || this.getLayerId(layer) in this._layers); + }, + + // @method clearLayers(): this + // Removes all the layers from the group. + clearLayers: function () { + return this.eachLayer(this.removeLayer, this); + }, + + // @method invoke(methodName: String, …): this + // Calls `methodName` on every layer contained in this group, passing any + // additional parameters. Has no effect if the layers contained do not + // implement `methodName`. + invoke: function (methodName) { + var args = Array.prototype.slice.call(arguments, 1), + i, layer; + + for (i in this._layers) { + layer = this._layers[i]; + + if (layer[methodName]) { + layer[methodName].apply(layer, args); + } + } + + return this; + }, + + onAdd: function (map) { + this.eachLayer(map.addLayer, map); + }, + + onRemove: function (map) { + this.eachLayer(map.removeLayer, map); + }, + + // @method eachLayer(fn: Function, context?: Object): this + // Iterates over the layers of the group, optionally specifying context of the iterator function. + // ```js + // group.eachLayer(function (layer) { + // layer.bindPopup('Hello'); + // }); + // ``` + eachLayer: function (method, context) { + for (var i in this._layers) { + method.call(context, this._layers[i]); + } + return this; + }, + + // @method getLayer(id: Number): Layer + // Returns the layer with the given internal ID. + getLayer: function (id) { + return this._layers[id]; + }, + + // @method getLayers(): Layer[] + // Returns an array of all the layers added to the group. + getLayers: function () { + var layers = []; + this.eachLayer(layers.push, layers); + return layers; + }, + + // @method setZIndex(zIndex: Number): this + // Calls `setZIndex` on every layer contained in this group, passing the z-index. + setZIndex: function (zIndex) { + return this.invoke('setZIndex', zIndex); + }, + + // @method getLayerId(layer: Layer): Number + // Returns the internal ID for a layer + getLayerId: function (layer) { + return stamp(layer); + } +}); + + +// @factory L.layerGroup(layers?: Layer[], options?: Object) +// Create a layer group, optionally given an initial set of layers and an `options` object. +var layerGroup = function (layers, options) { + return new LayerGroup(layers, options); +}; + +/* + * @class FeatureGroup + * @aka L.FeatureGroup + * @inherits LayerGroup + * + * Extended `LayerGroup` that makes it easier to do the same thing to all its member layers: + * * [`bindPopup`](#layer-bindpopup) binds a popup to all of the layers at once (likewise with [`bindTooltip`](#layer-bindtooltip)) + * * Events are propagated to the `FeatureGroup`, so if the group has an event + * handler, it will handle events from any of the layers. This includes mouse events + * and custom events. + * * Has `layeradd` and `layerremove` events + * + * @example + * + * ```js + * L.featureGroup([marker1, marker2, polyline]) + * .bindPopup('Hello world!') + * .on('click', function() { alert('Clicked on a member of the group!'); }) + * .addTo(map); + * ``` + */ + +var FeatureGroup = LayerGroup.extend({ + + addLayer: function (layer) { + if (this.hasLayer(layer)) { + return this; + } + + layer.addEventParent(this); + + LayerGroup.prototype.addLayer.call(this, layer); + + // @event layeradd: LayerEvent + // Fired when a layer is added to this `FeatureGroup` + return this.fire('layeradd', {layer: layer}); + }, + + removeLayer: function (layer) { + if (!this.hasLayer(layer)) { + return this; + } + if (layer in this._layers) { + layer = this._layers[layer]; + } + + layer.removeEventParent(this); + + LayerGroup.prototype.removeLayer.call(this, layer); + + // @event layerremove: LayerEvent + // Fired when a layer is removed from this `FeatureGroup` + return this.fire('layerremove', {layer: layer}); + }, + + // @method setStyle(style: Path options): this + // Sets the given path options to each layer of the group that has a `setStyle` method. + setStyle: function (style) { + return this.invoke('setStyle', style); + }, + + // @method bringToFront(): this + // Brings the layer group to the top of all other layers + bringToFront: function () { + return this.invoke('bringToFront'); + }, + + // @method bringToBack(): this + // Brings the layer group to the back of all other layers + bringToBack: function () { + return this.invoke('bringToBack'); + }, + + // @method getBounds(): LatLngBounds + // Returns the LatLngBounds of the Feature Group (created from bounds and coordinates of its children). + getBounds: function () { + var bounds = new LatLngBounds(); + + for (var id in this._layers) { + var layer = this._layers[id]; + bounds.extend(layer.getBounds ? layer.getBounds() : layer.getLatLng()); + } + return bounds; + } +}); + +// @factory L.featureGroup(layers: Layer[]) +// Create a feature group, optionally given an initial set of layers. +var featureGroup = function (layers) { + return new FeatureGroup(layers); +}; + +/* + * @class Icon + * @aka L.Icon + * + * Represents an icon to provide when creating a marker. + * + * @example + * + * ```js + * var myIcon = L.icon({ + * iconUrl: 'my-icon.png', + * iconRetinaUrl: 'my-icon@2x.png', + * iconSize: [38, 95], + * iconAnchor: [22, 94], + * popupAnchor: [-3, -76], + * shadowUrl: 'my-icon-shadow.png', + * shadowRetinaUrl: 'my-icon-shadow@2x.png', + * shadowSize: [68, 95], + * shadowAnchor: [22, 94] + * }); + * + * L.marker([50.505, 30.57], {icon: myIcon}).addTo(map); + * ``` + * + * `L.Icon.Default` extends `L.Icon` and is the blue icon Leaflet uses for markers by default. + * + */ + +var Icon = Class.extend({ + + /* @section + * @aka Icon options + * + * @option iconUrl: String = null + * **(required)** The URL to the icon image (absolute or relative to your script path). + * + * @option iconRetinaUrl: String = null + * The URL to a retina sized version of the icon image (absolute or relative to your + * script path). Used for Retina screen devices. + * + * @option iconSize: Point = null + * Size of the icon image in pixels. + * + * @option iconAnchor: Point = null + * The coordinates of the "tip" of the icon (relative to its top left corner). The icon + * will be aligned so that this point is at the marker's geographical location. Centered + * by default if size is specified, also can be set in CSS with negative margins. + * + * @option popupAnchor: Point = [0, 0] + * The coordinates of the point from which popups will "open", relative to the icon anchor. + * + * @option tooltipAnchor: Point = [0, 0] + * The coordinates of the point from which tooltips will "open", relative to the icon anchor. + * + * @option shadowUrl: String = null + * The URL to the icon shadow image. If not specified, no shadow image will be created. + * + * @option shadowRetinaUrl: String = null + * + * @option shadowSize: Point = null + * Size of the shadow image in pixels. + * + * @option shadowAnchor: Point = null + * The coordinates of the "tip" of the shadow (relative to its top left corner) (the same + * as iconAnchor if not specified). + * + * @option className: String = '' + * A custom class name to assign to both icon and shadow images. Empty by default. + */ + + options: { + popupAnchor: [0, 0], + tooltipAnchor: [0, 0] + }, + + initialize: function (options) { + setOptions(this, options); + }, + + // @method createIcon(oldIcon?: HTMLElement): HTMLElement + // Called internally when the icon has to be shown, returns a `` HTML element + // styled according to the options. + createIcon: function (oldIcon) { + return this._createIcon('icon', oldIcon); + }, + + // @method createShadow(oldIcon?: HTMLElement): HTMLElement + // As `createIcon`, but for the shadow beneath it. + createShadow: function (oldIcon) { + return this._createIcon('shadow', oldIcon); + }, + + _createIcon: function (name, oldIcon) { + var src = this._getIconUrl(name); + + if (!src) { + if (name === 'icon') { + throw new Error('iconUrl not set in Icon options (see the docs).'); + } + return null; + } + + var img = this._createImg(src, oldIcon && oldIcon.tagName === 'IMG' ? oldIcon : null); + this._setIconStyles(img, name); + + return img; + }, + + _setIconStyles: function (img, name) { + var options = this.options; + var sizeOption = options[name + 'Size']; + + if (typeof sizeOption === 'number') { + sizeOption = [sizeOption, sizeOption]; + } + + var size = toPoint(sizeOption), + anchor = toPoint(name === 'shadow' && options.shadowAnchor || options.iconAnchor || + size && size.divideBy(2, true)); + + img.className = 'leaflet-marker-' + name + ' ' + (options.className || ''); + + if (anchor) { + img.style.marginLeft = (-anchor.x) + 'px'; + img.style.marginTop = (-anchor.y) + 'px'; + } + + if (size) { + img.style.width = size.x + 'px'; + img.style.height = size.y + 'px'; + } + }, + + _createImg: function (src, el) { + el = el || document.createElement('img'); + el.src = src; + return el; + }, + + _getIconUrl: function (name) { + return retina && this.options[name + 'RetinaUrl'] || this.options[name + 'Url']; + } +}); + + +// @factory L.icon(options: Icon options) +// Creates an icon instance with the given options. +function icon(options) { + return new Icon(options); +} + +/* + * @miniclass Icon.Default (Icon) + * @aka L.Icon.Default + * @section + * + * A trivial subclass of `Icon`, represents the icon to use in `Marker`s when + * no icon is specified. Points to the blue marker image distributed with Leaflet + * releases. + * + * In order to customize the default icon, just change the properties of `L.Icon.Default.prototype.options` + * (which is a set of `Icon options`). + * + * If you want to _completely_ replace the default icon, override the + * `L.Marker.prototype.options.icon` with your own icon instead. + */ + +var IconDefault = Icon.extend({ + + options: { + iconUrl: 'marker-icon.png', + iconRetinaUrl: 'marker-icon-2x.png', + shadowUrl: 'marker-shadow.png', + iconSize: [25, 41], + iconAnchor: [12, 41], + popupAnchor: [1, -34], + tooltipAnchor: [16, -28], + shadowSize: [41, 41] + }, + + _getIconUrl: function (name) { + if (!IconDefault.imagePath) { // Deprecated, backwards-compatibility only + IconDefault.imagePath = this._detectIconPath(); + } + + // @option imagePath: String + // `Icon.Default` will try to auto-detect the location of the + // blue icon images. If you are placing these images in a non-standard + // way, set this option to point to the right path. + return (this.options.imagePath || IconDefault.imagePath) + Icon.prototype._getIconUrl.call(this, name); + }, + + _detectIconPath: function () { + var el = create$1('div', 'leaflet-default-icon-path', document.body); + var path = getStyle(el, 'background-image') || + getStyle(el, 'backgroundImage'); // IE8 + + document.body.removeChild(el); + + if (path === null || path.indexOf('url') !== 0) { + path = ''; + } else { + path = path.replace(/^url\(["']?/, '').replace(/marker-icon\.png["']?\)$/, ''); + } + + return path; + } +}); + +/* + * L.Handler.MarkerDrag is used internally by L.Marker to make the markers draggable. + */ + + +/* @namespace Marker + * @section Interaction handlers + * + * Interaction handlers are properties of a marker instance that allow you to control interaction behavior in runtime, enabling or disabling certain features such as dragging (see `Handler` methods). Example: + * + * ```js + * marker.dragging.disable(); + * ``` + * + * @property dragging: Handler + * Marker dragging handler (by both mouse and touch). Only valid when the marker is on the map (Otherwise set [`marker.options.draggable`](#marker-draggable)). + */ + +var MarkerDrag = Handler.extend({ + initialize: function (marker) { + this._marker = marker; + }, + + addHooks: function () { + var icon = this._marker._icon; + + if (!this._draggable) { + this._draggable = new Draggable(icon, icon, true); + } + + this._draggable.on({ + dragstart: this._onDragStart, + predrag: this._onPreDrag, + drag: this._onDrag, + dragend: this._onDragEnd + }, this).enable(); + + addClass(icon, 'leaflet-marker-draggable'); + }, + + removeHooks: function () { + this._draggable.off({ + dragstart: this._onDragStart, + predrag: this._onPreDrag, + drag: this._onDrag, + dragend: this._onDragEnd + }, this).disable(); + + if (this._marker._icon) { + removeClass(this._marker._icon, 'leaflet-marker-draggable'); + } + }, + + moved: function () { + return this._draggable && this._draggable._moved; + }, + + _adjustPan: function (e) { + var marker = this._marker, + map = marker._map, + speed = this._marker.options.autoPanSpeed, + padding = this._marker.options.autoPanPadding, + iconPos = getPosition(marker._icon), + bounds = map.getPixelBounds(), + origin = map.getPixelOrigin(); + + var panBounds = toBounds( + bounds.min._subtract(origin).add(padding), + bounds.max._subtract(origin).subtract(padding) + ); + + if (!panBounds.contains(iconPos)) { + // Compute incremental movement + var movement = toPoint( + (Math.max(panBounds.max.x, iconPos.x) - panBounds.max.x) / (bounds.max.x - panBounds.max.x) - + (Math.min(panBounds.min.x, iconPos.x) - panBounds.min.x) / (bounds.min.x - panBounds.min.x), + + (Math.max(panBounds.max.y, iconPos.y) - panBounds.max.y) / (bounds.max.y - panBounds.max.y) - + (Math.min(panBounds.min.y, iconPos.y) - panBounds.min.y) / (bounds.min.y - panBounds.min.y) + ).multiplyBy(speed); + + map.panBy(movement, {animate: false}); + + this._draggable._newPos._add(movement); + this._draggable._startPos._add(movement); + + setPosition(marker._icon, this._draggable._newPos); + this._onDrag(e); + + this._panRequest = requestAnimFrame(this._adjustPan.bind(this, e)); + } + }, + + _onDragStart: function () { + // @section Dragging events + // @event dragstart: Event + // Fired when the user starts dragging the marker. + + // @event movestart: Event + // Fired when the marker starts moving (because of dragging). + + this._oldLatLng = this._marker.getLatLng(); + this._marker + .closePopup() + .fire('movestart') + .fire('dragstart'); + }, + + _onPreDrag: function (e) { + if (this._marker.options.autoPan) { + cancelAnimFrame(this._panRequest); + this._panRequest = requestAnimFrame(this._adjustPan.bind(this, e)); + } + }, + + _onDrag: function (e) { + var marker = this._marker, + shadow = marker._shadow, + iconPos = getPosition(marker._icon), + latlng = marker._map.layerPointToLatLng(iconPos); + + // update shadow position + if (shadow) { + setPosition(shadow, iconPos); + } + + marker._latlng = latlng; + e.latlng = latlng; + e.oldLatLng = this._oldLatLng; + + // @event drag: Event + // Fired repeatedly while the user drags the marker. + marker + .fire('move', e) + .fire('drag', e); + }, + + _onDragEnd: function (e) { + // @event dragend: DragEndEvent + // Fired when the user stops dragging the marker. + + cancelAnimFrame(this._panRequest); + + // @event moveend: Event + // Fired when the marker stops moving (because of dragging). + delete this._oldLatLng; + this._marker + .fire('moveend') + .fire('dragend', e); + } +}); + +/* + * @class Marker + * @inherits Interactive layer + * @aka L.Marker + * L.Marker is used to display clickable/draggable icons on the map. Extends `Layer`. + * + * @example + * + * ```js + * L.marker([50.5, 30.5]).addTo(map); + * ``` + */ + +var Marker = Layer.extend({ + + // @section + // @aka Marker options + options: { + // @option icon: Icon = * + // Icon instance to use for rendering the marker. + // See [Icon documentation](#L.Icon) for details on how to customize the marker icon. + // If not specified, a common instance of `L.Icon.Default` is used. + icon: new IconDefault(), + + // Option inherited from "Interactive layer" abstract class + interactive: true, + + // @option keyboard: Boolean = true + // Whether the marker can be tabbed to with a keyboard and clicked by pressing enter. + keyboard: true, + + // @option title: String = '' + // Text for the browser tooltip that appear on marker hover (no tooltip by default). + title: '', + + // @option alt: String = '' + // Text for the `alt` attribute of the icon image (useful for accessibility). + alt: '', + + // @option zIndexOffset: Number = 0 + // By default, marker images zIndex is set automatically based on its latitude. Use this option if you want to put the marker on top of all others (or below), specifying a high value like `1000` (or high negative value, respectively). + zIndexOffset: 0, + + // @option opacity: Number = 1.0 + // The opacity of the marker. + opacity: 1, + + // @option riseOnHover: Boolean = false + // If `true`, the marker will get on top of others when you hover the mouse over it. + riseOnHover: false, + + // @option riseOffset: Number = 250 + // The z-index offset used for the `riseOnHover` feature. + riseOffset: 250, + + // @option pane: String = 'markerPane' + // `Map pane` where the markers icon will be added. + pane: 'markerPane', + + // @option pane: String = 'shadowPane' + // `Map pane` where the markers shadow will be added. + shadowPane: 'shadowPane', + + // @option bubblingMouseEvents: Boolean = false + // When `true`, a mouse event on this marker will trigger the same event on the map + // (unless [`L.DomEvent.stopPropagation`](#domevent-stoppropagation) is used). + bubblingMouseEvents: false, + + // @section Draggable marker options + // @option draggable: Boolean = false + // Whether the marker is draggable with mouse/touch or not. + draggable: false, + + // @option autoPan: Boolean = false + // Whether to pan the map when dragging this marker near its edge or not. + autoPan: false, + + // @option autoPanPadding: Point = Point(50, 50) + // Distance (in pixels to the left/right and to the top/bottom) of the + // map edge to start panning the map. + autoPanPadding: [50, 50], + + // @option autoPanSpeed: Number = 10 + // Number of pixels the map should pan by. + autoPanSpeed: 10 + }, + + /* @section + * + * In addition to [shared layer methods](#Layer) like `addTo()` and `remove()` and [popup methods](#Popup) like bindPopup() you can also use the following methods: + */ + + initialize: function (latlng, options) { + setOptions(this, options); + this._latlng = toLatLng(latlng); + }, + + onAdd: function (map) { + this._zoomAnimated = this._zoomAnimated && map.options.markerZoomAnimation; + + if (this._zoomAnimated) { + map.on('zoomanim', this._animateZoom, this); + } + + this._initIcon(); + this.update(); + }, + + onRemove: function (map) { + if (this.dragging && this.dragging.enabled()) { + this.options.draggable = true; + this.dragging.removeHooks(); + } + delete this.dragging; + + if (this._zoomAnimated) { + map.off('zoomanim', this._animateZoom, this); + } + + this._removeIcon(); + this._removeShadow(); + }, + + getEvents: function () { + return { + zoom: this.update, + viewreset: this.update + }; + }, + + // @method getLatLng: LatLng + // Returns the current geographical position of the marker. + getLatLng: function () { + return this._latlng; + }, + + // @method setLatLng(latlng: LatLng): this + // Changes the marker position to the given point. + setLatLng: function (latlng) { + var oldLatLng = this._latlng; + this._latlng = toLatLng(latlng); + this.update(); + + // @event move: Event + // Fired when the marker is moved via [`setLatLng`](#marker-setlatlng) or by [dragging](#marker-dragging). Old and new coordinates are included in event arguments as `oldLatLng`, `latlng`. + return this.fire('move', {oldLatLng: oldLatLng, latlng: this._latlng}); + }, + + // @method setZIndexOffset(offset: Number): this + // Changes the [zIndex offset](#marker-zindexoffset) of the marker. + setZIndexOffset: function (offset) { + this.options.zIndexOffset = offset; + return this.update(); + }, + + // @method getIcon: Icon + // Returns the current icon used by the marker + getIcon: function () { + return this.options.icon; + }, + + // @method setIcon(icon: Icon): this + // Changes the marker icon. + setIcon: function (icon) { + + this.options.icon = icon; + + if (this._map) { + this._initIcon(); + this.update(); + } + + if (this._popup) { + this.bindPopup(this._popup, this._popup.options); + } + + return this; + }, + + getElement: function () { + return this._icon; + }, + + update: function () { + + if (this._icon && this._map) { + var pos = this._map.latLngToLayerPoint(this._latlng).round(); + this._setPos(pos); + } + + return this; + }, + + _initIcon: function () { + var options = this.options, + classToAdd = 'leaflet-zoom-' + (this._zoomAnimated ? 'animated' : 'hide'); + + var icon = options.icon.createIcon(this._icon), + addIcon = false; + + // if we're not reusing the icon, remove the old one and init new one + if (icon !== this._icon) { + if (this._icon) { + this._removeIcon(); + } + addIcon = true; + + if (options.title) { + icon.title = options.title; + } + + if (icon.tagName === 'IMG') { + icon.alt = options.alt || ''; + } + } + + addClass(icon, classToAdd); + + if (options.keyboard) { + icon.tabIndex = '0'; + } + + this._icon = icon; + + if (options.riseOnHover) { + this.on({ + mouseover: this._bringToFront, + mouseout: this._resetZIndex + }); + } + + var newShadow = options.icon.createShadow(this._shadow), + addShadow = false; + + if (newShadow !== this._shadow) { + this._removeShadow(); + addShadow = true; + } + + if (newShadow) { + addClass(newShadow, classToAdd); + newShadow.alt = ''; + } + this._shadow = newShadow; + + + if (options.opacity < 1) { + this._updateOpacity(); + } + + + if (addIcon) { + this.getPane().appendChild(this._icon); + } + this._initInteraction(); + if (newShadow && addShadow) { + this.getPane(options.shadowPane).appendChild(this._shadow); + } + }, + + _removeIcon: function () { + if (this.options.riseOnHover) { + this.off({ + mouseover: this._bringToFront, + mouseout: this._resetZIndex + }); + } + + remove(this._icon); + this.removeInteractiveTarget(this._icon); + + this._icon = null; + }, + + _removeShadow: function () { + if (this._shadow) { + remove(this._shadow); + } + this._shadow = null; + }, + + _setPos: function (pos) { + + if (this._icon) { + setPosition(this._icon, pos); + } + + if (this._shadow) { + setPosition(this._shadow, pos); + } + + this._zIndex = pos.y + this.options.zIndexOffset; + + this._resetZIndex(); + }, + + _updateZIndex: function (offset) { + if (this._icon) { + this._icon.style.zIndex = this._zIndex + offset; + } + }, + + _animateZoom: function (opt) { + var pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center).round(); + + this._setPos(pos); + }, + + _initInteraction: function () { + + if (!this.options.interactive) { return; } + + addClass(this._icon, 'leaflet-interactive'); + + this.addInteractiveTarget(this._icon); + + if (MarkerDrag) { + var draggable = this.options.draggable; + if (this.dragging) { + draggable = this.dragging.enabled(); + this.dragging.disable(); + } + + this.dragging = new MarkerDrag(this); + + if (draggable) { + this.dragging.enable(); + } + } + }, + + // @method setOpacity(opacity: Number): this + // Changes the opacity of the marker. + setOpacity: function (opacity) { + this.options.opacity = opacity; + if (this._map) { + this._updateOpacity(); + } + + return this; + }, + + _updateOpacity: function () { + var opacity = this.options.opacity; + + if (this._icon) { + setOpacity(this._icon, opacity); + } + + if (this._shadow) { + setOpacity(this._shadow, opacity); + } + }, + + _bringToFront: function () { + this._updateZIndex(this.options.riseOffset); + }, + + _resetZIndex: function () { + this._updateZIndex(0); + }, + + _getPopupAnchor: function () { + return this.options.icon.options.popupAnchor; + }, + + _getTooltipAnchor: function () { + return this.options.icon.options.tooltipAnchor; + } +}); + + +// factory L.marker(latlng: LatLng, options? : Marker options) + +// @factory L.marker(latlng: LatLng, options? : Marker options) +// Instantiates a Marker object given a geographical point and optionally an options object. +function marker(latlng, options) { + return new Marker(latlng, options); +} + +/* + * @class Path + * @aka L.Path + * @inherits Interactive layer + * + * An abstract class that contains options and constants shared between vector + * overlays (Polygon, Polyline, Circle). Do not use it directly. Extends `Layer`. + */ + +var Path = Layer.extend({ + + // @section + // @aka Path options + options: { + // @option stroke: Boolean = true + // Whether to draw stroke along the path. Set it to `false` to disable borders on polygons or circles. + stroke: true, + + // @option color: String = '#3388ff' + // Stroke color + color: '#3388ff', + + // @option weight: Number = 3 + // Stroke width in pixels + weight: 3, + + // @option opacity: Number = 1.0 + // Stroke opacity + opacity: 1, + + // @option lineCap: String= 'round' + // A string that defines [shape to be used at the end](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-linecap) of the stroke. + lineCap: 'round', + + // @option lineJoin: String = 'round' + // A string that defines [shape to be used at the corners](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-linejoin) of the stroke. + lineJoin: 'round', + + // @option dashArray: String = null + // A string that defines the stroke [dash pattern](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-dasharray). Doesn't work on `Canvas`-powered layers in [some old browsers](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/setLineDash#Browser_compatibility). + dashArray: null, + + // @option dashOffset: String = null + // A string that defines the [distance into the dash pattern to start the dash](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-dashoffset). Doesn't work on `Canvas`-powered layers in [some old browsers](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/setLineDash#Browser_compatibility). + dashOffset: null, + + // @option fill: Boolean = depends + // Whether to fill the path with color. Set it to `false` to disable filling on polygons or circles. + fill: false, + + // @option fillColor: String = * + // Fill color. Defaults to the value of the [`color`](#path-color) option + fillColor: null, + + // @option fillOpacity: Number = 0.2 + // Fill opacity. + fillOpacity: 0.2, + + // @option fillRule: String = 'evenodd' + // A string that defines [how the inside of a shape](https://developer.mozilla.org/docs/Web/SVG/Attribute/fill-rule) is determined. + fillRule: 'evenodd', + + // className: '', + + // Option inherited from "Interactive layer" abstract class + interactive: true, + + // @option bubblingMouseEvents: Boolean = true + // When `true`, a mouse event on this path will trigger the same event on the map + // (unless [`L.DomEvent.stopPropagation`](#domevent-stoppropagation) is used). + bubblingMouseEvents: true + }, + + beforeAdd: function (map) { + // Renderer is set here because we need to call renderer.getEvents + // before this.getEvents. + this._renderer = map.getRenderer(this); + }, + + onAdd: function () { + this._renderer._initPath(this); + this._reset(); + this._renderer._addPath(this); + }, + + onRemove: function () { + this._renderer._removePath(this); + }, + + // @method redraw(): this + // Redraws the layer. Sometimes useful after you changed the coordinates that the path uses. + redraw: function () { + if (this._map) { + this._renderer._updatePath(this); + } + return this; + }, + + // @method setStyle(style: Path options): this + // Changes the appearance of a Path based on the options in the `Path options` object. + setStyle: function (style) { + setOptions(this, style); + if (this._renderer) { + this._renderer._updateStyle(this); + if (this.options.stroke && style && style.hasOwnProperty('weight')) { + this._updateBounds(); + } + } + return this; + }, + + // @method bringToFront(): this + // Brings the layer to the top of all path layers. + bringToFront: function () { + if (this._renderer) { + this._renderer._bringToFront(this); + } + return this; + }, + + // @method bringToBack(): this + // Brings the layer to the bottom of all path layers. + bringToBack: function () { + if (this._renderer) { + this._renderer._bringToBack(this); + } + return this; + }, + + getElement: function () { + return this._path; + }, + + _reset: function () { + // defined in child classes + this._project(); + this._update(); + }, + + _clickTolerance: function () { + // used when doing hit detection for Canvas layers + return (this.options.stroke ? this.options.weight / 2 : 0) + this._renderer.options.tolerance; + } +}); + +/* + * @class CircleMarker + * @aka L.CircleMarker + * @inherits Path + * + * A circle of a fixed size with radius specified in pixels. Extends `Path`. + */ + +var CircleMarker = Path.extend({ + + // @section + // @aka CircleMarker options + options: { + fill: true, + + // @option radius: Number = 10 + // Radius of the circle marker, in pixels + radius: 10 + }, + + initialize: function (latlng, options) { + setOptions(this, options); + this._latlng = toLatLng(latlng); + this._radius = this.options.radius; + }, + + // @method setLatLng(latLng: LatLng): this + // Sets the position of a circle marker to a new location. + setLatLng: function (latlng) { + var oldLatLng = this._latlng; + this._latlng = toLatLng(latlng); + this.redraw(); + + // @event move: Event + // Fired when the marker is moved via [`setLatLng`](#circlemarker-setlatlng). Old and new coordinates are included in event arguments as `oldLatLng`, `latlng`. + return this.fire('move', {oldLatLng: oldLatLng, latlng: this._latlng}); + }, + + // @method getLatLng(): LatLng + // Returns the current geographical position of the circle marker + getLatLng: function () { + return this._latlng; + }, + + // @method setRadius(radius: Number): this + // Sets the radius of a circle marker. Units are in pixels. + setRadius: function (radius) { + this.options.radius = this._radius = radius; + return this.redraw(); + }, + + // @method getRadius(): Number + // Returns the current radius of the circle + getRadius: function () { + return this._radius; + }, + + setStyle : function (options) { + var radius = options && options.radius || this._radius; + Path.prototype.setStyle.call(this, options); + this.setRadius(radius); + return this; + }, + + _project: function () { + this._point = this._map.latLngToLayerPoint(this._latlng); + this._updateBounds(); + }, + + _updateBounds: function () { + var r = this._radius, + r2 = this._radiusY || r, + w = this._clickTolerance(), + p = [r + w, r2 + w]; + this._pxBounds = new Bounds(this._point.subtract(p), this._point.add(p)); + }, + + _update: function () { + if (this._map) { + this._updatePath(); + } + }, + + _updatePath: function () { + this._renderer._updateCircle(this); + }, + + _empty: function () { + return this._radius && !this._renderer._bounds.intersects(this._pxBounds); + }, + + // Needed by the `Canvas` renderer for interactivity + _containsPoint: function (p) { + return p.distanceTo(this._point) <= this._radius + this._clickTolerance(); + } +}); + + +// @factory L.circleMarker(latlng: LatLng, options?: CircleMarker options) +// Instantiates a circle marker object given a geographical point, and an optional options object. +function circleMarker(latlng, options) { + return new CircleMarker(latlng, options); +} + +/* + * @class Circle + * @aka L.Circle + * @inherits CircleMarker + * + * A class for drawing circle overlays on a map. Extends `CircleMarker`. + * + * It's an approximation and starts to diverge from a real circle closer to poles (due to projection distortion). + * + * @example + * + * ```js + * L.circle([50.5, 30.5], {radius: 200}).addTo(map); + * ``` + */ + +var Circle = CircleMarker.extend({ + + initialize: function (latlng, options, legacyOptions) { + if (typeof options === 'number') { + // Backwards compatibility with 0.7.x factory (latlng, radius, options?) + options = extend({}, legacyOptions, {radius: options}); + } + setOptions(this, options); + this._latlng = toLatLng(latlng); + + if (isNaN(this.options.radius)) { throw new Error('Circle radius cannot be NaN'); } + + // @section + // @aka Circle options + // @option radius: Number; Radius of the circle, in meters. + this._mRadius = this.options.radius; + }, + + // @method setRadius(radius: Number): this + // Sets the radius of a circle. Units are in meters. + setRadius: function (radius) { + this._mRadius = radius; + return this.redraw(); + }, + + // @method getRadius(): Number + // Returns the current radius of a circle. Units are in meters. + getRadius: function () { + return this._mRadius; + }, + + // @method getBounds(): LatLngBounds + // Returns the `LatLngBounds` of the path. + getBounds: function () { + var half = [this._radius, this._radiusY || this._radius]; + + return new LatLngBounds( + this._map.layerPointToLatLng(this._point.subtract(half)), + this._map.layerPointToLatLng(this._point.add(half))); + }, + + setStyle: Path.prototype.setStyle, + + _project: function () { + + var lng = this._latlng.lng, + lat = this._latlng.lat, + map = this._map, + crs = map.options.crs; + + if (crs.distance === Earth.distance) { + var d = Math.PI / 180, + latR = (this._mRadius / Earth.R) / d, + top = map.project([lat + latR, lng]), + bottom = map.project([lat - latR, lng]), + p = top.add(bottom).divideBy(2), + lat2 = map.unproject(p).lat, + lngR = Math.acos((Math.cos(latR * d) - Math.sin(lat * d) * Math.sin(lat2 * d)) / + (Math.cos(lat * d) * Math.cos(lat2 * d))) / d; + + if (isNaN(lngR) || lngR === 0) { + lngR = latR / Math.cos(Math.PI / 180 * lat); // Fallback for edge case, #2425 + } + + this._point = p.subtract(map.getPixelOrigin()); + this._radius = isNaN(lngR) ? 0 : p.x - map.project([lat2, lng - lngR]).x; + this._radiusY = p.y - top.y; + + } else { + var latlng2 = crs.unproject(crs.project(this._latlng).subtract([this._mRadius, 0])); + + this._point = map.latLngToLayerPoint(this._latlng); + this._radius = this._point.x - map.latLngToLayerPoint(latlng2).x; + } + + this._updateBounds(); + } +}); + +// @factory L.circle(latlng: LatLng, options?: Circle options) +// Instantiates a circle object given a geographical point, and an options object +// which contains the circle radius. +// @alternative +// @factory L.circle(latlng: LatLng, radius: Number, options?: Circle options) +// Obsolete way of instantiating a circle, for compatibility with 0.7.x code. +// Do not use in new applications or plugins. +function circle(latlng, options, legacyOptions) { + return new Circle(latlng, options, legacyOptions); +} + +/* + * @class Polyline + * @aka L.Polyline + * @inherits Path + * + * A class for drawing polyline overlays on a map. Extends `Path`. + * + * @example + * + * ```js + * // create a red polyline from an array of LatLng points + * var latlngs = [ + * [45.51, -122.68], + * [37.77, -122.43], + * [34.04, -118.2] + * ]; + * + * var polyline = L.polyline(latlngs, {color: 'red'}).addTo(map); + * + * // zoom the map to the polyline + * map.fitBounds(polyline.getBounds()); + * ``` + * + * You can also pass a multi-dimensional array to represent a `MultiPolyline` shape: + * + * ```js + * // create a red polyline from an array of arrays of LatLng points + * var latlngs = [ + * [[45.51, -122.68], + * [37.77, -122.43], + * [34.04, -118.2]], + * [[40.78, -73.91], + * [41.83, -87.62], + * [32.76, -96.72]] + * ]; + * ``` + */ + + +var Polyline = Path.extend({ + + // @section + // @aka Polyline options + options: { + // @option smoothFactor: Number = 1.0 + // How much to simplify the polyline on each zoom level. More means + // better performance and smoother look, and less means more accurate representation. + smoothFactor: 1.0, + + // @option noClip: Boolean = false + // Disable polyline clipping. + noClip: false + }, + + initialize: function (latlngs, options) { + setOptions(this, options); + this._setLatLngs(latlngs); + }, + + // @method getLatLngs(): LatLng[] + // Returns an array of the points in the path, or nested arrays of points in case of multi-polyline. + getLatLngs: function () { + return this._latlngs; + }, + + // @method setLatLngs(latlngs: LatLng[]): this + // Replaces all the points in the polyline with the given array of geographical points. + setLatLngs: function (latlngs) { + this._setLatLngs(latlngs); + return this.redraw(); + }, + + // @method isEmpty(): Boolean + // Returns `true` if the Polyline has no LatLngs. + isEmpty: function () { + return !this._latlngs.length; + }, + + // @method closestLayerPoint(p: Point): Point + // Returns the point closest to `p` on the Polyline. + closestLayerPoint: function (p) { + var minDistance = Infinity, + minPoint = null, + closest = _sqClosestPointOnSegment, + p1, p2; + + for (var j = 0, jLen = this._parts.length; j < jLen; j++) { + var points = this._parts[j]; + + for (var i = 1, len = points.length; i < len; i++) { + p1 = points[i - 1]; + p2 = points[i]; + + var sqDist = closest(p, p1, p2, true); + + if (sqDist < minDistance) { + minDistance = sqDist; + minPoint = closest(p, p1, p2); + } + } + } + if (minPoint) { + minPoint.distance = Math.sqrt(minDistance); + } + return minPoint; + }, + + // @method getCenter(): LatLng + // Returns the center ([centroid](http://en.wikipedia.org/wiki/Centroid)) of the polyline. + getCenter: function () { + // throws error when not yet added to map as this center calculation requires projected coordinates + if (!this._map) { + throw new Error('Must add layer to map before using getCenter()'); + } + + var i, halfDist, segDist, dist, p1, p2, ratio, + points = this._rings[0], + len = points.length; + + if (!len) { return null; } + + // polyline centroid algorithm; only uses the first ring if there are multiple + + for (i = 0, halfDist = 0; i < len - 1; i++) { + halfDist += points[i].distanceTo(points[i + 1]) / 2; + } + + // The line is so small in the current view that all points are on the same pixel. + if (halfDist === 0) { + return this._map.layerPointToLatLng(points[0]); + } + + for (i = 0, dist = 0; i < len - 1; i++) { + p1 = points[i]; + p2 = points[i + 1]; + segDist = p1.distanceTo(p2); + dist += segDist; + + if (dist > halfDist) { + ratio = (dist - halfDist) / segDist; + return this._map.layerPointToLatLng([ + p2.x - ratio * (p2.x - p1.x), + p2.y - ratio * (p2.y - p1.y) + ]); + } + } + }, + + // @method getBounds(): LatLngBounds + // Returns the `LatLngBounds` of the path. + getBounds: function () { + return this._bounds; + }, + + // @method addLatLng(latlng: LatLng, latlngs? LatLng[]): this + // Adds a given point to the polyline. By default, adds to the first ring of + // the polyline in case of a multi-polyline, but can be overridden by passing + // a specific ring as a LatLng array (that you can earlier access with [`getLatLngs`](#polyline-getlatlngs)). + addLatLng: function (latlng, latlngs) { + latlngs = latlngs || this._defaultShape(); + latlng = toLatLng(latlng); + latlngs.push(latlng); + this._bounds.extend(latlng); + return this.redraw(); + }, + + _setLatLngs: function (latlngs) { + this._bounds = new LatLngBounds(); + this._latlngs = this._convertLatLngs(latlngs); + }, + + _defaultShape: function () { + return isFlat(this._latlngs) ? this._latlngs : this._latlngs[0]; + }, + + // recursively convert latlngs input into actual LatLng instances; calculate bounds along the way + _convertLatLngs: function (latlngs) { + var result = [], + flat = isFlat(latlngs); + + for (var i = 0, len = latlngs.length; i < len; i++) { + if (flat) { + result[i] = toLatLng(latlngs[i]); + this._bounds.extend(result[i]); + } else { + result[i] = this._convertLatLngs(latlngs[i]); + } + } + + return result; + }, + + _project: function () { + var pxBounds = new Bounds(); + this._rings = []; + this._projectLatlngs(this._latlngs, this._rings, pxBounds); + + if (this._bounds.isValid() && pxBounds.isValid()) { + this._rawPxBounds = pxBounds; + this._updateBounds(); + } + }, + + _updateBounds: function () { + var w = this._clickTolerance(), + p = new Point(w, w); + this._pxBounds = new Bounds([ + this._rawPxBounds.min.subtract(p), + this._rawPxBounds.max.add(p) + ]); + }, + + // recursively turns latlngs into a set of rings with projected coordinates + _projectLatlngs: function (latlngs, result, projectedBounds) { + var flat = latlngs[0] instanceof LatLng, + len = latlngs.length, + i, ring; + + if (flat) { + ring = []; + for (i = 0; i < len; i++) { + ring[i] = this._map.latLngToLayerPoint(latlngs[i]); + projectedBounds.extend(ring[i]); + } + result.push(ring); + } else { + for (i = 0; i < len; i++) { + this._projectLatlngs(latlngs[i], result, projectedBounds); + } + } + }, + + // clip polyline by renderer bounds so that we have less to render for performance + _clipPoints: function () { + var bounds = this._renderer._bounds; + + this._parts = []; + if (!this._pxBounds || !this._pxBounds.intersects(bounds)) { + return; + } + + if (this.options.noClip) { + this._parts = this._rings; + return; + } + + var parts = this._parts, + i, j, k, len, len2, segment, points; + + for (i = 0, k = 0, len = this._rings.length; i < len; i++) { + points = this._rings[i]; + + for (j = 0, len2 = points.length; j < len2 - 1; j++) { + segment = clipSegment(points[j], points[j + 1], bounds, j, true); + + if (!segment) { continue; } + + parts[k] = parts[k] || []; + parts[k].push(segment[0]); + + // if segment goes out of screen, or it's the last one, it's the end of the line part + if ((segment[1] !== points[j + 1]) || (j === len2 - 2)) { + parts[k].push(segment[1]); + k++; + } + } + } + }, + + // simplify each clipped part of the polyline for performance + _simplifyPoints: function () { + var parts = this._parts, + tolerance = this.options.smoothFactor; + + for (var i = 0, len = parts.length; i < len; i++) { + parts[i] = simplify(parts[i], tolerance); + } + }, + + _update: function () { + if (!this._map) { return; } + + this._clipPoints(); + this._simplifyPoints(); + this._updatePath(); + }, + + _updatePath: function () { + this._renderer._updatePoly(this); + }, + + // Needed by the `Canvas` renderer for interactivity + _containsPoint: function (p, closed) { + var i, j, k, len, len2, part, + w = this._clickTolerance(); + + if (!this._pxBounds || !this._pxBounds.contains(p)) { return false; } + + // hit detection for polylines + for (i = 0, len = this._parts.length; i < len; i++) { + part = this._parts[i]; + + for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) { + if (!closed && (j === 0)) { continue; } + + if (pointToSegmentDistance(p, part[k], part[j]) <= w) { + return true; + } + } + } + return false; + } +}); + +// @factory L.polyline(latlngs: LatLng[], options?: Polyline options) +// Instantiates a polyline object given an array of geographical points and +// optionally an options object. You can create a `Polyline` object with +// multiple separate lines (`MultiPolyline`) by passing an array of arrays +// of geographic points. +function polyline(latlngs, options) { + return new Polyline(latlngs, options); +} + +// Retrocompat. Allow plugins to support Leaflet versions before and after 1.1. +Polyline._flat = _flat; + +/* + * @class Polygon + * @aka L.Polygon + * @inherits Polyline + * + * A class for drawing polygon overlays on a map. Extends `Polyline`. + * + * Note that points you pass when creating a polygon shouldn't have an additional last point equal to the first one — it's better to filter out such points. + * + * + * @example + * + * ```js + * // create a red polygon from an array of LatLng points + * var latlngs = [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]]; + * + * var polygon = L.polygon(latlngs, {color: 'red'}).addTo(map); + * + * // zoom the map to the polygon + * map.fitBounds(polygon.getBounds()); + * ``` + * + * You can also pass an array of arrays of latlngs, with the first array representing the outer shape and the other arrays representing holes in the outer shape: + * + * ```js + * var latlngs = [ + * [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring + * [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole + * ]; + * ``` + * + * Additionally, you can pass a multi-dimensional array to represent a MultiPolygon shape. + * + * ```js + * var latlngs = [ + * [ // first polygon + * [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring + * [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole + * ], + * [ // second polygon + * [[41, -111.03],[45, -111.04],[45, -104.05],[41, -104.05]] + * ] + * ]; + * ``` + */ + +var Polygon = Polyline.extend({ + + options: { + fill: true + }, + + isEmpty: function () { + return !this._latlngs.length || !this._latlngs[0].length; + }, + + getCenter: function () { + // throws error when not yet added to map as this center calculation requires projected coordinates + if (!this._map) { + throw new Error('Must add layer to map before using getCenter()'); + } + + var i, j, p1, p2, f, area, x, y, center, + points = this._rings[0], + len = points.length; + + if (!len) { return null; } + + // polygon centroid algorithm; only uses the first ring if there are multiple + + area = x = y = 0; + + for (i = 0, j = len - 1; i < len; j = i++) { + p1 = points[i]; + p2 = points[j]; + + f = p1.y * p2.x - p2.y * p1.x; + x += (p1.x + p2.x) * f; + y += (p1.y + p2.y) * f; + area += f * 3; + } + + if (area === 0) { + // Polygon is so small that all points are on same pixel. + center = points[0]; + } else { + center = [x / area, y / area]; + } + return this._map.layerPointToLatLng(center); + }, + + _convertLatLngs: function (latlngs) { + var result = Polyline.prototype._convertLatLngs.call(this, latlngs), + len = result.length; + + // remove last point if it equals first one + if (len >= 2 && result[0] instanceof LatLng && result[0].equals(result[len - 1])) { + result.pop(); + } + return result; + }, + + _setLatLngs: function (latlngs) { + Polyline.prototype._setLatLngs.call(this, latlngs); + if (isFlat(this._latlngs)) { + this._latlngs = [this._latlngs]; + } + }, + + _defaultShape: function () { + return isFlat(this._latlngs[0]) ? this._latlngs[0] : this._latlngs[0][0]; + }, + + _clipPoints: function () { + // polygons need a different clipping algorithm so we redefine that + + var bounds = this._renderer._bounds, + w = this.options.weight, + p = new Point(w, w); + + // increase clip padding by stroke width to avoid stroke on clip edges + bounds = new Bounds(bounds.min.subtract(p), bounds.max.add(p)); + + this._parts = []; + if (!this._pxBounds || !this._pxBounds.intersects(bounds)) { + return; + } + + if (this.options.noClip) { + this._parts = this._rings; + return; + } + + for (var i = 0, len = this._rings.length, clipped; i < len; i++) { + clipped = clipPolygon(this._rings[i], bounds, true); + if (clipped.length) { + this._parts.push(clipped); + } + } + }, + + _updatePath: function () { + this._renderer._updatePoly(this, true); + }, + + // Needed by the `Canvas` renderer for interactivity + _containsPoint: function (p) { + var inside = false, + part, p1, p2, i, j, k, len, len2; + + if (!this._pxBounds || !this._pxBounds.contains(p)) { return false; } + + // ray casting algorithm for detecting if point is in polygon + for (i = 0, len = this._parts.length; i < len; i++) { + part = this._parts[i]; + + for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) { + p1 = part[j]; + p2 = part[k]; + + if (((p1.y > p.y) !== (p2.y > p.y)) && (p.x < (p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x)) { + inside = !inside; + } + } + } + + // also check if it's on polygon stroke + return inside || Polyline.prototype._containsPoint.call(this, p, true); + } + +}); + + +// @factory L.polygon(latlngs: LatLng[], options?: Polyline options) +function polygon(latlngs, options) { + return new Polygon(latlngs, options); +} + +/* + * @class GeoJSON + * @aka L.GeoJSON + * @inherits FeatureGroup + * + * Represents a GeoJSON object or an array of GeoJSON objects. Allows you to parse + * GeoJSON data and display it on the map. Extends `FeatureGroup`. + * + * @example + * + * ```js + * L.geoJSON(data, { + * style: function (feature) { + * return {color: feature.properties.color}; + * } + * }).bindPopup(function (layer) { + * return layer.feature.properties.description; + * }).addTo(map); + * ``` + */ + +var GeoJSON = FeatureGroup.extend({ + + /* @section + * @aka GeoJSON options + * + * @option pointToLayer: Function = * + * A `Function` defining how GeoJSON points spawn Leaflet layers. It is internally + * called when data is added, passing the GeoJSON point feature and its `LatLng`. + * The default is to spawn a default `Marker`: + * ```js + * function(geoJsonPoint, latlng) { + * return L.marker(latlng); + * } + * ``` + * + * @option style: Function = * + * A `Function` defining the `Path options` for styling GeoJSON lines and polygons, + * called internally when data is added. + * The default value is to not override any defaults: + * ```js + * function (geoJsonFeature) { + * return {} + * } + * ``` + * + * @option onEachFeature: Function = * + * A `Function` that will be called once for each created `Feature`, after it has + * been created and styled. Useful for attaching events and popups to features. + * The default is to do nothing with the newly created layers: + * ```js + * function (feature, layer) {} + * ``` + * + * @option filter: Function = * + * A `Function` that will be used to decide whether to include a feature or not. + * The default is to include all features: + * ```js + * function (geoJsonFeature) { + * return true; + * } + * ``` + * Note: dynamically changing the `filter` option will have effect only on newly + * added data. It will _not_ re-evaluate already included features. + * + * @option coordsToLatLng: Function = * + * A `Function` that will be used for converting GeoJSON coordinates to `LatLng`s. + * The default is the `coordsToLatLng` static method. + * + * @option markersInheritOptions: Boolean = false + * Whether default Markers for "Point" type Features inherit from group options. + */ + + initialize: function (geojson, options) { + setOptions(this, options); + + this._layers = {}; + + if (geojson) { + this.addData(geojson); + } + }, + + // @method addData( data ): this + // Adds a GeoJSON object to the layer. + addData: function (geojson) { + var features = isArray(geojson) ? geojson : geojson.features, + i, len, feature; + + if (features) { + for (i = 0, len = features.length; i < len; i++) { + // only add this if geometry or geometries are set and not null + feature = features[i]; + if (feature.geometries || feature.geometry || feature.features || feature.coordinates) { + this.addData(feature); + } + } + return this; + } + + var options = this.options; + + if (options.filter && !options.filter(geojson)) { return this; } + + var layer = geometryToLayer(geojson, options); + if (!layer) { + return this; + } + layer.feature = asFeature(geojson); + + layer.defaultOptions = layer.options; + this.resetStyle(layer); + + if (options.onEachFeature) { + options.onEachFeature(geojson, layer); + } + + return this.addLayer(layer); + }, + + // @method resetStyle( layer? ): this + // Resets the given vector layer's style to the original GeoJSON style, useful for resetting style after hover events. + // If `layer` is omitted, the style of all features in the current layer is reset. + resetStyle: function (layer) { + if (layer === undefined) { + return this.eachLayer(this.resetStyle, this); + } + // reset any custom styles + layer.options = extend({}, layer.defaultOptions); + this._setLayerStyle(layer, this.options.style); + return this; + }, + + // @method setStyle( style ): this + // Changes styles of GeoJSON vector layers with the given style function. + setStyle: function (style) { + return this.eachLayer(function (layer) { + this._setLayerStyle(layer, style); + }, this); + }, + + _setLayerStyle: function (layer, style) { + if (layer.setStyle) { + if (typeof style === 'function') { + style = style(layer.feature); + } + layer.setStyle(style); + } + } +}); + +// @section +// There are several static functions which can be called without instantiating L.GeoJSON: + +// @function geometryToLayer(featureData: Object, options?: GeoJSON options): Layer +// Creates a `Layer` from a given GeoJSON feature. Can use a custom +// [`pointToLayer`](#geojson-pointtolayer) and/or [`coordsToLatLng`](#geojson-coordstolatlng) +// functions if provided as options. +function geometryToLayer(geojson, options) { + + var geometry = geojson.type === 'Feature' ? geojson.geometry : geojson, + coords = geometry ? geometry.coordinates : null, + layers = [], + pointToLayer = options && options.pointToLayer, + _coordsToLatLng = options && options.coordsToLatLng || coordsToLatLng, + latlng, latlngs, i, len; + + if (!coords && !geometry) { + return null; + } + + switch (geometry.type) { + case 'Point': + latlng = _coordsToLatLng(coords); + return _pointToLayer(pointToLayer, geojson, latlng, options); + + case 'MultiPoint': + for (i = 0, len = coords.length; i < len; i++) { + latlng = _coordsToLatLng(coords[i]); + layers.push(_pointToLayer(pointToLayer, geojson, latlng, options)); + } + return new FeatureGroup(layers); + + case 'LineString': + case 'MultiLineString': + latlngs = coordsToLatLngs(coords, geometry.type === 'LineString' ? 0 : 1, _coordsToLatLng); + return new Polyline(latlngs, options); + + case 'Polygon': + case 'MultiPolygon': + latlngs = coordsToLatLngs(coords, geometry.type === 'Polygon' ? 1 : 2, _coordsToLatLng); + return new Polygon(latlngs, options); + + case 'GeometryCollection': + for (i = 0, len = geometry.geometries.length; i < len; i++) { + var layer = geometryToLayer({ + geometry: geometry.geometries[i], + type: 'Feature', + properties: geojson.properties + }, options); + + if (layer) { + layers.push(layer); + } + } + return new FeatureGroup(layers); + + default: + throw new Error('Invalid GeoJSON object.'); + } +} + +function _pointToLayer(pointToLayerFn, geojson, latlng, options) { + return pointToLayerFn ? + pointToLayerFn(geojson, latlng) : + new Marker(latlng, options && options.markersInheritOptions && options); +} + +// @function coordsToLatLng(coords: Array): LatLng +// Creates a `LatLng` object from an array of 2 numbers (longitude, latitude) +// or 3 numbers (longitude, latitude, altitude) used in GeoJSON for points. +function coordsToLatLng(coords) { + return new LatLng(coords[1], coords[0], coords[2]); +} + +// @function coordsToLatLngs(coords: Array, levelsDeep?: Number, coordsToLatLng?: Function): Array +// Creates a multidimensional array of `LatLng`s from a GeoJSON coordinates array. +// `levelsDeep` specifies the nesting level (0 is for an array of points, 1 for an array of arrays of points, etc., 0 by default). +// Can use a custom [`coordsToLatLng`](#geojson-coordstolatlng) function. +function coordsToLatLngs(coords, levelsDeep, _coordsToLatLng) { + var latlngs = []; + + for (var i = 0, len = coords.length, latlng; i < len; i++) { + latlng = levelsDeep ? + coordsToLatLngs(coords[i], levelsDeep - 1, _coordsToLatLng) : + (_coordsToLatLng || coordsToLatLng)(coords[i]); + + latlngs.push(latlng); + } + + return latlngs; +} + +// @function latLngToCoords(latlng: LatLng, precision?: Number): Array +// Reverse of [`coordsToLatLng`](#geojson-coordstolatlng) +function latLngToCoords(latlng, precision) { + precision = typeof precision === 'number' ? precision : 6; + return latlng.alt !== undefined ? + [formatNum(latlng.lng, precision), formatNum(latlng.lat, precision), formatNum(latlng.alt, precision)] : + [formatNum(latlng.lng, precision), formatNum(latlng.lat, precision)]; +} + +// @function latLngsToCoords(latlngs: Array, levelsDeep?: Number, closed?: Boolean): Array +// Reverse of [`coordsToLatLngs`](#geojson-coordstolatlngs) +// `closed` determines whether the first point should be appended to the end of the array to close the feature, only used when `levelsDeep` is 0. False by default. +function latLngsToCoords(latlngs, levelsDeep, closed, precision) { + var coords = []; + + for (var i = 0, len = latlngs.length; i < len; i++) { + coords.push(levelsDeep ? + latLngsToCoords(latlngs[i], levelsDeep - 1, closed, precision) : + latLngToCoords(latlngs[i], precision)); + } + + if (!levelsDeep && closed) { + coords.push(coords[0]); + } + + return coords; +} + +function getFeature(layer, newGeometry) { + return layer.feature ? + extend({}, layer.feature, {geometry: newGeometry}) : + asFeature(newGeometry); +} + +// @function asFeature(geojson: Object): Object +// Normalize GeoJSON geometries/features into GeoJSON features. +function asFeature(geojson) { + if (geojson.type === 'Feature' || geojson.type === 'FeatureCollection') { + return geojson; + } + + return { + type: 'Feature', + properties: {}, + geometry: geojson + }; +} + +var PointToGeoJSON = { + toGeoJSON: function (precision) { + return getFeature(this, { + type: 'Point', + coordinates: latLngToCoords(this.getLatLng(), precision) + }); + } +}; + +// @namespace Marker +// @section Other methods +// @method toGeoJSON(precision?: Number): Object +// `precision` is the number of decimal places for coordinates. +// The default value is 6 places. +// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the marker (as a GeoJSON `Point` Feature). +Marker.include(PointToGeoJSON); + +// @namespace CircleMarker +// @method toGeoJSON(precision?: Number): Object +// `precision` is the number of decimal places for coordinates. +// The default value is 6 places. +// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the circle marker (as a GeoJSON `Point` Feature). +Circle.include(PointToGeoJSON); +CircleMarker.include(PointToGeoJSON); + + +// @namespace Polyline +// @method toGeoJSON(precision?: Number): Object +// `precision` is the number of decimal places for coordinates. +// The default value is 6 places. +// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the polyline (as a GeoJSON `LineString` or `MultiLineString` Feature). +Polyline.include({ + toGeoJSON: function (precision) { + var multi = !isFlat(this._latlngs); + + var coords = latLngsToCoords(this._latlngs, multi ? 1 : 0, false, precision); + + return getFeature(this, { + type: (multi ? 'Multi' : '') + 'LineString', + coordinates: coords + }); + } +}); + +// @namespace Polygon +// @method toGeoJSON(precision?: Number): Object +// `precision` is the number of decimal places for coordinates. +// The default value is 6 places. +// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the polygon (as a GeoJSON `Polygon` or `MultiPolygon` Feature). +Polygon.include({ + toGeoJSON: function (precision) { + var holes = !isFlat(this._latlngs), + multi = holes && !isFlat(this._latlngs[0]); + + var coords = latLngsToCoords(this._latlngs, multi ? 2 : holes ? 1 : 0, true, precision); + + if (!holes) { + coords = [coords]; + } + + return getFeature(this, { + type: (multi ? 'Multi' : '') + 'Polygon', + coordinates: coords + }); + } +}); + + +// @namespace LayerGroup +LayerGroup.include({ + toMultiPoint: function (precision) { + var coords = []; + + this.eachLayer(function (layer) { + coords.push(layer.toGeoJSON(precision).geometry.coordinates); + }); + + return getFeature(this, { + type: 'MultiPoint', + coordinates: coords + }); + }, + + // @method toGeoJSON(precision?: Number): Object + // `precision` is the number of decimal places for coordinates. + // The default value is 6 places. + // Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the layer group (as a GeoJSON `FeatureCollection`, `GeometryCollection`, or `MultiPoint`). + toGeoJSON: function (precision) { + + var type = this.feature && this.feature.geometry && this.feature.geometry.type; + + if (type === 'MultiPoint') { + return this.toMultiPoint(precision); + } + + var isGeometryCollection = type === 'GeometryCollection', + jsons = []; + + this.eachLayer(function (layer) { + if (layer.toGeoJSON) { + var json = layer.toGeoJSON(precision); + if (isGeometryCollection) { + jsons.push(json.geometry); + } else { + var feature = asFeature(json); + // Squash nested feature collections + if (feature.type === 'FeatureCollection') { + jsons.push.apply(jsons, feature.features); + } else { + jsons.push(feature); + } + } + } + }); + + if (isGeometryCollection) { + return getFeature(this, { + geometries: jsons, + type: 'GeometryCollection' + }); + } + + return { + type: 'FeatureCollection', + features: jsons + }; + } +}); + +// @namespace GeoJSON +// @factory L.geoJSON(geojson?: Object, options?: GeoJSON options) +// Creates a GeoJSON layer. Optionally accepts an object in +// [GeoJSON format](https://tools.ietf.org/html/rfc7946) to display on the map +// (you can alternatively add it later with `addData` method) and an `options` object. +function geoJSON(geojson, options) { + return new GeoJSON(geojson, options); +} + +// Backward compatibility. +var geoJson = geoJSON; + +/* + * @class ImageOverlay + * @aka L.ImageOverlay + * @inherits Interactive layer + * + * Used to load and display a single image over specific bounds of the map. Extends `Layer`. + * + * @example + * + * ```js + * var imageUrl = 'http://www.lib.utexas.edu/maps/historical/newark_nj_1922.jpg', + * imageBounds = [[40.712216, -74.22655], [40.773941, -74.12544]]; + * L.imageOverlay(imageUrl, imageBounds).addTo(map); + * ``` + */ + +var ImageOverlay = Layer.extend({ + + // @section + // @aka ImageOverlay options + options: { + // @option opacity: Number = 1.0 + // The opacity of the image overlay. + opacity: 1, + + // @option alt: String = '' + // Text for the `alt` attribute of the image (useful for accessibility). + alt: '', + + // @option interactive: Boolean = false + // If `true`, the image overlay will emit [mouse events](#interactive-layer) when clicked or hovered. + interactive: false, + + // @option crossOrigin: Boolean|String = false + // Whether the crossOrigin attribute will be added to the image. + // If a String is provided, the image will have its crossOrigin attribute set to the String provided. This is needed if you want to access image pixel data. + // Refer to [CORS Settings](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) for valid String values. + crossOrigin: false, + + // @option errorOverlayUrl: String = '' + // URL to the overlay image to show in place of the overlay that failed to load. + errorOverlayUrl: '', + + // @option zIndex: Number = 1 + // The explicit [zIndex](https://developer.mozilla.org/docs/Web/CSS/CSS_Positioning/Understanding_z_index) of the overlay layer. + zIndex: 1, + + // @option className: String = '' + // A custom class name to assign to the image. Empty by default. + className: '' + }, + + initialize: function (url, bounds, options) { // (String, LatLngBounds, Object) + this._url = url; + this._bounds = toLatLngBounds(bounds); + + setOptions(this, options); + }, + + onAdd: function () { + if (!this._image) { + this._initImage(); + + if (this.options.opacity < 1) { + this._updateOpacity(); + } + } + + if (this.options.interactive) { + addClass(this._image, 'leaflet-interactive'); + this.addInteractiveTarget(this._image); + } + + this.getPane().appendChild(this._image); + this._reset(); + }, + + onRemove: function () { + remove(this._image); + if (this.options.interactive) { + this.removeInteractiveTarget(this._image); + } + }, + + // @method setOpacity(opacity: Number): this + // Sets the opacity of the overlay. + setOpacity: function (opacity) { + this.options.opacity = opacity; + + if (this._image) { + this._updateOpacity(); + } + return this; + }, + + setStyle: function (styleOpts) { + if (styleOpts.opacity) { + this.setOpacity(styleOpts.opacity); + } + return this; + }, + + // @method bringToFront(): this + // Brings the layer to the top of all overlays. + bringToFront: function () { + if (this._map) { + toFront(this._image); + } + return this; + }, + + // @method bringToBack(): this + // Brings the layer to the bottom of all overlays. + bringToBack: function () { + if (this._map) { + toBack(this._image); + } + return this; + }, + + // @method setUrl(url: String): this + // Changes the URL of the image. + setUrl: function (url) { + this._url = url; + + if (this._image) { + this._image.src = url; + } + return this; + }, + + // @method setBounds(bounds: LatLngBounds): this + // Update the bounds that this ImageOverlay covers + setBounds: function (bounds) { + this._bounds = toLatLngBounds(bounds); + + if (this._map) { + this._reset(); + } + return this; + }, + + getEvents: function () { + var events = { + zoom: this._reset, + viewreset: this._reset + }; + + if (this._zoomAnimated) { + events.zoomanim = this._animateZoom; + } + + return events; + }, + + // @method setZIndex(value: Number): this + // Changes the [zIndex](#imageoverlay-zindex) of the image overlay. + setZIndex: function (value) { + this.options.zIndex = value; + this._updateZIndex(); + return this; + }, + + // @method getBounds(): LatLngBounds + // Get the bounds that this ImageOverlay covers + getBounds: function () { + return this._bounds; + }, + + // @method getElement(): HTMLElement + // Returns the instance of [`HTMLImageElement`](https://developer.mozilla.org/docs/Web/API/HTMLImageElement) + // used by this overlay. + getElement: function () { + return this._image; + }, + + _initImage: function () { + var wasElementSupplied = this._url.tagName === 'IMG'; + var img = this._image = wasElementSupplied ? this._url : create$1('img'); + + addClass(img, 'leaflet-image-layer'); + if (this._zoomAnimated) { addClass(img, 'leaflet-zoom-animated'); } + if (this.options.className) { addClass(img, this.options.className); } + + img.onselectstart = falseFn; + img.onmousemove = falseFn; + + // @event load: Event + // Fired when the ImageOverlay layer has loaded its image + img.onload = bind(this.fire, this, 'load'); + img.onerror = bind(this._overlayOnError, this, 'error'); + + if (this.options.crossOrigin || this.options.crossOrigin === '') { + img.crossOrigin = this.options.crossOrigin === true ? '' : this.options.crossOrigin; + } + + if (this.options.zIndex) { + this._updateZIndex(); + } + + if (wasElementSupplied) { + this._url = img.src; + return; + } + + img.src = this._url; + img.alt = this.options.alt; + }, + + _animateZoom: function (e) { + var scale = this._map.getZoomScale(e.zoom), + offset = this._map._latLngBoundsToNewLayerBounds(this._bounds, e.zoom, e.center).min; + + setTransform(this._image, offset, scale); + }, + + _reset: function () { + var image = this._image, + bounds = new Bounds( + this._map.latLngToLayerPoint(this._bounds.getNorthWest()), + this._map.latLngToLayerPoint(this._bounds.getSouthEast())), + size = bounds.getSize(); + + setPosition(image, bounds.min); + + image.style.width = size.x + 'px'; + image.style.height = size.y + 'px'; + }, + + _updateOpacity: function () { + setOpacity(this._image, this.options.opacity); + }, + + _updateZIndex: function () { + if (this._image && this.options.zIndex !== undefined && this.options.zIndex !== null) { + this._image.style.zIndex = this.options.zIndex; + } + }, + + _overlayOnError: function () { + // @event error: Event + // Fired when the ImageOverlay layer fails to load its image + this.fire('error'); + + var errorUrl = this.options.errorOverlayUrl; + if (errorUrl && this._url !== errorUrl) { + this._url = errorUrl; + this._image.src = errorUrl; + } + } +}); + +// @factory L.imageOverlay(imageUrl: String, bounds: LatLngBounds, options?: ImageOverlay options) +// Instantiates an image overlay object given the URL of the image and the +// geographical bounds it is tied to. +var imageOverlay = function (url, bounds, options) { + return new ImageOverlay(url, bounds, options); +}; + +/* + * @class VideoOverlay + * @aka L.VideoOverlay + * @inherits ImageOverlay + * + * Used to load and display a video player over specific bounds of the map. Extends `ImageOverlay`. + * + * A video overlay uses the [`
` + * element instead of an image. Inherits from `Icon` but ignores the `iconUrl` and shadow options. + * + * @example + * ```js + * var myIcon = L.divIcon({className: 'my-div-icon'}); + * // you can set .my-div-icon styles in CSS + * + * L.marker([50.505, 30.57], {icon: myIcon}).addTo(map); + * ``` + * + * By default, it has a 'leaflet-div-icon' CSS class and is styled as a little white square with a shadow. + */ + +var DivIcon = Icon.extend({ + options: { + // @section + // @aka DivIcon options + iconSize: [12, 12], // also can be set through CSS + + // iconAnchor: (Point), + // popupAnchor: (Point), + + // @option html: String|HTMLElement = '' + // Custom HTML code to put inside the div element, empty by default. Alternatively, + // an instance of `HTMLElement`. + html: false, + + // @option bgPos: Point = [0, 0] + // Optional relative position of the background, in pixels + bgPos: null, + + className: 'leaflet-div-icon' + }, + + createIcon: function (oldIcon) { + var div = (oldIcon && oldIcon.tagName === 'DIV') ? oldIcon : document.createElement('div'), + options = this.options; + + if (options.html instanceof Element) { + empty(div); + div.appendChild(options.html); + } else { + div.innerHTML = options.html !== false ? options.html : ''; + } + + if (options.bgPos) { + var bgPos = toPoint(options.bgPos); + div.style.backgroundPosition = (-bgPos.x) + 'px ' + (-bgPos.y) + 'px'; + } + this._setIconStyles(div, 'icon'); + + return div; + }, + + createShadow: function () { + return null; + } +}); + +// @factory L.divIcon(options: DivIcon options) +// Creates a `DivIcon` instance with the given options. +function divIcon(options) { + return new DivIcon(options); +} + +Icon.Default = IconDefault; + +/* + * @class GridLayer + * @inherits Layer + * @aka L.GridLayer + * + * Generic class for handling a tiled grid of HTML elements. This is the base class for all tile layers and replaces `TileLayer.Canvas`. + * GridLayer can be extended to create a tiled grid of HTML elements like ``, `` or `
`. GridLayer will handle creating and animating these DOM elements for you. + * + * + * @section Synchronous usage + * @example + * + * To create a custom layer, extend GridLayer and implement the `createTile()` method, which will be passed a `Point` object with the `x`, `y`, and `z` (zoom level) coordinates to draw your tile. + * + * ```js + * var CanvasLayer = L.GridLayer.extend({ + * createTile: function(coords){ + * // create a element for drawing + * var tile = L.DomUtil.create('canvas', 'leaflet-tile'); + * + * // setup tile width and height according to the options + * var size = this.getTileSize(); + * tile.width = size.x; + * tile.height = size.y; + * + * // get a canvas context and draw something on it using coords.x, coords.y and coords.z + * var ctx = tile.getContext('2d'); + * + * // return the tile so it can be rendered on screen + * return tile; + * } + * }); + * ``` + * + * @section Asynchronous usage + * @example + * + * Tile creation can also be asynchronous, this is useful when using a third-party drawing library. Once the tile is finished drawing it can be passed to the `done()` callback. + * + * ```js + * var CanvasLayer = L.GridLayer.extend({ + * createTile: function(coords, done){ + * var error; + * + * // create a element for drawing + * var tile = L.DomUtil.create('canvas', 'leaflet-tile'); + * + * // setup tile width and height according to the options + * var size = this.getTileSize(); + * tile.width = size.x; + * tile.height = size.y; + * + * // draw something asynchronously and pass the tile to the done() callback + * setTimeout(function() { + * done(error, tile); + * }, 1000); + * + * return tile; + * } + * }); + * ``` + * + * @section + */ + + +var GridLayer = Layer.extend({ + + // @section + // @aka GridLayer options + options: { + // @option tileSize: Number|Point = 256 + // Width and height of tiles in the grid. Use a number if width and height are equal, or `L.point(width, height)` otherwise. + tileSize: 256, + + // @option opacity: Number = 1.0 + // Opacity of the tiles. Can be used in the `createTile()` function. + opacity: 1, + + // @option updateWhenIdle: Boolean = (depends) + // Load new tiles only when panning ends. + // `true` by default on mobile browsers, in order to avoid too many requests and keep smooth navigation. + // `false` otherwise in order to display new tiles _during_ panning, since it is easy to pan outside the + // [`keepBuffer`](#gridlayer-keepbuffer) option in desktop browsers. + updateWhenIdle: mobile, + + // @option updateWhenZooming: Boolean = true + // By default, a smooth zoom animation (during a [touch zoom](#map-touchzoom) or a [`flyTo()`](#map-flyto)) will update grid layers every integer zoom level. Setting this option to `false` will update the grid layer only when the smooth animation ends. + updateWhenZooming: true, + + // @option updateInterval: Number = 200 + // Tiles will not update more than once every `updateInterval` milliseconds when panning. + updateInterval: 200, + + // @option zIndex: Number = 1 + // The explicit zIndex of the tile layer. + zIndex: 1, + + // @option bounds: LatLngBounds = undefined + // If set, tiles will only be loaded inside the set `LatLngBounds`. + bounds: null, + + // @option minZoom: Number = 0 + // The minimum zoom level down to which this layer will be displayed (inclusive). + minZoom: 0, + + // @option maxZoom: Number = undefined + // The maximum zoom level up to which this layer will be displayed (inclusive). + maxZoom: undefined, + + // @option maxNativeZoom: Number = undefined + // Maximum zoom number the tile source has available. If it is specified, + // the tiles on all zoom levels higher than `maxNativeZoom` will be loaded + // from `maxNativeZoom` level and auto-scaled. + maxNativeZoom: undefined, + + // @option minNativeZoom: Number = undefined + // Minimum zoom number the tile source has available. If it is specified, + // the tiles on all zoom levels lower than `minNativeZoom` will be loaded + // from `minNativeZoom` level and auto-scaled. + minNativeZoom: undefined, + + // @option noWrap: Boolean = false + // Whether the layer is wrapped around the antimeridian. If `true`, the + // GridLayer will only be displayed once at low zoom levels. Has no + // effect when the [map CRS](#map-crs) doesn't wrap around. Can be used + // in combination with [`bounds`](#gridlayer-bounds) to prevent requesting + // tiles outside the CRS limits. + noWrap: false, + + // @option pane: String = 'tilePane' + // `Map pane` where the grid layer will be added. + pane: 'tilePane', + + // @option className: String = '' + // A custom class name to assign to the tile layer. Empty by default. + className: '', + + // @option keepBuffer: Number = 2 + // When panning the map, keep this many rows and columns of tiles before unloading them. + keepBuffer: 2 + }, + + initialize: function (options) { + setOptions(this, options); + }, + + onAdd: function () { + this._initContainer(); + + this._levels = {}; + this._tiles = {}; + + this._resetView(); + this._update(); + }, + + beforeAdd: function (map) { + map._addZoomLimit(this); + }, + + onRemove: function (map) { + this._removeAllTiles(); + remove(this._container); + map._removeZoomLimit(this); + this._container = null; + this._tileZoom = undefined; + }, + + // @method bringToFront: this + // Brings the tile layer to the top of all tile layers. + bringToFront: function () { + if (this._map) { + toFront(this._container); + this._setAutoZIndex(Math.max); + } + return this; + }, + + // @method bringToBack: this + // Brings the tile layer to the bottom of all tile layers. + bringToBack: function () { + if (this._map) { + toBack(this._container); + this._setAutoZIndex(Math.min); + } + return this; + }, + + // @method getContainer: HTMLElement + // Returns the HTML element that contains the tiles for this layer. + getContainer: function () { + return this._container; + }, + + // @method setOpacity(opacity: Number): this + // Changes the [opacity](#gridlayer-opacity) of the grid layer. + setOpacity: function (opacity) { + this.options.opacity = opacity; + this._updateOpacity(); + return this; + }, + + // @method setZIndex(zIndex: Number): this + // Changes the [zIndex](#gridlayer-zindex) of the grid layer. + setZIndex: function (zIndex) { + this.options.zIndex = zIndex; + this._updateZIndex(); + + return this; + }, + + // @method isLoading: Boolean + // Returns `true` if any tile in the grid layer has not finished loading. + isLoading: function () { + return this._loading; + }, + + // @method redraw: this + // Causes the layer to clear all the tiles and request them again. + redraw: function () { + if (this._map) { + this._removeAllTiles(); + this._update(); + } + return this; + }, + + getEvents: function () { + var events = { + viewprereset: this._invalidateAll, + viewreset: this._resetView, + zoom: this._resetView, + moveend: this._onMoveEnd + }; + + if (!this.options.updateWhenIdle) { + // update tiles on move, but not more often than once per given interval + if (!this._onMove) { + this._onMove = throttle(this._onMoveEnd, this.options.updateInterval, this); + } + + events.move = this._onMove; + } + + if (this._zoomAnimated) { + events.zoomanim = this._animateZoom; + } + + return events; + }, + + // @section Extension methods + // Layers extending `GridLayer` shall reimplement the following method. + // @method createTile(coords: Object, done?: Function): HTMLElement + // Called only internally, must be overridden by classes extending `GridLayer`. + // Returns the `HTMLElement` corresponding to the given `coords`. If the `done` callback + // is specified, it must be called when the tile has finished loading and drawing. + createTile: function () { + return document.createElement('div'); + }, + + // @section + // @method getTileSize: Point + // Normalizes the [tileSize option](#gridlayer-tilesize) into a point. Used by the `createTile()` method. + getTileSize: function () { + var s = this.options.tileSize; + return s instanceof Point ? s : new Point(s, s); + }, + + _updateZIndex: function () { + if (this._container && this.options.zIndex !== undefined && this.options.zIndex !== null) { + this._container.style.zIndex = this.options.zIndex; + } + }, + + _setAutoZIndex: function (compare) { + // go through all other layers of the same pane, set zIndex to max + 1 (front) or min - 1 (back) + + var layers = this.getPane().children, + edgeZIndex = -compare(-Infinity, Infinity); // -Infinity for max, Infinity for min + + for (var i = 0, len = layers.length, zIndex; i < len; i++) { + + zIndex = layers[i].style.zIndex; + + if (layers[i] !== this._container && zIndex) { + edgeZIndex = compare(edgeZIndex, +zIndex); + } + } + + if (isFinite(edgeZIndex)) { + this.options.zIndex = edgeZIndex + compare(-1, 1); + this._updateZIndex(); + } + }, + + _updateOpacity: function () { + if (!this._map) { return; } + + // IE doesn't inherit filter opacity properly, so we're forced to set it on tiles + if (ielt9) { return; } + + setOpacity(this._container, this.options.opacity); + + var now = +new Date(), + nextFrame = false, + willPrune = false; + + for (var key in this._tiles) { + var tile = this._tiles[key]; + if (!tile.current || !tile.loaded) { continue; } + + var fade = Math.min(1, (now - tile.loaded) / 200); + + setOpacity(tile.el, fade); + if (fade < 1) { + nextFrame = true; + } else { + if (tile.active) { + willPrune = true; + } else { + this._onOpaqueTile(tile); + } + tile.active = true; + } + } + + if (willPrune && !this._noPrune) { this._pruneTiles(); } + + if (nextFrame) { + cancelAnimFrame(this._fadeFrame); + this._fadeFrame = requestAnimFrame(this._updateOpacity, this); + } + }, + + _onOpaqueTile: falseFn, + + _initContainer: function () { + if (this._container) { return; } + + this._container = create$1('div', 'leaflet-layer ' + (this.options.className || '')); + this._updateZIndex(); + + if (this.options.opacity < 1) { + this._updateOpacity(); + } + + this.getPane().appendChild(this._container); + }, + + _updateLevels: function () { + + var zoom = this._tileZoom, + maxZoom = this.options.maxZoom; + + if (zoom === undefined) { return undefined; } + + for (var z in this._levels) { + if (this._levels[z].el.children.length || z === zoom) { + this._levels[z].el.style.zIndex = maxZoom - Math.abs(zoom - z); + this._onUpdateLevel(z); + } else { + remove(this._levels[z].el); + this._removeTilesAtZoom(z); + this._onRemoveLevel(z); + delete this._levels[z]; + } + } + + var level = this._levels[zoom], + map = this._map; + + if (!level) { + level = this._levels[zoom] = {}; + + level.el = create$1('div', 'leaflet-tile-container leaflet-zoom-animated', this._container); + level.el.style.zIndex = maxZoom; + + level.origin = map.project(map.unproject(map.getPixelOrigin()), zoom).round(); + level.zoom = zoom; + + this._setZoomTransform(level, map.getCenter(), map.getZoom()); + + // force the browser to consider the newly added element for transition + falseFn(level.el.offsetWidth); + + this._onCreateLevel(level); + } + + this._level = level; + + return level; + }, + + _onUpdateLevel: falseFn, + + _onRemoveLevel: falseFn, + + _onCreateLevel: falseFn, + + _pruneTiles: function () { + if (!this._map) { + return; + } + + var key, tile; + + var zoom = this._map.getZoom(); + if (zoom > this.options.maxZoom || + zoom < this.options.minZoom) { + this._removeAllTiles(); + return; + } + + for (key in this._tiles) { + tile = this._tiles[key]; + tile.retain = tile.current; + } + + for (key in this._tiles) { + tile = this._tiles[key]; + if (tile.current && !tile.active) { + var coords = tile.coords; + if (!this._retainParent(coords.x, coords.y, coords.z, coords.z - 5)) { + this._retainChildren(coords.x, coords.y, coords.z, coords.z + 2); + } + } + } + + for (key in this._tiles) { + if (!this._tiles[key].retain) { + this._removeTile(key); + } + } + }, + + _removeTilesAtZoom: function (zoom) { + for (var key in this._tiles) { + if (this._tiles[key].coords.z !== zoom) { + continue; + } + this._removeTile(key); + } + }, + + _removeAllTiles: function () { + for (var key in this._tiles) { + this._removeTile(key); + } + }, + + _invalidateAll: function () { + for (var z in this._levels) { + remove(this._levels[z].el); + this._onRemoveLevel(z); + delete this._levels[z]; + } + this._removeAllTiles(); + + this._tileZoom = undefined; + }, + + _retainParent: function (x, y, z, minZoom) { + var x2 = Math.floor(x / 2), + y2 = Math.floor(y / 2), + z2 = z - 1, + coords2 = new Point(+x2, +y2); + coords2.z = +z2; + + var key = this._tileCoordsToKey(coords2), + tile = this._tiles[key]; + + if (tile && tile.active) { + tile.retain = true; + return true; + + } else if (tile && tile.loaded) { + tile.retain = true; + } + + if (z2 > minZoom) { + return this._retainParent(x2, y2, z2, minZoom); + } + + return false; + }, + + _retainChildren: function (x, y, z, maxZoom) { + + for (var i = 2 * x; i < 2 * x + 2; i++) { + for (var j = 2 * y; j < 2 * y + 2; j++) { + + var coords = new Point(i, j); + coords.z = z + 1; + + var key = this._tileCoordsToKey(coords), + tile = this._tiles[key]; + + if (tile && tile.active) { + tile.retain = true; + continue; + + } else if (tile && tile.loaded) { + tile.retain = true; + } + + if (z + 1 < maxZoom) { + this._retainChildren(i, j, z + 1, maxZoom); + } + } + } + }, + + _resetView: function (e) { + var animating = e && (e.pinch || e.flyTo); + this._setView(this._map.getCenter(), this._map.getZoom(), animating, animating); + }, + + _animateZoom: function (e) { + this._setView(e.center, e.zoom, true, e.noUpdate); + }, + + _clampZoom: function (zoom) { + var options = this.options; + + if (undefined !== options.minNativeZoom && zoom < options.minNativeZoom) { + return options.minNativeZoom; + } + + if (undefined !== options.maxNativeZoom && options.maxNativeZoom < zoom) { + return options.maxNativeZoom; + } + + return zoom; + }, + + _setView: function (center, zoom, noPrune, noUpdate) { + var tileZoom = this._clampZoom(Math.round(zoom)); + if ((this.options.maxZoom !== undefined && tileZoom > this.options.maxZoom) || + (this.options.minZoom !== undefined && tileZoom < this.options.minZoom)) { + tileZoom = undefined; + } + + var tileZoomChanged = this.options.updateWhenZooming && (tileZoom !== this._tileZoom); + + if (!noUpdate || tileZoomChanged) { + + this._tileZoom = tileZoom; + + if (this._abortLoading) { + this._abortLoading(); + } + + this._updateLevels(); + this._resetGrid(); + + if (tileZoom !== undefined) { + this._update(center); + } + + if (!noPrune) { + this._pruneTiles(); + } + + // Flag to prevent _updateOpacity from pruning tiles during + // a zoom anim or a pinch gesture + this._noPrune = !!noPrune; + } + + this._setZoomTransforms(center, zoom); + }, + + _setZoomTransforms: function (center, zoom) { + for (var i in this._levels) { + this._setZoomTransform(this._levels[i], center, zoom); + } + }, + + _setZoomTransform: function (level, center, zoom) { + var scale = this._map.getZoomScale(zoom, level.zoom), + translate = level.origin.multiplyBy(scale) + .subtract(this._map._getNewPixelOrigin(center, zoom)).round(); + + if (any3d) { + setTransform(level.el, translate, scale); + } else { + setPosition(level.el, translate); + } + }, + + _resetGrid: function () { + var map = this._map, + crs = map.options.crs, + tileSize = this._tileSize = this.getTileSize(), + tileZoom = this._tileZoom; + + var bounds = this._map.getPixelWorldBounds(this._tileZoom); + if (bounds) { + this._globalTileRange = this._pxBoundsToTileRange(bounds); + } + + this._wrapX = crs.wrapLng && !this.options.noWrap && [ + Math.floor(map.project([0, crs.wrapLng[0]], tileZoom).x / tileSize.x), + Math.ceil(map.project([0, crs.wrapLng[1]], tileZoom).x / tileSize.y) + ]; + this._wrapY = crs.wrapLat && !this.options.noWrap && [ + Math.floor(map.project([crs.wrapLat[0], 0], tileZoom).y / tileSize.x), + Math.ceil(map.project([crs.wrapLat[1], 0], tileZoom).y / tileSize.y) + ]; + }, + + _onMoveEnd: function () { + if (!this._map || this._map._animatingZoom) { return; } + + this._update(); + }, + + _getTiledPixelBounds: function (center) { + var map = this._map, + mapZoom = map._animatingZoom ? Math.max(map._animateToZoom, map.getZoom()) : map.getZoom(), + scale = map.getZoomScale(mapZoom, this._tileZoom), + pixelCenter = map.project(center, this._tileZoom).floor(), + halfSize = map.getSize().divideBy(scale * 2); + + return new Bounds(pixelCenter.subtract(halfSize), pixelCenter.add(halfSize)); + }, + + // Private method to load tiles in the grid's active zoom level according to map bounds + _update: function (center) { + var map = this._map; + if (!map) { return; } + var zoom = this._clampZoom(map.getZoom()); + + if (center === undefined) { center = map.getCenter(); } + if (this._tileZoom === undefined) { return; } // if out of minzoom/maxzoom + + var pixelBounds = this._getTiledPixelBounds(center), + tileRange = this._pxBoundsToTileRange(pixelBounds), + tileCenter = tileRange.getCenter(), + queue = [], + margin = this.options.keepBuffer, + noPruneRange = new Bounds(tileRange.getBottomLeft().subtract([margin, -margin]), + tileRange.getTopRight().add([margin, -margin])); + + // Sanity check: panic if the tile range contains Infinity somewhere. + if (!(isFinite(tileRange.min.x) && + isFinite(tileRange.min.y) && + isFinite(tileRange.max.x) && + isFinite(tileRange.max.y))) { throw new Error('Attempted to load an infinite number of tiles'); } + + for (var key in this._tiles) { + var c = this._tiles[key].coords; + if (c.z !== this._tileZoom || !noPruneRange.contains(new Point(c.x, c.y))) { + this._tiles[key].current = false; + } + } + + // _update just loads more tiles. If the tile zoom level differs too much + // from the map's, let _setView reset levels and prune old tiles. + if (Math.abs(zoom - this._tileZoom) > 1) { this._setView(center, zoom); return; } + + // create a queue of coordinates to load tiles from + for (var j = tileRange.min.y; j <= tileRange.max.y; j++) { + for (var i = tileRange.min.x; i <= tileRange.max.x; i++) { + var coords = new Point(i, j); + coords.z = this._tileZoom; + + if (!this._isValidTile(coords)) { continue; } + + var tile = this._tiles[this._tileCoordsToKey(coords)]; + if (tile) { + tile.current = true; + } else { + queue.push(coords); + } + } + } + + // sort tile queue to load tiles in order of their distance to center + queue.sort(function (a, b) { + return a.distanceTo(tileCenter) - b.distanceTo(tileCenter); + }); + + if (queue.length !== 0) { + // if it's the first batch of tiles to load + if (!this._loading) { + this._loading = true; + // @event loading: Event + // Fired when the grid layer starts loading tiles. + this.fire('loading'); + } + + // create DOM fragment to append tiles in one batch + var fragment = document.createDocumentFragment(); + + for (i = 0; i < queue.length; i++) { + this._addTile(queue[i], fragment); + } + + this._level.el.appendChild(fragment); + } + }, + + _isValidTile: function (coords) { + var crs = this._map.options.crs; + + if (!crs.infinite) { + // don't load tile if it's out of bounds and not wrapped + var bounds = this._globalTileRange; + if ((!crs.wrapLng && (coords.x < bounds.min.x || coords.x > bounds.max.x)) || + (!crs.wrapLat && (coords.y < bounds.min.y || coords.y > bounds.max.y))) { return false; } + } + + if (!this.options.bounds) { return true; } + + // don't load tile if it doesn't intersect the bounds in options + var tileBounds = this._tileCoordsToBounds(coords); + return toLatLngBounds(this.options.bounds).overlaps(tileBounds); + }, + + _keyToBounds: function (key) { + return this._tileCoordsToBounds(this._keyToTileCoords(key)); + }, + + _tileCoordsToNwSe: function (coords) { + var map = this._map, + tileSize = this.getTileSize(), + nwPoint = coords.scaleBy(tileSize), + sePoint = nwPoint.add(tileSize), + nw = map.unproject(nwPoint, coords.z), + se = map.unproject(sePoint, coords.z); + return [nw, se]; + }, + + // converts tile coordinates to its geographical bounds + _tileCoordsToBounds: function (coords) { + var bp = this._tileCoordsToNwSe(coords), + bounds = new LatLngBounds(bp[0], bp[1]); + + if (!this.options.noWrap) { + bounds = this._map.wrapLatLngBounds(bounds); + } + return bounds; + }, + // converts tile coordinates to key for the tile cache + _tileCoordsToKey: function (coords) { + return coords.x + ':' + coords.y + ':' + coords.z; + }, + + // converts tile cache key to coordinates + _keyToTileCoords: function (key) { + var k = key.split(':'), + coords = new Point(+k[0], +k[1]); + coords.z = +k[2]; + return coords; + }, + + _removeTile: function (key) { + var tile = this._tiles[key]; + if (!tile) { return; } + + remove(tile.el); + + delete this._tiles[key]; + + // @event tileunload: TileEvent + // Fired when a tile is removed (e.g. when a tile goes off the screen). + this.fire('tileunload', { + tile: tile.el, + coords: this._keyToTileCoords(key) + }); + }, + + _initTile: function (tile) { + addClass(tile, 'leaflet-tile'); + + var tileSize = this.getTileSize(); + tile.style.width = tileSize.x + 'px'; + tile.style.height = tileSize.y + 'px'; + + tile.onselectstart = falseFn; + tile.onmousemove = falseFn; + + // update opacity on tiles in IE7-8 because of filter inheritance problems + if (ielt9 && this.options.opacity < 1) { + setOpacity(tile, this.options.opacity); + } + + // without this hack, tiles disappear after zoom on Chrome for Android + // https://github.com/Leaflet/Leaflet/issues/2078 + if (android && !android23) { + tile.style.WebkitBackfaceVisibility = 'hidden'; + } + }, + + _addTile: function (coords, container) { + var tilePos = this._getTilePos(coords), + key = this._tileCoordsToKey(coords); + + var tile = this.createTile(this._wrapCoords(coords), bind(this._tileReady, this, coords)); + + this._initTile(tile); + + // if createTile is defined with a second argument ("done" callback), + // we know that tile is async and will be ready later; otherwise + if (this.createTile.length < 2) { + // mark tile as ready, but delay one frame for opacity animation to happen + requestAnimFrame(bind(this._tileReady, this, coords, null, tile)); + } + + setPosition(tile, tilePos); + + // save tile in cache + this._tiles[key] = { + el: tile, + coords: coords, + current: true + }; + + container.appendChild(tile); + // @event tileloadstart: TileEvent + // Fired when a tile is requested and starts loading. + this.fire('tileloadstart', { + tile: tile, + coords: coords + }); + }, + + _tileReady: function (coords, err, tile) { + if (err) { + // @event tileerror: TileErrorEvent + // Fired when there is an error loading a tile. + this.fire('tileerror', { + error: err, + tile: tile, + coords: coords + }); + } + + var key = this._tileCoordsToKey(coords); + + tile = this._tiles[key]; + if (!tile) { return; } + + tile.loaded = +new Date(); + if (this._map._fadeAnimated) { + setOpacity(tile.el, 0); + cancelAnimFrame(this._fadeFrame); + this._fadeFrame = requestAnimFrame(this._updateOpacity, this); + } else { + tile.active = true; + this._pruneTiles(); + } + + if (!err) { + addClass(tile.el, 'leaflet-tile-loaded'); + + // @event tileload: TileEvent + // Fired when a tile loads. + this.fire('tileload', { + tile: tile.el, + coords: coords + }); + } + + if (this._noTilesToLoad()) { + this._loading = false; + // @event load: Event + // Fired when the grid layer loaded all visible tiles. + this.fire('load'); + + if (ielt9 || !this._map._fadeAnimated) { + requestAnimFrame(this._pruneTiles, this); + } else { + // Wait a bit more than 0.2 secs (the duration of the tile fade-in) + // to trigger a pruning. + setTimeout(bind(this._pruneTiles, this), 250); + } + } + }, + + _getTilePos: function (coords) { + return coords.scaleBy(this.getTileSize()).subtract(this._level.origin); + }, + + _wrapCoords: function (coords) { + var newCoords = new Point( + this._wrapX ? wrapNum(coords.x, this._wrapX) : coords.x, + this._wrapY ? wrapNum(coords.y, this._wrapY) : coords.y); + newCoords.z = coords.z; + return newCoords; + }, + + _pxBoundsToTileRange: function (bounds) { + var tileSize = this.getTileSize(); + return new Bounds( + bounds.min.unscaleBy(tileSize).floor(), + bounds.max.unscaleBy(tileSize).ceil().subtract([1, 1])); + }, + + _noTilesToLoad: function () { + for (var key in this._tiles) { + if (!this._tiles[key].loaded) { return false; } + } + return true; + } +}); + +// @factory L.gridLayer(options?: GridLayer options) +// Creates a new instance of GridLayer with the supplied options. +function gridLayer(options) { + return new GridLayer(options); +} + +/* + * @class TileLayer + * @inherits GridLayer + * @aka L.TileLayer + * Used to load and display tile layers on the map. Note that most tile servers require attribution, which you can set under `Layer`. Extends `GridLayer`. + * + * @example + * + * ```js + * L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?{foo}', {foo: 'bar', attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA'}).addTo(map); + * ``` + * + * @section URL template + * @example + * + * A string of the following form: + * + * ``` + * 'http://{s}.somedomain.com/blabla/{z}/{x}/{y}{r}.png' + * ``` + * + * `{s}` means one of the available subdomains (used sequentially to help with browser parallel requests per domain limitation; subdomain values are specified in options; `a`, `b` or `c` by default, can be omitted), `{z}` — zoom level, `{x}` and `{y}` — tile coordinates. `{r}` can be used to add "@2x" to the URL to load retina tiles. + * + * You can use custom keys in the template, which will be [evaluated](#util-template) from TileLayer options, like this: + * + * ``` + * L.tileLayer('http://{s}.somedomain.com/{foo}/{z}/{x}/{y}.png', {foo: 'bar'}); + * ``` + */ + + +var TileLayer = GridLayer.extend({ + + // @section + // @aka TileLayer options + options: { + // @option minZoom: Number = 0 + // The minimum zoom level down to which this layer will be displayed (inclusive). + minZoom: 0, + + // @option maxZoom: Number = 18 + // The maximum zoom level up to which this layer will be displayed (inclusive). + maxZoom: 18, + + // @option subdomains: String|String[] = 'abc' + // Subdomains of the tile service. Can be passed in the form of one string (where each letter is a subdomain name) or an array of strings. + subdomains: 'abc', + + // @option errorTileUrl: String = '' + // URL to the tile image to show in place of the tile that failed to load. + errorTileUrl: '', + + // @option zoomOffset: Number = 0 + // The zoom number used in tile URLs will be offset with this value. + zoomOffset: 0, + + // @option tms: Boolean = false + // If `true`, inverses Y axis numbering for tiles (turn this on for [TMS](https://en.wikipedia.org/wiki/Tile_Map_Service) services). + tms: false, + + // @option zoomReverse: Boolean = false + // If set to true, the zoom number used in tile URLs will be reversed (`maxZoom - zoom` instead of `zoom`) + zoomReverse: false, + + // @option detectRetina: Boolean = false + // If `true` and user is on a retina display, it will request four tiles of half the specified size and a bigger zoom level in place of one to utilize the high resolution. + detectRetina: false, + + // @option crossOrigin: Boolean|String = false + // Whether the crossOrigin attribute will be added to the tiles. + // If a String is provided, all tiles will have their crossOrigin attribute set to the String provided. This is needed if you want to access tile pixel data. + // Refer to [CORS Settings](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) for valid String values. + crossOrigin: false + }, + + initialize: function (url, options) { + + this._url = url; + + options = setOptions(this, options); + + // detecting retina displays, adjusting tileSize and zoom levels + if (options.detectRetina && retina && options.maxZoom > 0) { + + options.tileSize = Math.floor(options.tileSize / 2); + + if (!options.zoomReverse) { + options.zoomOffset++; + options.maxZoom--; + } else { + options.zoomOffset--; + options.minZoom++; + } + + options.minZoom = Math.max(0, options.minZoom); + } + + if (typeof options.subdomains === 'string') { + options.subdomains = options.subdomains.split(''); + } + + // for https://github.com/Leaflet/Leaflet/issues/137 + if (!android) { + this.on('tileunload', this._onTileRemove); + } + }, + + // @method setUrl(url: String, noRedraw?: Boolean): this + // Updates the layer's URL template and redraws it (unless `noRedraw` is set to `true`). + // If the URL does not change, the layer will not be redrawn unless + // the noRedraw parameter is set to false. + setUrl: function (url, noRedraw) { + if (this._url === url && noRedraw === undefined) { + noRedraw = true; + } + + this._url = url; + + if (!noRedraw) { + this.redraw(); + } + return this; + }, + + // @method createTile(coords: Object, done?: Function): HTMLElement + // Called only internally, overrides GridLayer's [`createTile()`](#gridlayer-createtile) + // to return an `` HTML element with the appropriate image URL given `coords`. The `done` + // callback is called when the tile has been loaded. + createTile: function (coords, done) { + var tile = document.createElement('img'); + + on(tile, 'load', bind(this._tileOnLoad, this, done, tile)); + on(tile, 'error', bind(this._tileOnError, this, done, tile)); + + if (this.options.crossOrigin || this.options.crossOrigin === '') { + tile.crossOrigin = this.options.crossOrigin === true ? '' : this.options.crossOrigin; + } + + /* + Alt tag is set to empty string to keep screen readers from reading URL and for compliance reasons + http://www.w3.org/TR/WCAG20-TECHS/H67 + */ + tile.alt = ''; + + /* + Set role="presentation" to force screen readers to ignore this + https://www.w3.org/TR/wai-aria/roles#textalternativecomputation + */ + tile.setAttribute('role', 'presentation'); + + tile.src = this.getTileUrl(coords); + + return tile; + }, + + // @section Extension methods + // @uninheritable + // Layers extending `TileLayer` might reimplement the following method. + // @method getTileUrl(coords: Object): String + // Called only internally, returns the URL for a tile given its coordinates. + // Classes extending `TileLayer` can override this function to provide custom tile URL naming schemes. + getTileUrl: function (coords) { + var data = { + r: retina ? '@2x' : '', + s: this._getSubdomain(coords), + x: coords.x, + y: coords.y, + z: this._getZoomForUrl() + }; + if (this._map && !this._map.options.crs.infinite) { + var invertedY = this._globalTileRange.max.y - coords.y; + if (this.options.tms) { + data['y'] = invertedY; + } + data['-y'] = invertedY; + } + + return template(this._url, extend(data, this.options)); + }, + + _tileOnLoad: function (done, tile) { + // For https://github.com/Leaflet/Leaflet/issues/3332 + if (ielt9) { + setTimeout(bind(done, this, null, tile), 0); + } else { + done(null, tile); + } + }, + + _tileOnError: function (done, tile, e) { + var errorUrl = this.options.errorTileUrl; + if (errorUrl && tile.getAttribute('src') !== errorUrl) { + tile.src = errorUrl; + } + done(e, tile); + }, + + _onTileRemove: function (e) { + e.tile.onload = null; + }, + + _getZoomForUrl: function () { + var zoom = this._tileZoom, + maxZoom = this.options.maxZoom, + zoomReverse = this.options.zoomReverse, + zoomOffset = this.options.zoomOffset; + + if (zoomReverse) { + zoom = maxZoom - zoom; + } + + return zoom + zoomOffset; + }, + + _getSubdomain: function (tilePoint) { + var index = Math.abs(tilePoint.x + tilePoint.y) % this.options.subdomains.length; + return this.options.subdomains[index]; + }, + + // stops loading all tiles in the background layer + _abortLoading: function () { + var i, tile; + for (i in this._tiles) { + if (this._tiles[i].coords.z !== this._tileZoom) { + tile = this._tiles[i].el; + + tile.onload = falseFn; + tile.onerror = falseFn; + + if (!tile.complete) { + tile.src = emptyImageUrl; + remove(tile); + delete this._tiles[i]; + } + } + } + }, + + _removeTile: function (key) { + var tile = this._tiles[key]; + if (!tile) { return; } + + // Cancels any pending http requests associated with the tile + // unless we're on Android's stock browser, + // see https://github.com/Leaflet/Leaflet/issues/137 + if (!androidStock) { + tile.el.setAttribute('src', emptyImageUrl); + } + + return GridLayer.prototype._removeTile.call(this, key); + }, + + _tileReady: function (coords, err, tile) { + if (!this._map || (tile && tile.getAttribute('src') === emptyImageUrl)) { + return; + } + + return GridLayer.prototype._tileReady.call(this, coords, err, tile); + } +}); + + +// @factory L.tilelayer(urlTemplate: String, options?: TileLayer options) +// Instantiates a tile layer object given a `URL template` and optionally an options object. + +function tileLayer(url, options) { + return new TileLayer(url, options); +} + +/* + * @class TileLayer.WMS + * @inherits TileLayer + * @aka L.TileLayer.WMS + * Used to display [WMS](https://en.wikipedia.org/wiki/Web_Map_Service) services as tile layers on the map. Extends `TileLayer`. + * + * @example + * + * ```js + * var nexrad = L.tileLayer.wms("http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi", { + * layers: 'nexrad-n0r-900913', + * format: 'image/png', + * transparent: true, + * attribution: "Weather data © 2012 IEM Nexrad" + * }); + * ``` + */ + +var TileLayerWMS = TileLayer.extend({ + + // @section + // @aka TileLayer.WMS options + // If any custom options not documented here are used, they will be sent to the + // WMS server as extra parameters in each request URL. This can be useful for + // [non-standard vendor WMS parameters](http://docs.geoserver.org/stable/en/user/services/wms/vendor.html). + defaultWmsParams: { + service: 'WMS', + request: 'GetMap', + + // @option layers: String = '' + // **(required)** Comma-separated list of WMS layers to show. + layers: '', + + // @option styles: String = '' + // Comma-separated list of WMS styles. + styles: '', + + // @option format: String = 'image/jpeg' + // WMS image format (use `'image/png'` for layers with transparency). + format: 'image/jpeg', + + // @option transparent: Boolean = false + // If `true`, the WMS service will return images with transparency. + transparent: false, + + // @option version: String = '1.1.1' + // Version of the WMS service to use + version: '1.1.1' + }, + + options: { + // @option crs: CRS = null + // Coordinate Reference System to use for the WMS requests, defaults to + // map CRS. Don't change this if you're not sure what it means. + crs: null, + + // @option uppercase: Boolean = false + // If `true`, WMS request parameter keys will be uppercase. + uppercase: false + }, + + initialize: function (url, options) { + + this._url = url; + + var wmsParams = extend({}, this.defaultWmsParams); + + // all keys that are not TileLayer options go to WMS params + for (var i in options) { + if (!(i in this.options)) { + wmsParams[i] = options[i]; + } + } + + options = setOptions(this, options); + + var realRetina = options.detectRetina && retina ? 2 : 1; + var tileSize = this.getTileSize(); + wmsParams.width = tileSize.x * realRetina; + wmsParams.height = tileSize.y * realRetina; + + this.wmsParams = wmsParams; + }, + + onAdd: function (map) { + + this._crs = this.options.crs || map.options.crs; + this._wmsVersion = parseFloat(this.wmsParams.version); + + var projectionKey = this._wmsVersion >= 1.3 ? 'crs' : 'srs'; + this.wmsParams[projectionKey] = this._crs.code; + + TileLayer.prototype.onAdd.call(this, map); + }, + + getTileUrl: function (coords) { + + var tileBounds = this._tileCoordsToNwSe(coords), + crs = this._crs, + bounds = toBounds(crs.project(tileBounds[0]), crs.project(tileBounds[1])), + min = bounds.min, + max = bounds.max, + bbox = (this._wmsVersion >= 1.3 && this._crs === EPSG4326 ? + [min.y, min.x, max.y, max.x] : + [min.x, min.y, max.x, max.y]).join(','), + url = TileLayer.prototype.getTileUrl.call(this, coords); + return url + + getParamString(this.wmsParams, url, this.options.uppercase) + + (this.options.uppercase ? '&BBOX=' : '&bbox=') + bbox; + }, + + // @method setParams(params: Object, noRedraw?: Boolean): this + // Merges an object with the new parameters and re-requests tiles on the current screen (unless `noRedraw` was set to true). + setParams: function (params, noRedraw) { + + extend(this.wmsParams, params); + + if (!noRedraw) { + this.redraw(); + } + + return this; + } +}); + + +// @factory L.tileLayer.wms(baseUrl: String, options: TileLayer.WMS options) +// Instantiates a WMS tile layer object given a base URL of the WMS service and a WMS parameters/options object. +function tileLayerWMS(url, options) { + return new TileLayerWMS(url, options); +} + +TileLayer.WMS = TileLayerWMS; +tileLayer.wms = tileLayerWMS; + +/* + * @class Renderer + * @inherits Layer + * @aka L.Renderer + * + * Base class for vector renderer implementations (`SVG`, `Canvas`). Handles the + * DOM container of the renderer, its bounds, and its zoom animation. + * + * A `Renderer` works as an implicit layer group for all `Path`s - the renderer + * itself can be added or removed to the map. All paths use a renderer, which can + * be implicit (the map will decide the type of renderer and use it automatically) + * or explicit (using the [`renderer`](#path-renderer) option of the path). + * + * Do not use this class directly, use `SVG` and `Canvas` instead. + * + * @event update: Event + * Fired when the renderer updates its bounds, center and zoom, for example when + * its map has moved + */ + +var Renderer = Layer.extend({ + + // @section + // @aka Renderer options + options: { + // @option padding: Number = 0.1 + // How much to extend the clip area around the map view (relative to its size) + // e.g. 0.1 would be 10% of map view in each direction + padding: 0.1, + + // @option tolerance: Number = 0 + // How much to extend click tolerance round a path/object on the map + tolerance : 0 + }, + + initialize: function (options) { + setOptions(this, options); + stamp(this); + this._layers = this._layers || {}; + }, + + onAdd: function () { + if (!this._container) { + this._initContainer(); // defined by renderer implementations + + if (this._zoomAnimated) { + addClass(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 events = { + viewreset: this._reset, + zoom: this._onZoom, + moveend: this._update, + zoomend: this._onZoomEnd + }; + if (this._zoomAnimated) { + events.zoomanim = this._onAnimZoom; + } + return events; + }, + + _onAnimZoom: function (ev) { + this._updateTransform(ev.center, ev.zoom); + }, + + _onZoom: function () { + this._updateTransform(this._map.getCenter(), this._map.getZoom()); + }, + + _updateTransform: function (center, zoom) { + var scale = this._map.getZoomScale(zoom, this._zoom), + position = getPosition(this._container), + viewHalf = this._map.getSize().multiplyBy(0.5 + this.options.padding), + currentCenterPoint = this._map.project(this._center, zoom), + destCenterPoint = this._map.project(center, zoom), + centerOffset = destCenterPoint.subtract(currentCenterPoint), + + topLeftOffset = viewHalf.multiplyBy(-scale).add(position).add(viewHalf).subtract(centerOffset); + + if (any3d) { + setTransform(this._container, topLeftOffset, scale); + } else { + setPosition(this._container, topLeftOffset); + } + }, + + _reset: function () { + this._update(); + this._updateTransform(this._center, this._zoom); + + for (var id in this._layers) { + this._layers[id]._reset(); + } + }, + + _onZoomEnd: function () { + for (var id in this._layers) { + this._layers[id]._project(); + } + }, + + _updatePaths: function () { + for (var id in this._layers) { + this._layers[id]._update(); + } + }, + + _update: function () { + // Update pixel bounds of renderer container (for positioning/sizing/clipping later) + // Subclasses are responsible of firing the 'update' event. + var p = this.options.padding, + size = this._map.getSize(), + min = this._map.containerPointToLayerPoint(size.multiplyBy(-p)).round(); + + this._bounds = new Bounds(min, min.add(size.multiplyBy(1 + p * 2)).round()); + + this._center = this._map.getCenter(); + this._zoom = this._map.getZoom(); + } +}); + +/* + * @class Canvas + * @inherits Renderer + * @aka L.Canvas + * + * Allows vector layers to be displayed with [``](https://developer.mozilla.org/docs/Web/API/Canvas_API). + * Inherits `Renderer`. + * + * Due to [technical limitations](http://caniuse.com/#search=canvas), Canvas is not + * available in all web browsers, notably IE8, and overlapping geometries might + * not display properly in some edge cases. + * + * @example + * + * Use Canvas by default for all paths in the map: + * + * ```js + * var map = L.map('map', { + * renderer: L.canvas() + * }); + * ``` + * + * Use a Canvas renderer with extra padding for specific vector geometries: + * + * ```js + * var map = L.map('map'); + * var myRenderer = L.canvas({ padding: 0.5 }); + * var line = L.polyline( coordinates, { renderer: myRenderer } ); + * var circle = L.circle( center, { renderer: myRenderer } ); + * ``` + */ + +var Canvas = Renderer.extend({ + getEvents: function () { + var events = Renderer.prototype.getEvents.call(this); + events.viewprereset = this._onViewPreReset; + return events; + }, + + _onViewPreReset: function () { + // Set a flag so that a viewprereset+moveend+viewreset only updates&redraws once + this._postponeUpdatePaths = true; + }, + + onAdd: function () { + Renderer.prototype.onAdd.call(this); + + // Redraw vectors since canvas is cleared upon removal, + // in case of removing the renderer itself from the map. + this._draw(); + }, + + _initContainer: function () { + var container = this._container = document.createElement('canvas'); + + on(container, 'mousemove', this._onMouseMove, this); + on(container, 'click dblclick mousedown mouseup contextmenu', this._onClick, this); + on(container, 'mouseout', this._handleMouseOut, this); + + this._ctx = container.getContext('2d'); + }, + + _destroyContainer: function () { + cancelAnimFrame(this._redrawRequest); + delete this._ctx; + remove(this._container); + off(this._container); + delete this._container; + }, + + _updatePaths: function () { + if (this._postponeUpdatePaths) { return; } + + var layer; + this._redrawBounds = null; + for (var id in this._layers) { + layer = this._layers[id]; + layer._update(); + } + this._redraw(); + }, + + _update: function () { + if (this._map._animatingZoom && this._bounds) { return; } + + Renderer.prototype._update.call(this); + + var b = this._bounds, + container = this._container, + size = b.getSize(), + m = retina ? 2 : 1; + + setPosition(container, b.min); + + // set canvas size (also clearing it); use double size on retina + container.width = m * size.x; + container.height = m * size.y; + container.style.width = size.x + 'px'; + container.style.height = size.y + 'px'; + + if (retina) { + this._ctx.scale(2, 2); + } + + // translate so we use the same path coordinates after canvas element moves + this._ctx.translate(-b.min.x, -b.min.y); + + // Tell paths to redraw themselves + this.fire('update'); + }, + + _reset: function () { + Renderer.prototype._reset.call(this); + + if (this._postponeUpdatePaths) { + this._postponeUpdatePaths = false; + this._updatePaths(); + } + }, + + _initPath: function (layer) { + this._updateDashArray(layer); + this._layers[stamp(layer)] = layer; + + var order = layer._order = { + layer: layer, + prev: this._drawLast, + next: null + }; + if (this._drawLast) { this._drawLast.next = order; } + this._drawLast = order; + this._drawFirst = this._drawFirst || this._drawLast; + }, + + _addPath: function (layer) { + this._requestRedraw(layer); + }, + + _removePath: function (layer) { + var order = layer._order; + var next = order.next; + var prev = order.prev; + + if (next) { + next.prev = prev; + } else { + this._drawLast = prev; + } + if (prev) { + prev.next = next; + } else { + this._drawFirst = next; + } + + delete layer._order; + + delete this._layers[stamp(layer)]; + + this._requestRedraw(layer); + }, + + _updatePath: function (layer) { + // Redraw the union of the layer's old pixel + // bounds and the new pixel bounds. + this._extendRedrawBounds(layer); + layer._project(); + layer._update(); + // The redraw will extend the redraw bounds + // with the new pixel bounds. + this._requestRedraw(layer); + }, + + _updateStyle: function (layer) { + this._updateDashArray(layer); + this._requestRedraw(layer); + }, + + _updateDashArray: function (layer) { + if (typeof layer.options.dashArray === 'string') { + var parts = layer.options.dashArray.split(/[, ]+/), + dashArray = [], + dashValue, + i; + for (i = 0; i < parts.length; i++) { + dashValue = Number(parts[i]); + // Ignore dash array containing invalid lengths + if (isNaN(dashValue)) { return; } + dashArray.push(dashValue); + } + layer.options._dashArray = dashArray; + } else { + layer.options._dashArray = layer.options.dashArray; + } + }, + + _requestRedraw: function (layer) { + if (!this._map) { return; } + + this._extendRedrawBounds(layer); + this._redrawRequest = this._redrawRequest || requestAnimFrame(this._redraw, this); + }, + + _extendRedrawBounds: function (layer) { + if (layer._pxBounds) { + var padding = (layer.options.weight || 0) + 1; + this._redrawBounds = this._redrawBounds || new Bounds(); + this._redrawBounds.extend(layer._pxBounds.min.subtract([padding, padding])); + this._redrawBounds.extend(layer._pxBounds.max.add([padding, padding])); + } + }, + + _redraw: function () { + this._redrawRequest = null; + + if (this._redrawBounds) { + this._redrawBounds.min._floor(); + this._redrawBounds.max._ceil(); + } + + this._clear(); // clear layers in redraw bounds + this._draw(); // draw layers + + this._redrawBounds = null; + }, + + _clear: function () { + var bounds = this._redrawBounds; + if (bounds) { + var size = bounds.getSize(); + this._ctx.clearRect(bounds.min.x, bounds.min.y, size.x, size.y); + } else { + this._ctx.clearRect(0, 0, this._container.width, this._container.height); + } + }, + + _draw: function () { + var layer, bounds = this._redrawBounds; + this._ctx.save(); + if (bounds) { + var size = bounds.getSize(); + this._ctx.beginPath(); + this._ctx.rect(bounds.min.x, bounds.min.y, size.x, size.y); + this._ctx.clip(); + } + + this._drawing = true; + + for (var order = this._drawFirst; order; order = order.next) { + layer = order.layer; + if (!bounds || (layer._pxBounds && layer._pxBounds.intersects(bounds))) { + layer._updatePath(); + } + } + + this._drawing = false; + + this._ctx.restore(); // Restore state before clipping. + }, + + _updatePoly: function (layer, closed) { + if (!this._drawing) { return; } + + var i, j, len2, p, + parts = layer._parts, + len = parts.length, + ctx = this._ctx; + + if (!len) { return; } + + ctx.beginPath(); + + for (i = 0; i < len; i++) { + for (j = 0, len2 = parts[i].length; j < len2; j++) { + p = parts[i][j]; + ctx[j ? 'lineTo' : 'moveTo'](p.x, p.y); + } + if (closed) { + ctx.closePath(); + } + } + + this._fillStroke(ctx, layer); + + // TODO optimization: 1 fill/stroke for all features with equal style instead of 1 for each feature + }, + + _updateCircle: function (layer) { + + if (!this._drawing || layer._empty()) { return; } + + var p = layer._point, + ctx = this._ctx, + r = Math.max(Math.round(layer._radius), 1), + s = (Math.max(Math.round(layer._radiusY), 1) || r) / r; + + if (s !== 1) { + ctx.save(); + ctx.scale(1, s); + } + + ctx.beginPath(); + ctx.arc(p.x, p.y / s, r, 0, Math.PI * 2, false); + + if (s !== 1) { + ctx.restore(); + } + + this._fillStroke(ctx, layer); + }, + + _fillStroke: function (ctx, layer) { + var options = layer.options; + + if (options.fill) { + ctx.globalAlpha = options.fillOpacity; + ctx.fillStyle = options.fillColor || options.color; + ctx.fill(options.fillRule || 'evenodd'); + } + + if (options.stroke && options.weight !== 0) { + if (ctx.setLineDash) { + ctx.setLineDash(layer.options && layer.options._dashArray || []); + } + ctx.globalAlpha = options.opacity; + ctx.lineWidth = options.weight; + ctx.strokeStyle = options.color; + ctx.lineCap = options.lineCap; + ctx.lineJoin = options.lineJoin; + ctx.stroke(); + } + }, + + // Canvas obviously doesn't have mouse events for individual drawn objects, + // so we emulate that by calculating what's under the mouse on mousemove/click manually + + _onClick: function (e) { + var point = this._map.mouseEventToLayerPoint(e), layer, clickedLayer; + + for (var order = this._drawFirst; order; order = order.next) { + layer = order.layer; + if (layer.options.interactive && layer._containsPoint(point) && !this._map._draggableMoved(layer)) { + clickedLayer = layer; + } + } + if (clickedLayer) { + fakeStop(e); + this._fireEvent([clickedLayer], e); + } + }, + + _onMouseMove: function (e) { + if (!this._map || this._map.dragging.moving() || this._map._animatingZoom) { return; } + + var point = this._map.mouseEventToLayerPoint(e); + this._handleMouseHover(e, point); + }, + + + _handleMouseOut: function (e) { + var layer = this._hoveredLayer; + if (layer) { + // if we're leaving the layer, fire mouseout + removeClass(this._container, 'leaflet-interactive'); + this._fireEvent([layer], e, 'mouseout'); + this._hoveredLayer = null; + this._mouseHoverThrottled = false; + } + }, + + _handleMouseHover: function (e, point) { + if (this._mouseHoverThrottled) { + return; + } + + var layer, candidateHoveredLayer; + + for (var order = this._drawFirst; order; order = order.next) { + layer = order.layer; + if (layer.options.interactive && layer._containsPoint(point)) { + candidateHoveredLayer = layer; + } + } + + if (candidateHoveredLayer !== this._hoveredLayer) { + this._handleMouseOut(e); + + if (candidateHoveredLayer) { + addClass(this._container, 'leaflet-interactive'); // change cursor + this._fireEvent([candidateHoveredLayer], e, 'mouseover'); + this._hoveredLayer = candidateHoveredLayer; + } + } + + if (this._hoveredLayer) { + this._fireEvent([this._hoveredLayer], e); + } + + this._mouseHoverThrottled = true; + setTimeout(L.bind(function () { + this._mouseHoverThrottled = false; + }, this), 32); + }, + + _fireEvent: function (layers, e, type) { + this._map._fireDOMEvent(e, type || e.type, layers); + }, + + _bringToFront: function (layer) { + var order = layer._order; + + if (!order) { return; } + + var next = order.next; + var prev = order.prev; + + if (next) { + next.prev = prev; + } else { + // Already last + return; + } + if (prev) { + prev.next = next; + } else if (next) { + // Update first entry unless this is the + // single entry + this._drawFirst = next; + } + + order.prev = this._drawLast; + this._drawLast.next = order; + + order.next = null; + this._drawLast = order; + + this._requestRedraw(layer); + }, + + _bringToBack: function (layer) { + var order = layer._order; + + if (!order) { return; } + + var next = order.next; + var prev = order.prev; + + if (prev) { + prev.next = next; + } else { + // Already first + return; + } + if (next) { + next.prev = prev; + } else if (prev) { + // Update last entry unless this is the + // single entry + this._drawLast = prev; + } + + order.prev = null; + + order.next = this._drawFirst; + this._drawFirst.prev = order; + this._drawFirst = order; + + this._requestRedraw(layer); + } +}); + +// @factory L.canvas(options?: Renderer options) +// Creates a Canvas renderer with the given options. +function canvas$1(options) { + return canvas ? new Canvas(options) : null; +} + +/* + * Thanks to Dmitry Baranovsky and his Raphael library for inspiration! + */ + + +var vmlCreate = (function () { + try { + document.namespaces.add('lvml', 'urn:schemas-microsoft-com:vml'); + return function (name) { + return document.createElement(''); + }; + } catch (e) { + return function (name) { + return document.createElement('<' + name + ' xmlns="urn:schemas-microsoft.com:vml" class="lvml">'); + }; + } +})(); + + +/* + * @class SVG + * + * + * VML was deprecated in 2012, which means VML functionality exists only for backwards compatibility + * with old versions of Internet Explorer. + */ + +// mixin to redefine some SVG methods to handle VML syntax which is similar but with some differences +var vmlMixin = { + + _initContainer: function () { + this._container = create$1('div', 'leaflet-vml-container'); + }, + + _update: function () { + if (this._map._animatingZoom) { return; } + Renderer.prototype._update.call(this); + this.fire('update'); + }, + + _initPath: function (layer) { + var container = layer._container = vmlCreate('shape'); + + addClass(container, 'leaflet-vml-shape ' + (this.options.className || '')); + + container.coordsize = '1 1'; + + layer._path = vmlCreate('path'); + container.appendChild(layer._path); + + this._updateStyle(layer); + this._layers[stamp(layer)] = layer; + }, + + _addPath: function (layer) { + var container = layer._container; + this._container.appendChild(container); + + if (layer.options.interactive) { + layer.addInteractiveTarget(container); + } + }, + + _removePath: function (layer) { + var container = layer._container; + remove(container); + layer.removeInteractiveTarget(container); + delete this._layers[stamp(layer)]; + }, + + _updateStyle: function (layer) { + var stroke = layer._stroke, + fill = layer._fill, + options = layer.options, + container = layer._container; + + container.stroked = !!options.stroke; + container.filled = !!options.fill; + + if (options.stroke) { + if (!stroke) { + stroke = layer._stroke = vmlCreate('stroke'); + } + container.appendChild(stroke); + stroke.weight = options.weight + 'px'; + stroke.color = options.color; + stroke.opacity = options.opacity; + + if (options.dashArray) { + stroke.dashStyle = isArray(options.dashArray) ? + options.dashArray.join(' ') : + options.dashArray.replace(/( *, *)/g, ' '); + } else { + stroke.dashStyle = ''; + } + stroke.endcap = options.lineCap.replace('butt', 'flat'); + stroke.joinstyle = options.lineJoin; + + } else if (stroke) { + container.removeChild(stroke); + layer._stroke = null; + } + + if (options.fill) { + if (!fill) { + fill = layer._fill = vmlCreate('fill'); + } + container.appendChild(fill); + fill.color = options.fillColor || options.color; + fill.opacity = options.fillOpacity; + + } else if (fill) { + container.removeChild(fill); + layer._fill = null; + } + }, + + _updateCircle: function (layer) { + var p = layer._point.round(), + r = Math.round(layer._radius), + r2 = Math.round(layer._radiusY || r); + + this._setPath(layer, layer._empty() ? 'M0 0' : + 'AL ' + p.x + ',' + p.y + ' ' + r + ',' + r2 + ' 0,' + (65535 * 360)); + }, + + _setPath: function (layer, path) { + layer._path.v = path; + }, + + _bringToFront: function (layer) { + toFront(layer._container); + }, + + _bringToBack: function (layer) { + toBack(layer._container); + } +}; + +var create$2 = vml ? vmlCreate : svgCreate; + +/* + * @class SVG + * @inherits Renderer + * @aka L.SVG + * + * Allows vector layers to be displayed with [SVG](https://developer.mozilla.org/docs/Web/SVG). + * Inherits `Renderer`. + * + * Due to [technical limitations](http://caniuse.com/#search=svg), SVG is not + * available in all web browsers, notably Android 2.x and 3.x. + * + * Although SVG is not available on IE7 and IE8, these browsers support + * [VML](https://en.wikipedia.org/wiki/Vector_Markup_Language) + * (a now deprecated technology), and the SVG renderer will fall back to VML in + * this case. + * + * @example + * + * Use SVG by default for all paths in the map: + * + * ```js + * var map = L.map('map', { + * renderer: L.svg() + * }); + * ``` + * + * Use a SVG renderer with extra padding for specific vector geometries: + * + * ```js + * var map = L.map('map'); + * var myRenderer = L.svg({ padding: 0.5 }); + * var line = L.polyline( coordinates, { renderer: myRenderer } ); + * var circle = L.circle( center, { renderer: myRenderer } ); + * ``` + */ + +var SVG = Renderer.extend({ + + getEvents: function () { + var events = Renderer.prototype.getEvents.call(this); + events.zoomstart = this._onZoomStart; + return events; + }, + + _initContainer: function () { + this._container = create$2('svg'); + + // makes it possible to click through svg root; we'll reset it back in individual paths + this._container.setAttribute('pointer-events', 'none'); + + this._rootGroup = create$2('g'); + this._container.appendChild(this._rootGroup); + }, + + _destroyContainer: function () { + remove(this._container); + off(this._container); + delete this._container; + delete this._rootGroup; + delete this._svgSize; + }, + + _onZoomStart: function () { + // Drag-then-pinch interactions might mess up the center and zoom. + // In this case, the easiest way to prevent this is re-do the renderer + // bounds and padding when the zooming starts. + this._update(); + }, + + _update: function () { + if (this._map._animatingZoom && this._bounds) { return; } + + Renderer.prototype._update.call(this); + + var b = this._bounds, + size = b.getSize(), + container = this._container; + + // set size of svg-container if changed + if (!this._svgSize || !this._svgSize.equals(size)) { + this._svgSize = size; + container.setAttribute('width', size.x); + container.setAttribute('height', size.y); + } + + // movement: update container viewBox so that we don't have to change coordinates of individual layers + setPosition(container, b.min); + container.setAttribute('viewBox', [b.min.x, b.min.y, size.x, size.y].join(' ')); + + this.fire('update'); + }, + + // methods below are called by vector layers implementations + + _initPath: function (layer) { + var path = layer._path = create$2('path'); + + // @namespace Path + // @option className: String = null + // Custom class name set on an element. Only for SVG renderer. + if (layer.options.className) { + addClass(path, layer.options.className); + } + + if (layer.options.interactive) { + addClass(path, 'leaflet-interactive'); + } + + this._updateStyle(layer); + this._layers[stamp(layer)] = layer; + }, + + _addPath: function (layer) { + if (!this._rootGroup) { this._initContainer(); } + this._rootGroup.appendChild(layer._path); + layer.addInteractiveTarget(layer._path); + }, + + _removePath: function (layer) { + remove(layer._path); + layer.removeInteractiveTarget(layer._path); + delete this._layers[stamp(layer)]; + }, + + _updatePath: function (layer) { + layer._project(); + layer._update(); + }, + + _updateStyle: function (layer) { + var path = layer._path, + options = layer.options; + + if (!path) { return; } + + if (options.stroke) { + path.setAttribute('stroke', options.color); + path.setAttribute('stroke-opacity', options.opacity); + path.setAttribute('stroke-width', options.weight); + path.setAttribute('stroke-linecap', options.lineCap); + path.setAttribute('stroke-linejoin', options.lineJoin); + + if (options.dashArray) { + path.setAttribute('stroke-dasharray', options.dashArray); + } else { + path.removeAttribute('stroke-dasharray'); + } + + if (options.dashOffset) { + path.setAttribute('stroke-dashoffset', options.dashOffset); + } else { + path.removeAttribute('stroke-dashoffset'); + } + } else { + path.setAttribute('stroke', 'none'); + } + + if (options.fill) { + path.setAttribute('fill', options.fillColor || options.color); + path.setAttribute('fill-opacity', options.fillOpacity); + path.setAttribute('fill-rule', options.fillRule || 'evenodd'); + } else { + path.setAttribute('fill', 'none'); + } + }, + + _updatePoly: function (layer, closed) { + this._setPath(layer, pointsToPath(layer._parts, closed)); + }, + + _updateCircle: function (layer) { + var p = layer._point, + r = Math.max(Math.round(layer._radius), 1), + r2 = Math.max(Math.round(layer._radiusY), 1) || r, + arc = 'a' + r + ',' + r2 + ' 0 1,0 '; + + // drawing a circle with two half-arcs + var d = layer._empty() ? 'M0 0' : + 'M' + (p.x - r) + ',' + p.y + + arc + (r * 2) + ',0 ' + + arc + (-r * 2) + ',0 '; + + this._setPath(layer, d); + }, + + _setPath: function (layer, path) { + layer._path.setAttribute('d', path); + }, + + // SVG does not have the concept of zIndex so we resort to changing the DOM order of elements + _bringToFront: function (layer) { + toFront(layer._path); + }, + + _bringToBack: function (layer) { + toBack(layer._path); + } +}); + +if (vml) { + SVG.include(vmlMixin); +} + +// @namespace SVG +// @factory L.svg(options?: Renderer options) +// Creates a SVG renderer with the given options. +function svg$1(options) { + return svg || vml ? new SVG(options) : null; +} + +Map.include({ + // @namespace Map; @method getRenderer(layer: Path): Renderer + // Returns the instance of `Renderer` that should be used to render the given + // `Path`. It will ensure that the `renderer` options of the map and paths + // are respected, and that the renderers do exist on the map. + getRenderer: function (layer) { + // @namespace Path; @option renderer: Renderer + // Use this specific instance of `Renderer` for this path. Takes + // precedence over the map's [default renderer](#map-renderer). + var renderer = layer.options.renderer || this._getPaneRenderer(layer.options.pane) || this.options.renderer || this._renderer; + + if (!renderer) { + renderer = this._renderer = this._createRenderer(); + } + + if (!this.hasLayer(renderer)) { + this.addLayer(renderer); + } + return renderer; + }, + + _getPaneRenderer: function (name) { + if (name === 'overlayPane' || name === undefined) { + return false; + } + + var renderer = this._paneRenderers[name]; + if (renderer === undefined) { + renderer = this._createRenderer({pane: name}); + this._paneRenderers[name] = renderer; + } + return renderer; + }, + + _createRenderer: function (options) { + // @namespace Map; @option preferCanvas: Boolean = false + // Whether `Path`s should be rendered on a `Canvas` renderer. + // By default, all `Path`s are rendered in a `SVG` renderer. + return (this.options.preferCanvas && canvas$1(options)) || svg$1(options); + } +}); + +/* + * L.Rectangle extends Polygon and creates a rectangle when passed a LatLngBounds object. + */ + +/* + * @class Rectangle + * @aka L.Rectangle + * @inherits Polygon + * + * A class for drawing rectangle overlays on a map. Extends `Polygon`. + * + * @example + * + * ```js + * // define rectangle geographical bounds + * var bounds = [[54.559322, -5.767822], [56.1210604, -3.021240]]; + * + * // create an orange rectangle + * L.rectangle(bounds, {color: "#ff7800", weight: 1}).addTo(map); + * + * // zoom the map to the rectangle bounds + * map.fitBounds(bounds); + * ``` + * + */ + + +var Rectangle = Polygon.extend({ + initialize: function (latLngBounds, options) { + Polygon.prototype.initialize.call(this, this._boundsToLatLngs(latLngBounds), options); + }, + + // @method setBounds(latLngBounds: LatLngBounds): this + // Redraws the rectangle with the passed bounds. + setBounds: function (latLngBounds) { + return this.setLatLngs(this._boundsToLatLngs(latLngBounds)); + }, + + _boundsToLatLngs: function (latLngBounds) { + latLngBounds = toLatLngBounds(latLngBounds); + return [ + latLngBounds.getSouthWest(), + latLngBounds.getNorthWest(), + latLngBounds.getNorthEast(), + latLngBounds.getSouthEast() + ]; + } +}); + + +// @factory L.rectangle(latLngBounds: LatLngBounds, options?: Polyline options) +function rectangle(latLngBounds, options) { + return new Rectangle(latLngBounds, options); +} + +SVG.create = create$2; +SVG.pointsToPath = pointsToPath; + +GeoJSON.geometryToLayer = geometryToLayer; +GeoJSON.coordsToLatLng = coordsToLatLng; +GeoJSON.coordsToLatLngs = coordsToLatLngs; +GeoJSON.latLngToCoords = latLngToCoords; +GeoJSON.latLngsToCoords = latLngsToCoords; +GeoJSON.getFeature = getFeature; +GeoJSON.asFeature = asFeature; + +/* + * L.Handler.BoxZoom is used to add shift-drag zoom interaction to the map + * (zoom to a selected bounding box), enabled by default. + */ + +// @namespace Map +// @section Interaction Options +Map.mergeOptions({ + // @option boxZoom: Boolean = true + // Whether the map can be zoomed to a rectangular area specified by + // dragging the mouse while pressing the shift key. + boxZoom: true +}); + +var BoxZoom = Handler.extend({ + initialize: function (map) { + this._map = map; + this._container = map._container; + this._pane = map._panes.overlayPane; + this._resetStateTimeout = 0; + map.on('unload', this._destroy, this); + }, + + addHooks: function () { + on(this._container, 'mousedown', this._onMouseDown, this); + }, + + removeHooks: function () { + off(this._container, 'mousedown', this._onMouseDown, this); + }, + + moved: function () { + return this._moved; + }, + + _destroy: function () { + remove(this._pane); + delete this._pane; + }, + + _resetState: function () { + this._resetStateTimeout = 0; + this._moved = false; + }, + + _clearDeferredResetState: function () { + if (this._resetStateTimeout !== 0) { + clearTimeout(this._resetStateTimeout); + this._resetStateTimeout = 0; + } + }, + + _onMouseDown: function (e) { + if (!e.shiftKey || ((e.which !== 1) && (e.button !== 1))) { return false; } + + // Clear the deferred resetState if it hasn't executed yet, otherwise it + // will interrupt the interaction and orphan a box element in the container. + this._clearDeferredResetState(); + this._resetState(); + + disableTextSelection(); + disableImageDrag(); + + this._startPoint = this._map.mouseEventToContainerPoint(e); + + on(document, { + contextmenu: stop, + mousemove: this._onMouseMove, + mouseup: this._onMouseUp, + keydown: this._onKeyDown + }, this); + }, + + _onMouseMove: function (e) { + if (!this._moved) { + this._moved = true; + + this._box = create$1('div', 'leaflet-zoom-box', this._container); + addClass(this._container, 'leaflet-crosshair'); + + this._map.fire('boxzoomstart'); + } + + this._point = this._map.mouseEventToContainerPoint(e); + + var bounds = new Bounds(this._point, this._startPoint), + size = bounds.getSize(); + + setPosition(this._box, bounds.min); + + this._box.style.width = size.x + 'px'; + this._box.style.height = size.y + 'px'; + }, + + _finish: function () { + if (this._moved) { + remove(this._box); + removeClass(this._container, 'leaflet-crosshair'); + } + + enableTextSelection(); + enableImageDrag(); + + off(document, { + contextmenu: stop, + mousemove: this._onMouseMove, + mouseup: this._onMouseUp, + keydown: this._onKeyDown + }, this); + }, + + _onMouseUp: function (e) { + if ((e.which !== 1) && (e.button !== 1)) { return; } + + this._finish(); + + if (!this._moved) { return; } + // Postpone to next JS tick so internal click event handling + // still see it as "moved". + this._clearDeferredResetState(); + this._resetStateTimeout = setTimeout(bind(this._resetState, this), 0); + + var bounds = new LatLngBounds( + this._map.containerPointToLatLng(this._startPoint), + this._map.containerPointToLatLng(this._point)); + + this._map + .fitBounds(bounds) + .fire('boxzoomend', {boxZoomBounds: bounds}); + }, + + _onKeyDown: function (e) { + if (e.keyCode === 27) { + this._finish(); + } + } +}); + +// @section Handlers +// @property boxZoom: Handler +// Box (shift-drag with mouse) zoom handler. +Map.addInitHook('addHandler', 'boxZoom', BoxZoom); + +/* + * L.Handler.DoubleClickZoom is used to handle double-click zoom on the map, enabled by default. + */ + +// @namespace Map +// @section Interaction Options + +Map.mergeOptions({ + // @option doubleClickZoom: Boolean|String = true + // Whether the map can be zoomed in by double clicking on it and + // zoomed out by double clicking while holding shift. If passed + // `'center'`, double-click zoom will zoom to the center of the + // view regardless of where the mouse was. + doubleClickZoom: true +}); + +var DoubleClickZoom = Handler.extend({ + addHooks: function () { + this._map.on('dblclick', this._onDoubleClick, this); + }, + + removeHooks: function () { + this._map.off('dblclick', this._onDoubleClick, this); + }, + + _onDoubleClick: function (e) { + var map = this._map, + oldZoom = map.getZoom(), + delta = map.options.zoomDelta, + zoom = e.originalEvent.shiftKey ? oldZoom - delta : oldZoom + delta; + + if (map.options.doubleClickZoom === 'center') { + map.setZoom(zoom); + } else { + map.setZoomAround(e.containerPoint, zoom); + } + } +}); + +// @section Handlers +// +// Map properties include interaction handlers that allow you to control +// interaction behavior in runtime, enabling or disabling certain features such +// as dragging or touch zoom (see `Handler` methods). For example: +// +// ```js +// map.doubleClickZoom.disable(); +// ``` +// +// @property doubleClickZoom: Handler +// Double click zoom handler. +Map.addInitHook('addHandler', 'doubleClickZoom', DoubleClickZoom); + +/* + * L.Handler.MapDrag is used to make the map draggable (with panning inertia), enabled by default. + */ + +// @namespace Map +// @section Interaction Options +Map.mergeOptions({ + // @option dragging: Boolean = true + // Whether the map be draggable with mouse/touch or not. + dragging: true, + + // @section Panning Inertia Options + // @option inertia: Boolean = * + // If enabled, panning of the map will have an inertia effect where + // the map builds momentum while dragging and continues moving in + // the same direction for some time. Feels especially nice on touch + // devices. Enabled by default unless running on old Android devices. + inertia: !android23, + + // @option inertiaDeceleration: Number = 3000 + // The rate with which the inertial movement slows down, in pixels/second². + inertiaDeceleration: 3400, // px/s^2 + + // @option inertiaMaxSpeed: Number = Infinity + // Max speed of the inertial movement, in pixels/second. + inertiaMaxSpeed: Infinity, // px/s + + // @option easeLinearity: Number = 0.2 + easeLinearity: 0.2, + + // TODO refactor, move to CRS + // @option worldCopyJump: Boolean = false + // With this option enabled, the map tracks when you pan to another "copy" + // of the world and seamlessly jumps to the original one so that all overlays + // like markers and vector layers are still visible. + worldCopyJump: false, + + // @option maxBoundsViscosity: Number = 0.0 + // If `maxBounds` is set, this option will control how solid the bounds + // are when dragging the map around. The default value of `0.0` allows the + // user to drag outside the bounds at normal speed, higher values will + // slow down map dragging outside bounds, and `1.0` makes the bounds fully + // solid, preventing the user from dragging outside the bounds. + maxBoundsViscosity: 0.0 +}); + +var Drag = Handler.extend({ + addHooks: function () { + if (!this._draggable) { + var map = this._map; + + this._draggable = new Draggable(map._mapPane, map._container); + + this._draggable.on({ + dragstart: this._onDragStart, + drag: this._onDrag, + dragend: this._onDragEnd + }, this); + + this._draggable.on('predrag', this._onPreDragLimit, this); + if (map.options.worldCopyJump) { + this._draggable.on('predrag', this._onPreDragWrap, this); + map.on('zoomend', this._onZoomEnd, this); + + map.whenReady(this._onZoomEnd, this); + } + } + addClass(this._map._container, 'leaflet-grab leaflet-touch-drag'); + this._draggable.enable(); + this._positions = []; + this._times = []; + }, + + removeHooks: function () { + removeClass(this._map._container, 'leaflet-grab'); + removeClass(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 map = this._map; + + map._stop(); + if (this._map.options.maxBounds && this._map.options.maxBoundsViscosity) { + var bounds = toLatLngBounds(this._map.options.maxBounds); + + this._offsetLimit = toBounds( + this._map.latLngToContainerPoint(bounds.getNorthWest()).multiplyBy(-1), + this._map.latLngToContainerPoint(bounds.getSouthEast()).multiplyBy(-1) + .add(this._map.getSize())); + + this._viscosity = Math.min(1.0, Math.max(0.0, this._map.options.maxBoundsViscosity)); + } else { + this._offsetLimit = null; + } + + map + .fire('movestart') + .fire('dragstart'); + + if (map.options.inertia) { + this._positions = []; + this._times = []; + } + }, + + _onDrag: function (e) { + if (this._map.options.inertia) { + var time = this._lastTime = +new Date(), + pos = this._lastPos = this._draggable._absPos || this._draggable._newPos; + + this._positions.push(pos); + this._times.push(time); + + this._prunePositions(time); + } + + this._map + .fire('move', e) + .fire('drag', e); + }, + + _prunePositions: function (time) { + while (this._positions.length > 1 && time - this._times[0] > 50) { + this._positions.shift(); + this._times.shift(); + } + }, + + _onZoomEnd: function () { + var pxCenter = this._map.getSize().divideBy(2), + pxWorldCenter = this._map.latLngToLayerPoint([0, 0]); + + this._initialWorldOffset = pxWorldCenter.subtract(pxCenter).x; + this._worldWidth = this._map.getPixelWorldBounds().getSize().x; + }, + + _viscousLimit: function (value, threshold) { + return value - (value - threshold) * this._viscosity; + }, + + _onPreDragLimit: function () { + if (!this._viscosity || !this._offsetLimit) { return; } + + var offset = this._draggable._newPos.subtract(this._draggable._startPos); + + var limit = this._offsetLimit; + if (offset.x < limit.min.x) { offset.x = this._viscousLimit(offset.x, limit.min.x); } + if (offset.y < limit.min.y) { offset.y = this._viscousLimit(offset.y, limit.min.y); } + if (offset.x > limit.max.x) { offset.x = this._viscousLimit(offset.x, limit.max.x); } + if (offset.y > limit.max.y) { offset.y = this._viscousLimit(offset.y, limit.max.y); } + + this._draggable._newPos = this._draggable._startPos.add(offset); + }, + + _onPreDragWrap: function () { + // TODO refactor to be able to adjust map pane position after zoom + var worldWidth = this._worldWidth, + halfWidth = Math.round(worldWidth / 2), + dx = this._initialWorldOffset, + x = this._draggable._newPos.x, + newX1 = (x - halfWidth + dx) % worldWidth + halfWidth - dx, + newX2 = (x + halfWidth + dx) % worldWidth - halfWidth - dx, + newX = Math.abs(newX1 + dx) < Math.abs(newX2 + dx) ? newX1 : newX2; + + this._draggable._absPos = this._draggable._newPos.clone(); + this._draggable._newPos.x = newX; + }, + + _onDragEnd: function (e) { + var map = this._map, + options = map.options, + + noInertia = !options.inertia || this._times.length < 2; + + map.fire('dragend', e); + + if (noInertia) { + map.fire('moveend'); + + } else { + this._prunePositions(+new Date()); + + var direction = this._lastPos.subtract(this._positions[0]), + duration = (this._lastTime - this._times[0]) / 1000, + ease = options.easeLinearity, + + speedVector = direction.multiplyBy(ease / duration), + speed = speedVector.distanceTo([0, 0]), + + limitedSpeed = Math.min(options.inertiaMaxSpeed, speed), + limitedSpeedVector = speedVector.multiplyBy(limitedSpeed / speed), + + decelerationDuration = limitedSpeed / (options.inertiaDeceleration * ease), + offset = limitedSpeedVector.multiplyBy(-decelerationDuration / 2).round(); + + if (!offset.x && !offset.y) { + map.fire('moveend'); + + } else { + offset = map._limitOffset(offset, map.options.maxBounds); + + requestAnimFrame(function () { + map.panBy(offset, { + duration: decelerationDuration, + easeLinearity: ease, + noMoveStart: true, + animate: true + }); + }); + } + } + } +}); + +// @section Handlers +// @property dragging: Handler +// Map dragging handler (by both mouse and touch). +Map.addInitHook('addHandler', 'dragging', Drag); + +/* + * L.Map.Keyboard is handling keyboard interaction with the map, enabled by default. + */ + +// @namespace Map +// @section Keyboard Navigation Options +Map.mergeOptions({ + // @option keyboard: Boolean = true + // Makes the map focusable and allows users to navigate the map with keyboard + // arrows and `+`/`-` keys. + keyboard: true, + + // @option keyboardPanDelta: Number = 80 + // Amount of pixels to pan when pressing an arrow key. + keyboardPanDelta: 80 +}); + +var Keyboard = Handler.extend({ + + keyCodes: { + left: [37], + right: [39], + down: [40], + up: [38], + zoomIn: [187, 107, 61, 171], + zoomOut: [189, 109, 54, 173] + }, + + initialize: function (map) { + this._map = map; + + this._setPanDelta(map.options.keyboardPanDelta); + this._setZoomDelta(map.options.zoomDelta); + }, + + addHooks: function () { + var container = this._map._container; + + // make the container focusable by tabbing + if (container.tabIndex <= 0) { + container.tabIndex = '0'; + } + + on(container, { + focus: this._onFocus, + blur: this._onBlur, + mousedown: this._onMouseDown + }, this); + + this._map.on({ + focus: this._addHooks, + blur: this._removeHooks + }, this); + }, + + removeHooks: function () { + this._removeHooks(); + + off(this._map._container, { + focus: this._onFocus, + blur: this._onBlur, + mousedown: this._onMouseDown + }, this); + + this._map.off({ + focus: this._addHooks, + blur: this._removeHooks + }, this); + }, + + _onMouseDown: function () { + if (this._focused) { return; } + + var body = document.body, + docEl = document.documentElement, + top = body.scrollTop || docEl.scrollTop, + left = body.scrollLeft || docEl.scrollLeft; + + this._map._container.focus(); + + window.scrollTo(left, top); + }, + + _onFocus: function () { + this._focused = true; + this._map.fire('focus'); + }, + + _onBlur: function () { + this._focused = false; + this._map.fire('blur'); + }, + + _setPanDelta: function (panDelta) { + var keys = this._panKeys = {}, + codes = this.keyCodes, + i, len; + + for (i = 0, len = codes.left.length; i < len; i++) { + keys[codes.left[i]] = [-1 * panDelta, 0]; + } + for (i = 0, len = codes.right.length; i < len; i++) { + keys[codes.right[i]] = [panDelta, 0]; + } + for (i = 0, len = codes.down.length; i < len; i++) { + keys[codes.down[i]] = [0, panDelta]; + } + for (i = 0, len = codes.up.length; i < len; i++) { + keys[codes.up[i]] = [0, -1 * panDelta]; + } + }, + + _setZoomDelta: function (zoomDelta) { + var keys = this._zoomKeys = {}, + codes = this.keyCodes, + i, len; + + for (i = 0, len = codes.zoomIn.length; i < len; i++) { + keys[codes.zoomIn[i]] = zoomDelta; + } + for (i = 0, len = codes.zoomOut.length; i < len; i++) { + keys[codes.zoomOut[i]] = -zoomDelta; + } + }, + + _addHooks: function () { + on(document, 'keydown', this._onKeyDown, this); + }, + + _removeHooks: function () { + off(document, 'keydown', this._onKeyDown, this); + }, + + _onKeyDown: function (e) { + if (e.altKey || e.ctrlKey || e.metaKey) { return; } + + var key = e.keyCode, + map = this._map, + offset; + + if (key in this._panKeys) { + if (!map._panAnim || !map._panAnim._inProgress) { + offset = this._panKeys[key]; + if (e.shiftKey) { + offset = toPoint(offset).multiplyBy(3); + } + + map.panBy(offset); + + if (map.options.maxBounds) { + map.panInsideBounds(map.options.maxBounds); + } + } + } else if (key in this._zoomKeys) { + map.setZoom(map.getZoom() + (e.shiftKey ? 3 : 1) * this._zoomKeys[key]); + + } else if (key === 27 && map._popup && map._popup.options.closeOnEscapeKey) { + map.closePopup(); + + } else { + return; + } + + stop(e); + } +}); + +// @section Handlers +// @section Handlers +// @property keyboard: Handler +// Keyboard navigation handler. +Map.addInitHook('addHandler', 'keyboard', Keyboard); + +/* + * L.Handler.ScrollWheelZoom is used by L.Map to enable mouse scroll wheel zoom on the map. + */ + +// @namespace Map +// @section Interaction Options +Map.mergeOptions({ + // @section Mousewheel options + // @option scrollWheelZoom: Boolean|String = true + // Whether the map can be zoomed by using the mouse wheel. If passed `'center'`, + // it will zoom to the center of the view regardless of where the mouse was. + scrollWheelZoom: true, + + // @option wheelDebounceTime: Number = 40 + // Limits the rate at which a wheel can fire (in milliseconds). By default + // user can't zoom via wheel more often than once per 40 ms. + wheelDebounceTime: 40, + + // @option wheelPxPerZoomLevel: Number = 60 + // How many scroll pixels (as reported by [L.DomEvent.getWheelDelta](#domevent-getwheeldelta)) + // mean a change of one full zoom level. Smaller values will make wheel-zooming + // faster (and vice versa). + wheelPxPerZoomLevel: 60 +}); + +var ScrollWheelZoom = Handler.extend({ + addHooks: function () { + on(this._map._container, 'mousewheel', this._onWheelScroll, this); + + this._delta = 0; + }, + + removeHooks: function () { + off(this._map._container, 'mousewheel', this._onWheelScroll, this); + }, + + _onWheelScroll: function (e) { + var delta = getWheelDelta(e); + + var debounce = this._map.options.wheelDebounceTime; + + this._delta += delta; + this._lastMousePos = this._map.mouseEventToContainerPoint(e); + + if (!this._startTime) { + this._startTime = +new Date(); + } + + var left = Math.max(debounce - (+new Date() - this._startTime), 0); + + clearTimeout(this._timer); + this._timer = setTimeout(bind(this._performZoom, this), left); + + stop(e); + }, + + _performZoom: function () { + var map = this._map, + zoom = map.getZoom(), + snap = this._map.options.zoomSnap || 0; + + map._stop(); // stop panning and fly animations if any + + // map the delta with a sigmoid function to -4..4 range leaning on -1..1 + var d2 = this._delta / (this._map.options.wheelPxPerZoomLevel * 4), + d3 = 4 * Math.log(2 / (1 + Math.exp(-Math.abs(d2)))) / Math.LN2, + d4 = snap ? Math.ceil(d3 / snap) * snap : d3, + delta = map._limitZoom(zoom + (this._delta > 0 ? d4 : -d4)) - zoom; + + this._delta = 0; + this._startTime = null; + + if (!delta) { return; } + + if (map.options.scrollWheelZoom === 'center') { + map.setZoom(zoom + delta); + } else { + map.setZoomAround(this._lastMousePos, zoom + delta); + } + } +}); + +// @section Handlers +// @property scrollWheelZoom: Handler +// Scroll wheel zoom handler. +Map.addInitHook('addHandler', 'scrollWheelZoom', ScrollWheelZoom); + +/* + * L.Map.Tap is used to enable mobile hacks like quick taps and long hold. + */ + +// @namespace Map +// @section Interaction Options +Map.mergeOptions({ + // @section Touch interaction options + // @option tap: Boolean = true + // Enables mobile hacks for supporting instant taps (fixing 200ms click + // delay on iOS/Android) and touch holds (fired as `contextmenu` events). + tap: true, + + // @option tapTolerance: Number = 15 + // The max number of pixels a user can shift his finger during touch + // for it to be considered a valid tap. + tapTolerance: 15 +}); + +var Tap = Handler.extend({ + addHooks: function () { + on(this._map._container, 'touchstart', this._onDown, this); + }, + + removeHooks: function () { + off(this._map._container, 'touchstart', this._onDown, this); + }, + + _onDown: function (e) { + if (!e.touches) { return; } + + preventDefault(e); + + this._fireClick = true; + + // don't simulate click or track longpress if more than 1 touch + if (e.touches.length > 1) { + this._fireClick = false; + clearTimeout(this._holdTimeout); + return; + } + + var first = e.touches[0], + el = first.target; + + this._startPos = this._newPos = new Point(first.clientX, first.clientY); + + // if touching a link, highlight it + if (el.tagName && el.tagName.toLowerCase() === 'a') { + addClass(el, 'leaflet-active'); + } + + // simulate long hold but setting a timeout + this._holdTimeout = setTimeout(bind(function () { + if (this._isTapValid()) { + this._fireClick = false; + this._onUp(); + this._simulateEvent('contextmenu', first); + } + }, this), 1000); + + this._simulateEvent('mousedown', first); + + on(document, { + touchmove: this._onMove, + touchend: this._onUp + }, this); + }, + + _onUp: function (e) { + clearTimeout(this._holdTimeout); + + off(document, { + touchmove: this._onMove, + touchend: this._onUp + }, this); + + if (this._fireClick && e && e.changedTouches) { + + var first = e.changedTouches[0], + el = first.target; + + if (el && el.tagName && el.tagName.toLowerCase() === 'a') { + removeClass(el, 'leaflet-active'); + } + + this._simulateEvent('mouseup', first); + + // simulate click if the touch didn't move too much + if (this._isTapValid()) { + this._simulateEvent('click', first); + } + } + }, + + _isTapValid: function () { + return this._newPos.distanceTo(this._startPos) <= this._map.options.tapTolerance; + }, + + _onMove: function (e) { + var first = e.touches[0]; + this._newPos = new Point(first.clientX, first.clientY); + this._simulateEvent('mousemove', first); + }, + + _simulateEvent: function (type, e) { + var simulatedEvent = document.createEvent('MouseEvents'); + + simulatedEvent._simulated = true; + e.target._simulatedClick = true; + + simulatedEvent.initMouseEvent( + type, true, true, window, 1, + e.screenX, e.screenY, + e.clientX, e.clientY, + false, false, false, false, 0, null); + + e.target.dispatchEvent(simulatedEvent); + } +}); + +// @section Handlers +// @property tap: Handler +// Mobile touch hacks (quick tap and touch hold) handler. +if (touch && !pointer) { + Map.addInitHook('addHandler', 'tap', Tap); +} + +/* + * L.Handler.TouchZoom is used by L.Map to add pinch zoom on supported mobile browsers. + */ + +// @namespace Map +// @section Interaction Options +Map.mergeOptions({ + // @section Touch interaction options + // @option touchZoom: Boolean|String = * + // Whether the map can be zoomed by touch-dragging with two fingers. If + // passed `'center'`, it will zoom to the center of the view regardless of + // where the touch events (fingers) were. Enabled for touch-capable web + // browsers except for old Androids. + touchZoom: touch && !android23, + + // @option bounceAtZoomLimits: Boolean = true + // Set it to false if you don't want the map to zoom beyond min/max zoom + // and then bounce back when pinch-zooming. + bounceAtZoomLimits: true +}); + +var TouchZoom = Handler.extend({ + addHooks: function () { + addClass(this._map._container, 'leaflet-touch-zoom'); + on(this._map._container, 'touchstart', this._onTouchStart, this); + }, + + removeHooks: function () { + removeClass(this._map._container, 'leaflet-touch-zoom'); + off(this._map._container, 'touchstart', this._onTouchStart, this); + }, + + _onTouchStart: function (e) { + var map = this._map; + if (!e.touches || e.touches.length !== 2 || map._animatingZoom || this._zooming) { return; } + + var p1 = map.mouseEventToContainerPoint(e.touches[0]), + p2 = map.mouseEventToContainerPoint(e.touches[1]); + + this._centerPoint = map.getSize()._divideBy(2); + this._startLatLng = map.containerPointToLatLng(this._centerPoint); + if (map.options.touchZoom !== 'center') { + this._pinchStartLatLng = map.containerPointToLatLng(p1.add(p2)._divideBy(2)); + } + + this._startDist = p1.distanceTo(p2); + this._startZoom = map.getZoom(); + + this._moved = false; + this._zooming = true; + + map._stop(); + + on(document, 'touchmove', this._onTouchMove, this); + on(document, 'touchend', this._onTouchEnd, this); + + preventDefault(e); + }, + + _onTouchMove: function (e) { + if (!e.touches || e.touches.length !== 2 || !this._zooming) { return; } + + var map = this._map, + p1 = map.mouseEventToContainerPoint(e.touches[0]), + p2 = map.mouseEventToContainerPoint(e.touches[1]), + scale = p1.distanceTo(p2) / this._startDist; + + this._zoom = map.getScaleZoom(scale, this._startZoom); + + if (!map.options.bounceAtZoomLimits && ( + (this._zoom < map.getMinZoom() && scale < 1) || + (this._zoom > map.getMaxZoom() && scale > 1))) { + this._zoom = map._limitZoom(this._zoom); + } + + if (map.options.touchZoom === 'center') { + this._center = this._startLatLng; + if (scale === 1) { return; } + } else { + // Get delta from pinch to center, so centerLatLng is delta applied to initial pinchLatLng + var delta = p1._add(p2)._divideBy(2)._subtract(this._centerPoint); + if (scale === 1 && delta.x === 0 && delta.y === 0) { return; } + this._center = map.unproject(map.project(this._pinchStartLatLng, this._zoom).subtract(delta), this._zoom); + } + + if (!this._moved) { + map._moveStart(true, false); + this._moved = true; + } + + cancelAnimFrame(this._animRequest); + + var moveFn = bind(map._move, map, this._center, this._zoom, {pinch: true, round: false}); + this._animRequest = requestAnimFrame(moveFn, this, true); + + preventDefault(e); + }, + + _onTouchEnd: function () { + if (!this._moved || !this._zooming) { + this._zooming = false; + return; + } + + this._zooming = false; + cancelAnimFrame(this._animRequest); + + off(document, 'touchmove', this._onTouchMove); + off(document, 'touchend', this._onTouchEnd); + + // Pinch updates GridLayers' levels only when zoomSnap is off, so zoomSnap becomes noUpdate. + if (this._map.options.zoomAnimation) { + this._map._animateZoom(this._center, this._map._limitZoom(this._zoom), true, this._map.options.zoomSnap); + } else { + this._map._resetView(this._center, this._map._limitZoom(this._zoom)); + } + } +}); + +// @section Handlers +// @property touchZoom: Handler +// Touch zoom handler. +Map.addInitHook('addHandler', 'touchZoom', TouchZoom); + +Map.BoxZoom = BoxZoom; +Map.DoubleClickZoom = DoubleClickZoom; +Map.Drag = Drag; +Map.Keyboard = Keyboard; +Map.ScrollWheelZoom = ScrollWheelZoom; +Map.Tap = Tap; +Map.TouchZoom = TouchZoom; + +Object.freeze = freeze; + +export { version, Control, control, Browser, Evented, Mixin, Util, Class, Handler, extend, bind, stamp, setOptions, DomEvent, DomUtil, PosAnimation, Draggable, LineUtil, PolyUtil, Point, toPoint as point, Bounds, toBounds as bounds, Transformation, toTransformation as transformation, index as Projection, LatLng, toLatLng as latLng, LatLngBounds, toLatLngBounds as latLngBounds, CRS, GeoJSON, geoJSON, geoJson, Layer, LayerGroup, layerGroup, FeatureGroup, featureGroup, ImageOverlay, imageOverlay, VideoOverlay, videoOverlay, SVGOverlay, svgOverlay, DivOverlay, Popup, popup, Tooltip, tooltip, Icon, icon, DivIcon, divIcon, Marker, marker, TileLayer, tileLayer, GridLayer, gridLayer, SVG, svg$1 as svg, Renderer, Canvas, canvas$1 as canvas, Path, CircleMarker, circleMarker, Circle, circle, Polyline, polyline, Polygon, polygon, Rectangle, rectangle, Map, createMap as map }; +//# sourceMappingURL=leaflet-src.esm.js.map diff --git a/deploy/grafana-map-plugin/dist/vendor/leaflet/leaflet-src.esm.js.map b/deploy/grafana-map-plugin/dist/vendor/leaflet/leaflet-src.esm.js.map new file mode 100755 index 0000000..bf2a31d --- /dev/null +++ b/deploy/grafana-map-plugin/dist/vendor/leaflet/leaflet-src.esm.js.map @@ -0,0 +1 @@ +{"version":3,"file":"leaflet-src.esm.js","sources":["../src/core/Util.js","../src/core/Class.js","../src/core/Events.js","../src/geometry/Point.js","../src/geometry/Bounds.js","../src/geo/LatLngBounds.js","../src/geo/LatLng.js","../src/geo/crs/CRS.js","../src/geo/crs/CRS.Earth.js","../src/geo/projection/Projection.SphericalMercator.js","../src/geometry/Transformation.js","../src/geo/crs/CRS.EPSG3857.js","../src/layer/vector/SVG.Util.js","../src/core/Browser.js","../src/dom/DomEvent.Pointer.js","../src/dom/DomEvent.DoubleTap.js","../src/dom/DomUtil.js","../src/dom/DomEvent.js","../src/dom/PosAnimation.js","../src/map/Map.js","../src/control/Control.js","../src/control/Control.Layers.js","../src/control/Control.Zoom.js","../src/control/Control.Scale.js","../src/control/Control.Attribution.js","../src/control/index.js","../src/core/Handler.js","../src/core/index.js","../src/dom/Draggable.js","../src/geometry/LineUtil.js","../src/geometry/PolyUtil.js","../src/geo/projection/Projection.LonLat.js","../src/geo/projection/Projection.Mercator.js","../src/geo/projection/index.js","../src/geo/crs/CRS.EPSG3395.js","../src/geo/crs/CRS.EPSG4326.js","../src/geo/crs/CRS.Simple.js","../src/geo/crs/index.js","../src/layer/Layer.js","../src/layer/LayerGroup.js","../src/layer/FeatureGroup.js","../src/layer/marker/Icon.js","../src/layer/marker/Icon.Default.js","../src/layer/marker/Marker.Drag.js","../src/layer/marker/Marker.js","../src/layer/vector/Path.js","../src/layer/vector/CircleMarker.js","../src/layer/vector/Circle.js","../src/layer/vector/Polyline.js","../src/layer/vector/Polygon.js","../src/layer/GeoJSON.js","../src/layer/ImageOverlay.js","../src/layer/VideoOverlay.js","../src/layer/SVGOverlay.js","../src/layer/DivOverlay.js","../src/layer/Popup.js","../src/layer/Tooltip.js","../src/layer/marker/DivIcon.js","../src/layer/marker/index.js","../src/layer/tile/GridLayer.js","../src/layer/tile/TileLayer.js","../src/layer/tile/TileLayer.WMS.js","../src/layer/tile/index.js","../src/layer/vector/Renderer.js","../src/layer/vector/Canvas.js","../src/layer/vector/SVG.VML.js","../src/layer/vector/SVG.js","../src/layer/vector/Renderer.getRenderer.js","../src/layer/vector/Rectangle.js","../src/layer/vector/index.js","../src/layer/index.js","../src/map/handler/Map.BoxZoom.js","../src/map/handler/Map.DoubleClickZoom.js","../src/map/handler/Map.Drag.js","../src/map/handler/Map.Keyboard.js","../src/map/handler/Map.ScrollWheelZoom.js","../src/map/handler/Map.Tap.js","../src/map/handler/Map.TouchZoom.js","../src/map/index.js","../src/Leaflet.js"],"sourcesContent":["/*\r\n * @namespace Util\r\n *\r\n * Various utility functions, used by Leaflet internally.\r\n */\r\n\r\nexport var freeze = Object.freeze;\r\nObject.freeze = function (obj) { return obj; };\r\n\r\n// @function extend(dest: Object, src?: Object): Object\r\n// Merges the properties of the `src` object (or multiple objects) into `dest` object and returns the latter. Has an `L.extend` shortcut.\r\nexport function extend(dest) {\r\n\tvar i, j, len, src;\r\n\r\n\tfor (j = 1, len = arguments.length; j < len; j++) {\r\n\t\tsrc = arguments[j];\r\n\t\tfor (i in src) {\r\n\t\t\tdest[i] = src[i];\r\n\t\t}\r\n\t}\r\n\treturn dest;\r\n}\r\n\r\n// @function create(proto: Object, properties?: Object): Object\r\n// Compatibility polyfill for [Object.create](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/create)\r\nexport var create = Object.create || (function () {\r\n\tfunction F() {}\r\n\treturn function (proto) {\r\n\t\tF.prototype = proto;\r\n\t\treturn new F();\r\n\t};\r\n})();\r\n\r\n// @function bind(fn: Function, …): Function\r\n// Returns a new function bound to the arguments passed, like [Function.prototype.bind](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Function/bind).\r\n// Has a `L.bind()` shortcut.\r\nexport function bind(fn, obj) {\r\n\tvar slice = Array.prototype.slice;\r\n\r\n\tif (fn.bind) {\r\n\t\treturn fn.bind.apply(fn, slice.call(arguments, 1));\r\n\t}\r\n\r\n\tvar args = slice.call(arguments, 2);\r\n\r\n\treturn function () {\r\n\t\treturn fn.apply(obj, args.length ? args.concat(slice.call(arguments)) : arguments);\r\n\t};\r\n}\r\n\r\n// @property lastId: Number\r\n// Last unique ID used by [`stamp()`](#util-stamp)\r\nexport var lastId = 0;\r\n\r\n// @function stamp(obj: Object): Number\r\n// Returns the unique ID of an object, assigning it one if it doesn't have it.\r\nexport function stamp(obj) {\r\n\t/*eslint-disable */\r\n\tobj._leaflet_id = obj._leaflet_id || ++lastId;\r\n\treturn obj._leaflet_id;\r\n\t/* eslint-enable */\r\n}\r\n\r\n// @function throttle(fn: Function, time: Number, context: Object): Function\r\n// Returns a function which executes function `fn` with the given scope `context`\r\n// (so that the `this` keyword refers to `context` inside `fn`'s code). The function\r\n// `fn` will be called no more than one time per given amount of `time`. The arguments\r\n// received by the bound function will be any arguments passed when binding the\r\n// function, followed by any arguments passed when invoking the bound function.\r\n// Has an `L.throttle` shortcut.\r\nexport function throttle(fn, time, context) {\r\n\tvar lock, args, wrapperFn, later;\r\n\r\n\tlater = function () {\r\n\t\t// reset lock and call if queued\r\n\t\tlock = false;\r\n\t\tif (args) {\r\n\t\t\twrapperFn.apply(context, args);\r\n\t\t\targs = false;\r\n\t\t}\r\n\t};\r\n\r\n\twrapperFn = function () {\r\n\t\tif (lock) {\r\n\t\t\t// called too soon, queue to call later\r\n\t\t\targs = arguments;\r\n\r\n\t\t} else {\r\n\t\t\t// call and lock until later\r\n\t\t\tfn.apply(context, arguments);\r\n\t\t\tsetTimeout(later, time);\r\n\t\t\tlock = true;\r\n\t\t}\r\n\t};\r\n\r\n\treturn wrapperFn;\r\n}\r\n\r\n// @function wrapNum(num: Number, range: Number[], includeMax?: Boolean): Number\r\n// Returns the number `num` modulo `range` in such a way so it lies within\r\n// `range[0]` and `range[1]`. The returned value will be always smaller than\r\n// `range[1]` unless `includeMax` is set to `true`.\r\nexport function wrapNum(x, range, includeMax) {\r\n\tvar max = range[1],\r\n\t min = range[0],\r\n\t d = max - min;\r\n\treturn x === max && includeMax ? x : ((x - min) % d + d) % d + min;\r\n}\r\n\r\n// @function falseFn(): Function\r\n// Returns a function which always returns `false`.\r\nexport function falseFn() { return false; }\r\n\r\n// @function formatNum(num: Number, digits?: Number): Number\r\n// Returns the number `num` rounded to `digits` decimals, or to 6 decimals by default.\r\nexport function formatNum(num, digits) {\r\n\tvar pow = Math.pow(10, (digits === undefined ? 6 : digits));\r\n\treturn Math.round(num * pow) / pow;\r\n}\r\n\r\n// @function trim(str: String): String\r\n// Compatibility polyfill for [String.prototype.trim](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/Trim)\r\nexport function trim(str) {\r\n\treturn str.trim ? str.trim() : str.replace(/^\\s+|\\s+$/g, '');\r\n}\r\n\r\n// @function splitWords(str: String): String[]\r\n// Trims and splits the string on whitespace and returns the array of parts.\r\nexport function splitWords(str) {\r\n\treturn trim(str).split(/\\s+/);\r\n}\r\n\r\n// @function setOptions(obj: Object, options: Object): Object\r\n// Merges the given properties to the `options` of the `obj` object, returning the resulting options. See `Class options`. Has an `L.setOptions` shortcut.\r\nexport function setOptions(obj, options) {\r\n\tif (!obj.hasOwnProperty('options')) {\r\n\t\tobj.options = obj.options ? create(obj.options) : {};\r\n\t}\r\n\tfor (var i in options) {\r\n\t\tobj.options[i] = options[i];\r\n\t}\r\n\treturn obj.options;\r\n}\r\n\r\n// @function getParamString(obj: Object, existingUrl?: String, uppercase?: Boolean): String\r\n// Converts an object into a parameter URL string, e.g. `{a: \"foo\", b: \"bar\"}`\r\n// translates to `'?a=foo&b=bar'`. If `existingUrl` is set, the parameters will\r\n// be appended at the end. If `uppercase` is `true`, the parameter names will\r\n// be uppercased (e.g. `'?A=foo&B=bar'`)\r\nexport function getParamString(obj, existingUrl, uppercase) {\r\n\tvar params = [];\r\n\tfor (var i in obj) {\r\n\t\tparams.push(encodeURIComponent(uppercase ? i.toUpperCase() : i) + '=' + encodeURIComponent(obj[i]));\r\n\t}\r\n\treturn ((!existingUrl || existingUrl.indexOf('?') === -1) ? '?' : '&') + params.join('&');\r\n}\r\n\r\nvar templateRe = /\\{ *([\\w_-]+) *\\}/g;\r\n\r\n// @function template(str: String, data: Object): String\r\n// Simple templating facility, accepts a template string of the form `'Hello {a}, {b}'`\r\n// and a data object like `{a: 'foo', b: 'bar'}`, returns evaluated string\r\n// `('Hello foo, bar')`. You can also specify functions instead of strings for\r\n// data values — they will be evaluated passing `data` as an argument.\r\nexport function template(str, data) {\r\n\treturn str.replace(templateRe, function (str, key) {\r\n\t\tvar value = data[key];\r\n\r\n\t\tif (value === undefined) {\r\n\t\t\tthrow new Error('No value provided for variable ' + str);\r\n\r\n\t\t} else if (typeof value === 'function') {\r\n\t\t\tvalue = value(data);\r\n\t\t}\r\n\t\treturn value;\r\n\t});\r\n}\r\n\r\n// @function isArray(obj): Boolean\r\n// Compatibility polyfill for [Array.isArray](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray)\r\nexport var isArray = Array.isArray || function (obj) {\r\n\treturn (Object.prototype.toString.call(obj) === '[object Array]');\r\n};\r\n\r\n// @function indexOf(array: Array, el: Object): Number\r\n// Compatibility polyfill for [Array.prototype.indexOf](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf)\r\nexport function indexOf(array, el) {\r\n\tfor (var i = 0; i < array.length; i++) {\r\n\t\tif (array[i] === el) { return i; }\r\n\t}\r\n\treturn -1;\r\n}\r\n\r\n// @property emptyImageUrl: String\r\n// Data URI string containing a base64-encoded empty GIF image.\r\n// Used as a hack to free memory from unused images on WebKit-powered\r\n// mobile devices (by setting image `src` to this string).\r\nexport var emptyImageUrl = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=';\r\n\r\n// inspired by http://paulirish.com/2011/requestanimationframe-for-smart-animating/\r\n\r\nfunction getPrefixed(name) {\r\n\treturn window['webkit' + name] || window['moz' + name] || window['ms' + name];\r\n}\r\n\r\nvar lastTime = 0;\r\n\r\n// fallback for IE 7-8\r\nfunction timeoutDefer(fn) {\r\n\tvar time = +new Date(),\r\n\t timeToCall = Math.max(0, 16 - (time - lastTime));\r\n\r\n\tlastTime = time + timeToCall;\r\n\treturn window.setTimeout(fn, timeToCall);\r\n}\r\n\r\nexport var requestFn = window.requestAnimationFrame || getPrefixed('RequestAnimationFrame') || timeoutDefer;\r\nexport var cancelFn = window.cancelAnimationFrame || getPrefixed('CancelAnimationFrame') ||\r\n\t\tgetPrefixed('CancelRequestAnimationFrame') || function (id) { window.clearTimeout(id); };\r\n\r\n// @function requestAnimFrame(fn: Function, context?: Object, immediate?: Boolean): Number\r\n// Schedules `fn` to be executed when the browser repaints. `fn` is bound to\r\n// `context` if given. When `immediate` is set, `fn` is called immediately if\r\n// the browser doesn't have native support for\r\n// [`window.requestAnimationFrame`](https://developer.mozilla.org/docs/Web/API/window/requestAnimationFrame),\r\n// otherwise it's delayed. Returns a request ID that can be used to cancel the request.\r\nexport function requestAnimFrame(fn, context, immediate) {\r\n\tif (immediate && requestFn === timeoutDefer) {\r\n\t\tfn.call(context);\r\n\t} else {\r\n\t\treturn requestFn.call(window, bind(fn, context));\r\n\t}\r\n}\r\n\r\n// @function cancelAnimFrame(id: Number): undefined\r\n// Cancels a previous `requestAnimFrame`. See also [window.cancelAnimationFrame](https://developer.mozilla.org/docs/Web/API/window/cancelAnimationFrame).\r\nexport function cancelAnimFrame(id) {\r\n\tif (id) {\r\n\t\tcancelFn.call(window, id);\r\n\t}\r\n}\r\n","import * as Util from './Util';\r\n\r\n// @class Class\r\n// @aka L.Class\r\n\r\n// @section\r\n// @uninheritable\r\n\r\n// Thanks to John Resig and Dean Edwards for inspiration!\r\n\r\nexport function Class() {}\r\n\r\nClass.extend = function (props) {\r\n\r\n\t// @function extend(props: Object): Function\r\n\t// [Extends the current class](#class-inheritance) given the properties to be included.\r\n\t// Returns a Javascript function that is a class constructor (to be called with `new`).\r\n\tvar NewClass = function () {\r\n\r\n\t\t// call the constructor\r\n\t\tif (this.initialize) {\r\n\t\t\tthis.initialize.apply(this, arguments);\r\n\t\t}\r\n\r\n\t\t// call all constructor hooks\r\n\t\tthis.callInitHooks();\r\n\t};\r\n\r\n\tvar parentProto = NewClass.__super__ = this.prototype;\r\n\r\n\tvar proto = Util.create(parentProto);\r\n\tproto.constructor = NewClass;\r\n\r\n\tNewClass.prototype = proto;\r\n\r\n\t// inherit parent's statics\r\n\tfor (var i in this) {\r\n\t\tif (this.hasOwnProperty(i) && i !== 'prototype' && i !== '__super__') {\r\n\t\t\tNewClass[i] = this[i];\r\n\t\t}\r\n\t}\r\n\r\n\t// mix static properties into the class\r\n\tif (props.statics) {\r\n\t\tUtil.extend(NewClass, props.statics);\r\n\t\tdelete props.statics;\r\n\t}\r\n\r\n\t// mix includes into the prototype\r\n\tif (props.includes) {\r\n\t\tcheckDeprecatedMixinEvents(props.includes);\r\n\t\tUtil.extend.apply(null, [proto].concat(props.includes));\r\n\t\tdelete props.includes;\r\n\t}\r\n\r\n\t// merge options\r\n\tif (proto.options) {\r\n\t\tprops.options = Util.extend(Util.create(proto.options), props.options);\r\n\t}\r\n\r\n\t// mix given properties into the prototype\r\n\tUtil.extend(proto, props);\r\n\r\n\tproto._initHooks = [];\r\n\r\n\t// add method for calling all hooks\r\n\tproto.callInitHooks = function () {\r\n\r\n\t\tif (this._initHooksCalled) { return; }\r\n\r\n\t\tif (parentProto.callInitHooks) {\r\n\t\t\tparentProto.callInitHooks.call(this);\r\n\t\t}\r\n\r\n\t\tthis._initHooksCalled = true;\r\n\r\n\t\tfor (var i = 0, len = proto._initHooks.length; i < len; i++) {\r\n\t\t\tproto._initHooks[i].call(this);\r\n\t\t}\r\n\t};\r\n\r\n\treturn NewClass;\r\n};\r\n\r\n\r\n// @function include(properties: Object): this\r\n// [Includes a mixin](#class-includes) into the current class.\r\nClass.include = function (props) {\r\n\tUtil.extend(this.prototype, props);\r\n\treturn this;\r\n};\r\n\r\n// @function mergeOptions(options: Object): this\r\n// [Merges `options`](#class-options) into the defaults of the class.\r\nClass.mergeOptions = function (options) {\r\n\tUtil.extend(this.prototype.options, options);\r\n\treturn this;\r\n};\r\n\r\n// @function addInitHook(fn: Function): this\r\n// Adds a [constructor hook](#class-constructor-hooks) to the class.\r\nClass.addInitHook = function (fn) { // (Function) || (String, args...)\r\n\tvar args = Array.prototype.slice.call(arguments, 1);\r\n\r\n\tvar init = typeof fn === 'function' ? fn : function () {\r\n\t\tthis[fn].apply(this, args);\r\n\t};\r\n\r\n\tthis.prototype._initHooks = this.prototype._initHooks || [];\r\n\tthis.prototype._initHooks.push(init);\r\n\treturn this;\r\n};\r\n\r\nfunction checkDeprecatedMixinEvents(includes) {\r\n\tif (typeof L === 'undefined' || !L || !L.Mixin) { return; }\r\n\r\n\tincludes = Util.isArray(includes) ? includes : [includes];\r\n\r\n\tfor (var i = 0; i < includes.length; i++) {\r\n\t\tif (includes[i] === L.Mixin.Events) {\r\n\t\t\tconsole.warn('Deprecated include of L.Mixin.Events: ' +\r\n\t\t\t\t'this property will be removed in future releases, ' +\r\n\t\t\t\t'please inherit from L.Evented instead.', new Error().stack);\r\n\t\t}\r\n\t}\r\n}\r\n","import {Class} from './Class';\r\nimport * as Util from './Util';\r\n\r\n/*\r\n * @class Evented\r\n * @aka L.Evented\r\n * @inherits Class\r\n *\r\n * A set of methods shared between event-powered classes (like `Map` and `Marker`). Generally, events allow you to execute some function when something happens with an object (e.g. the user clicks on the map, causing the map to fire `'click'` event).\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * map.on('click', function(e) {\r\n * \talert(e.latlng);\r\n * } );\r\n * ```\r\n *\r\n * Leaflet deals with event listeners by reference, so if you want to add a listener and then remove it, define it as a function:\r\n *\r\n * ```js\r\n * function onClick(e) { ... }\r\n *\r\n * map.on('click', onClick);\r\n * map.off('click', onClick);\r\n * ```\r\n */\r\n\r\nexport var Events = {\r\n\t/* @method on(type: String, fn: Function, context?: Object): this\r\n\t * Adds a listener function (`fn`) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. `'click dblclick'`).\r\n\t *\r\n\t * @alternative\r\n\t * @method on(eventMap: Object): this\r\n\t * Adds a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}`\r\n\t */\r\n\ton: function (types, fn, context) {\r\n\r\n\t\t// types can be a map of types/handlers\r\n\t\tif (typeof types === 'object') {\r\n\t\t\tfor (var type in types) {\r\n\t\t\t\t// we don't process space-separated events here for performance;\r\n\t\t\t\t// it's a hot path since Layer uses the on(obj) syntax\r\n\t\t\t\tthis._on(type, types[type], fn);\r\n\t\t\t}\r\n\r\n\t\t} else {\r\n\t\t\t// types can be a string of space-separated words\r\n\t\t\ttypes = Util.splitWords(types);\r\n\r\n\t\t\tfor (var i = 0, len = types.length; i < len; i++) {\r\n\t\t\t\tthis._on(types[i], fn, context);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t/* @method off(type: String, fn?: Function, context?: Object): this\r\n\t * Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to `on`, you must pass the same context to `off` in order to remove the listener.\r\n\t *\r\n\t * @alternative\r\n\t * @method off(eventMap: Object): this\r\n\t * Removes a set of type/listener pairs.\r\n\t *\r\n\t * @alternative\r\n\t * @method off: this\r\n\t * Removes all listeners to all events on the object. This includes implicitly attached events.\r\n\t */\r\n\toff: function (types, fn, context) {\r\n\r\n\t\tif (!types) {\r\n\t\t\t// clear all listeners if called without arguments\r\n\t\t\tdelete this._events;\r\n\r\n\t\t} else if (typeof types === 'object') {\r\n\t\t\tfor (var type in types) {\r\n\t\t\t\tthis._off(type, types[type], fn);\r\n\t\t\t}\r\n\r\n\t\t} else {\r\n\t\t\ttypes = Util.splitWords(types);\r\n\r\n\t\t\tfor (var i = 0, len = types.length; i < len; i++) {\r\n\t\t\t\tthis._off(types[i], fn, context);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// attach listener (without syntactic sugar now)\r\n\t_on: function (type, fn, context) {\r\n\t\tthis._events = this._events || {};\r\n\r\n\t\t/* get/init listeners for type */\r\n\t\tvar typeListeners = this._events[type];\r\n\t\tif (!typeListeners) {\r\n\t\t\ttypeListeners = [];\r\n\t\t\tthis._events[type] = typeListeners;\r\n\t\t}\r\n\r\n\t\tif (context === this) {\r\n\t\t\t// Less memory footprint.\r\n\t\t\tcontext = undefined;\r\n\t\t}\r\n\t\tvar newListener = {fn: fn, ctx: context},\r\n\t\t listeners = typeListeners;\r\n\r\n\t\t// check if fn already there\r\n\t\tfor (var i = 0, len = listeners.length; i < len; i++) {\r\n\t\t\tif (listeners[i].fn === fn && listeners[i].ctx === context) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tlisteners.push(newListener);\r\n\t},\r\n\r\n\t_off: function (type, fn, context) {\r\n\t\tvar listeners,\r\n\t\t i,\r\n\t\t len;\r\n\r\n\t\tif (!this._events) { return; }\r\n\r\n\t\tlisteners = this._events[type];\r\n\r\n\t\tif (!listeners) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (!fn) {\r\n\t\t\t// Set all removed listeners to noop so they are not called if remove happens in fire\r\n\t\t\tfor (i = 0, len = listeners.length; i < len; i++) {\r\n\t\t\t\tlisteners[i].fn = Util.falseFn;\r\n\t\t\t}\r\n\t\t\t// clear all listeners for a type if function isn't specified\r\n\t\t\tdelete this._events[type];\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (context === this) {\r\n\t\t\tcontext = undefined;\r\n\t\t}\r\n\r\n\t\tif (listeners) {\r\n\r\n\t\t\t// find fn and remove it\r\n\t\t\tfor (i = 0, len = listeners.length; i < len; i++) {\r\n\t\t\t\tvar l = listeners[i];\r\n\t\t\t\tif (l.ctx !== context) { continue; }\r\n\t\t\t\tif (l.fn === fn) {\r\n\r\n\t\t\t\t\t// set the removed listener to noop so that's not called if remove happens in fire\r\n\t\t\t\t\tl.fn = Util.falseFn;\r\n\r\n\t\t\t\t\tif (this._firingCount) {\r\n\t\t\t\t\t\t/* copy array in case events are being fired */\r\n\t\t\t\t\t\tthis._events[type] = listeners = listeners.slice();\r\n\t\t\t\t\t}\r\n\t\t\t\t\tlisteners.splice(i, 1);\r\n\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\t// @method fire(type: String, data?: Object, propagate?: Boolean): this\r\n\t// Fires an event of the specified type. You can optionally provide an data\r\n\t// object — the first argument of the listener function will contain its\r\n\t// properties. The event can optionally be propagated to event parents.\r\n\tfire: function (type, data, propagate) {\r\n\t\tif (!this.listens(type, propagate)) { return this; }\r\n\r\n\t\tvar event = Util.extend({}, data, {\r\n\t\t\ttype: type,\r\n\t\t\ttarget: this,\r\n\t\t\tsourceTarget: data && data.sourceTarget || this\r\n\t\t});\r\n\r\n\t\tif (this._events) {\r\n\t\t\tvar listeners = this._events[type];\r\n\r\n\t\t\tif (listeners) {\r\n\t\t\t\tthis._firingCount = (this._firingCount + 1) || 1;\r\n\t\t\t\tfor (var i = 0, len = listeners.length; i < len; i++) {\r\n\t\t\t\t\tvar l = listeners[i];\r\n\t\t\t\t\tl.fn.call(l.ctx || this, event);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis._firingCount--;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (propagate) {\r\n\t\t\t// propagate the event to parents (set with addEventParent)\r\n\t\t\tthis._propagateEvent(event);\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method listens(type: String): Boolean\r\n\t// Returns `true` if a particular event type has any listeners attached to it.\r\n\tlistens: function (type, propagate) {\r\n\t\tvar listeners = this._events && this._events[type];\r\n\t\tif (listeners && listeners.length) { return true; }\r\n\r\n\t\tif (propagate) {\r\n\t\t\t// also check parents for listeners if event propagates\r\n\t\t\tfor (var id in this._eventParents) {\r\n\t\t\t\tif (this._eventParents[id].listens(type, propagate)) { return true; }\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn false;\r\n\t},\r\n\r\n\t// @method once(…): this\r\n\t// Behaves as [`on(…)`](#evented-on), except the listener will only get fired once and then removed.\r\n\tonce: function (types, fn, context) {\r\n\r\n\t\tif (typeof types === 'object') {\r\n\t\t\tfor (var type in types) {\r\n\t\t\t\tthis.once(type, types[type], fn);\r\n\t\t\t}\r\n\t\t\treturn this;\r\n\t\t}\r\n\r\n\t\tvar handler = Util.bind(function () {\r\n\t\t\tthis\r\n\t\t\t .off(types, fn, context)\r\n\t\t\t .off(types, handler, context);\r\n\t\t}, this);\r\n\r\n\t\t// add a listener that's executed once and removed after that\r\n\t\treturn this\r\n\t\t .on(types, fn, context)\r\n\t\t .on(types, handler, context);\r\n\t},\r\n\r\n\t// @method addEventParent(obj: Evented): this\r\n\t// Adds an event parent - an `Evented` that will receive propagated events\r\n\taddEventParent: function (obj) {\r\n\t\tthis._eventParents = this._eventParents || {};\r\n\t\tthis._eventParents[Util.stamp(obj)] = obj;\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method removeEventParent(obj: Evented): this\r\n\t// Removes an event parent, so it will stop receiving propagated events\r\n\tremoveEventParent: function (obj) {\r\n\t\tif (this._eventParents) {\r\n\t\t\tdelete this._eventParents[Util.stamp(obj)];\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t_propagateEvent: function (e) {\r\n\t\tfor (var id in this._eventParents) {\r\n\t\t\tthis._eventParents[id].fire(e.type, Util.extend({\r\n\t\t\t\tlayer: e.target,\r\n\t\t\t\tpropagatedFrom: e.target\r\n\t\t\t}, e), true);\r\n\t\t}\r\n\t}\r\n};\r\n\r\n// aliases; we should ditch those eventually\r\n\r\n// @method addEventListener(…): this\r\n// Alias to [`on(…)`](#evented-on)\r\nEvents.addEventListener = Events.on;\r\n\r\n// @method removeEventListener(…): this\r\n// Alias to [`off(…)`](#evented-off)\r\n\r\n// @method clearAllEventListeners(…): this\r\n// Alias to [`off()`](#evented-off)\r\nEvents.removeEventListener = Events.clearAllEventListeners = Events.off;\r\n\r\n// @method addOneTimeEventListener(…): this\r\n// Alias to [`once(…)`](#evented-once)\r\nEvents.addOneTimeEventListener = Events.once;\r\n\r\n// @method fireEvent(…): this\r\n// Alias to [`fire(…)`](#evented-fire)\r\nEvents.fireEvent = Events.fire;\r\n\r\n// @method hasEventListeners(…): Boolean\r\n// Alias to [`listens(…)`](#evented-listens)\r\nEvents.hasEventListeners = Events.listens;\r\n\r\nexport var Evented = Class.extend(Events);\r\n","import {isArray, formatNum} from '../core/Util';\r\n\r\n/*\r\n * @class Point\r\n * @aka L.Point\r\n *\r\n * Represents a point with `x` and `y` coordinates in pixels.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * var point = L.point(200, 300);\r\n * ```\r\n *\r\n * All Leaflet methods and options that accept `Point` objects also accept them in a simple Array form (unless noted otherwise), so these lines are equivalent:\r\n *\r\n * ```js\r\n * map.panBy([200, 300]);\r\n * map.panBy(L.point(200, 300));\r\n * ```\r\n *\r\n * Note that `Point` does not inherit from Leafet's `Class` object,\r\n * which means new classes can't inherit from it, and new methods\r\n * can't be added to it with the `include` function.\r\n */\r\n\r\nexport function Point(x, y, round) {\r\n\t// @property x: Number; The `x` coordinate of the point\r\n\tthis.x = (round ? Math.round(x) : x);\r\n\t// @property y: Number; The `y` coordinate of the point\r\n\tthis.y = (round ? Math.round(y) : y);\r\n}\r\n\r\nvar trunc = Math.trunc || function (v) {\r\n\treturn v > 0 ? Math.floor(v) : Math.ceil(v);\r\n};\r\n\r\nPoint.prototype = {\r\n\r\n\t// @method clone(): Point\r\n\t// Returns a copy of the current point.\r\n\tclone: function () {\r\n\t\treturn new Point(this.x, this.y);\r\n\t},\r\n\r\n\t// @method add(otherPoint: Point): Point\r\n\t// Returns the result of addition of the current and the given points.\r\n\tadd: function (point) {\r\n\t\t// non-destructive, returns a new point\r\n\t\treturn this.clone()._add(toPoint(point));\r\n\t},\r\n\r\n\t_add: function (point) {\r\n\t\t// destructive, used directly for performance in situations where it's safe to modify existing point\r\n\t\tthis.x += point.x;\r\n\t\tthis.y += point.y;\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method subtract(otherPoint: Point): Point\r\n\t// Returns the result of subtraction of the given point from the current.\r\n\tsubtract: function (point) {\r\n\t\treturn this.clone()._subtract(toPoint(point));\r\n\t},\r\n\r\n\t_subtract: function (point) {\r\n\t\tthis.x -= point.x;\r\n\t\tthis.y -= point.y;\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method divideBy(num: Number): Point\r\n\t// Returns the result of division of the current point by the given number.\r\n\tdivideBy: function (num) {\r\n\t\treturn this.clone()._divideBy(num);\r\n\t},\r\n\r\n\t_divideBy: function (num) {\r\n\t\tthis.x /= num;\r\n\t\tthis.y /= num;\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method multiplyBy(num: Number): Point\r\n\t// Returns the result of multiplication of the current point by the given number.\r\n\tmultiplyBy: function (num) {\r\n\t\treturn this.clone()._multiplyBy(num);\r\n\t},\r\n\r\n\t_multiplyBy: function (num) {\r\n\t\tthis.x *= num;\r\n\t\tthis.y *= num;\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method scaleBy(scale: Point): Point\r\n\t// Multiply each coordinate of the current point by each coordinate of\r\n\t// `scale`. In linear algebra terms, multiply the point by the\r\n\t// [scaling matrix](https://en.wikipedia.org/wiki/Scaling_%28geometry%29#Matrix_representation)\r\n\t// defined by `scale`.\r\n\tscaleBy: function (point) {\r\n\t\treturn new Point(this.x * point.x, this.y * point.y);\r\n\t},\r\n\r\n\t// @method unscaleBy(scale: Point): Point\r\n\t// Inverse of `scaleBy`. Divide each coordinate of the current point by\r\n\t// each coordinate of `scale`.\r\n\tunscaleBy: function (point) {\r\n\t\treturn new Point(this.x / point.x, this.y / point.y);\r\n\t},\r\n\r\n\t// @method round(): Point\r\n\t// Returns a copy of the current point with rounded coordinates.\r\n\tround: function () {\r\n\t\treturn this.clone()._round();\r\n\t},\r\n\r\n\t_round: function () {\r\n\t\tthis.x = Math.round(this.x);\r\n\t\tthis.y = Math.round(this.y);\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method floor(): Point\r\n\t// Returns a copy of the current point with floored coordinates (rounded down).\r\n\tfloor: function () {\r\n\t\treturn this.clone()._floor();\r\n\t},\r\n\r\n\t_floor: function () {\r\n\t\tthis.x = Math.floor(this.x);\r\n\t\tthis.y = Math.floor(this.y);\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method ceil(): Point\r\n\t// Returns a copy of the current point with ceiled coordinates (rounded up).\r\n\tceil: function () {\r\n\t\treturn this.clone()._ceil();\r\n\t},\r\n\r\n\t_ceil: function () {\r\n\t\tthis.x = Math.ceil(this.x);\r\n\t\tthis.y = Math.ceil(this.y);\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method trunc(): Point\r\n\t// Returns a copy of the current point with truncated coordinates (rounded towards zero).\r\n\ttrunc: function () {\r\n\t\treturn this.clone()._trunc();\r\n\t},\r\n\r\n\t_trunc: function () {\r\n\t\tthis.x = trunc(this.x);\r\n\t\tthis.y = trunc(this.y);\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method distanceTo(otherPoint: Point): Number\r\n\t// Returns the cartesian distance between the current and the given points.\r\n\tdistanceTo: function (point) {\r\n\t\tpoint = toPoint(point);\r\n\r\n\t\tvar x = point.x - this.x,\r\n\t\t y = point.y - this.y;\r\n\r\n\t\treturn Math.sqrt(x * x + y * y);\r\n\t},\r\n\r\n\t// @method equals(otherPoint: Point): Boolean\r\n\t// Returns `true` if the given point has the same coordinates.\r\n\tequals: function (point) {\r\n\t\tpoint = toPoint(point);\r\n\r\n\t\treturn point.x === this.x &&\r\n\t\t point.y === this.y;\r\n\t},\r\n\r\n\t// @method contains(otherPoint: Point): Boolean\r\n\t// Returns `true` if both coordinates of the given point are less than the corresponding current point coordinates (in absolute values).\r\n\tcontains: function (point) {\r\n\t\tpoint = toPoint(point);\r\n\r\n\t\treturn Math.abs(point.x) <= Math.abs(this.x) &&\r\n\t\t Math.abs(point.y) <= Math.abs(this.y);\r\n\t},\r\n\r\n\t// @method toString(): String\r\n\t// Returns a string representation of the point for debugging purposes.\r\n\ttoString: function () {\r\n\t\treturn 'Point(' +\r\n\t\t formatNum(this.x) + ', ' +\r\n\t\t formatNum(this.y) + ')';\r\n\t}\r\n};\r\n\r\n// @factory L.point(x: Number, y: Number, round?: Boolean)\r\n// Creates a Point object with the given `x` and `y` coordinates. If optional `round` is set to true, rounds the `x` and `y` values.\r\n\r\n// @alternative\r\n// @factory L.point(coords: Number[])\r\n// Expects an array of the form `[x, y]` instead.\r\n\r\n// @alternative\r\n// @factory L.point(coords: Object)\r\n// Expects a plain object of the form `{x: Number, y: Number}` instead.\r\nexport function toPoint(x, y, round) {\r\n\tif (x instanceof Point) {\r\n\t\treturn x;\r\n\t}\r\n\tif (isArray(x)) {\r\n\t\treturn new Point(x[0], x[1]);\r\n\t}\r\n\tif (x === undefined || x === null) {\r\n\t\treturn x;\r\n\t}\r\n\tif (typeof x === 'object' && 'x' in x && 'y' in x) {\r\n\t\treturn new Point(x.x, x.y);\r\n\t}\r\n\treturn new Point(x, y, round);\r\n}\r\n","import {Point, toPoint} from './Point';\r\n\r\n/*\r\n * @class Bounds\r\n * @aka L.Bounds\r\n *\r\n * Represents a rectangular area in pixel coordinates.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * var p1 = L.point(10, 10),\r\n * p2 = L.point(40, 60),\r\n * bounds = L.bounds(p1, p2);\r\n * ```\r\n *\r\n * All Leaflet methods that accept `Bounds` objects also accept them in a simple Array form (unless noted otherwise), so the bounds example above can be passed like this:\r\n *\r\n * ```js\r\n * otherBounds.intersects([[10, 10], [40, 60]]);\r\n * ```\r\n *\r\n * Note that `Bounds` does not inherit from Leafet's `Class` object,\r\n * which means new classes can't inherit from it, and new methods\r\n * can't be added to it with the `include` function.\r\n */\r\n\r\nexport function Bounds(a, b) {\r\n\tif (!a) { return; }\r\n\r\n\tvar points = b ? [a, b] : a;\r\n\r\n\tfor (var i = 0, len = points.length; i < len; i++) {\r\n\t\tthis.extend(points[i]);\r\n\t}\r\n}\r\n\r\nBounds.prototype = {\r\n\t// @method extend(point: Point): this\r\n\t// Extends the bounds to contain the given point.\r\n\textend: function (point) { // (Point)\r\n\t\tpoint = toPoint(point);\r\n\r\n\t\t// @property min: Point\r\n\t\t// The top left corner of the rectangle.\r\n\t\t// @property max: Point\r\n\t\t// The bottom right corner of the rectangle.\r\n\t\tif (!this.min && !this.max) {\r\n\t\t\tthis.min = point.clone();\r\n\t\t\tthis.max = point.clone();\r\n\t\t} else {\r\n\t\t\tthis.min.x = Math.min(point.x, this.min.x);\r\n\t\t\tthis.max.x = Math.max(point.x, this.max.x);\r\n\t\t\tthis.min.y = Math.min(point.y, this.min.y);\r\n\t\t\tthis.max.y = Math.max(point.y, this.max.y);\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method getCenter(round?: Boolean): Point\r\n\t// Returns the center point of the bounds.\r\n\tgetCenter: function (round) {\r\n\t\treturn new Point(\r\n\t\t (this.min.x + this.max.x) / 2,\r\n\t\t (this.min.y + this.max.y) / 2, round);\r\n\t},\r\n\r\n\t// @method getBottomLeft(): Point\r\n\t// Returns the bottom-left point of the bounds.\r\n\tgetBottomLeft: function () {\r\n\t\treturn new Point(this.min.x, this.max.y);\r\n\t},\r\n\r\n\t// @method getTopRight(): Point\r\n\t// Returns the top-right point of the bounds.\r\n\tgetTopRight: function () { // -> Point\r\n\t\treturn new Point(this.max.x, this.min.y);\r\n\t},\r\n\r\n\t// @method getTopLeft(): Point\r\n\t// Returns the top-left point of the bounds (i.e. [`this.min`](#bounds-min)).\r\n\tgetTopLeft: function () {\r\n\t\treturn this.min; // left, top\r\n\t},\r\n\r\n\t// @method getBottomRight(): Point\r\n\t// Returns the bottom-right point of the bounds (i.e. [`this.max`](#bounds-max)).\r\n\tgetBottomRight: function () {\r\n\t\treturn this.max; // right, bottom\r\n\t},\r\n\r\n\t// @method getSize(): Point\r\n\t// Returns the size of the given bounds\r\n\tgetSize: function () {\r\n\t\treturn this.max.subtract(this.min);\r\n\t},\r\n\r\n\t// @method contains(otherBounds: Bounds): Boolean\r\n\t// Returns `true` if the rectangle contains the given one.\r\n\t// @alternative\r\n\t// @method contains(point: Point): Boolean\r\n\t// Returns `true` if the rectangle contains the given point.\r\n\tcontains: function (obj) {\r\n\t\tvar min, max;\r\n\r\n\t\tif (typeof obj[0] === 'number' || obj instanceof Point) {\r\n\t\t\tobj = toPoint(obj);\r\n\t\t} else {\r\n\t\t\tobj = toBounds(obj);\r\n\t\t}\r\n\r\n\t\tif (obj instanceof Bounds) {\r\n\t\t\tmin = obj.min;\r\n\t\t\tmax = obj.max;\r\n\t\t} else {\r\n\t\t\tmin = max = obj;\r\n\t\t}\r\n\r\n\t\treturn (min.x >= this.min.x) &&\r\n\t\t (max.x <= this.max.x) &&\r\n\t\t (min.y >= this.min.y) &&\r\n\t\t (max.y <= this.max.y);\r\n\t},\r\n\r\n\t// @method intersects(otherBounds: Bounds): Boolean\r\n\t// Returns `true` if the rectangle intersects the given bounds. Two bounds\r\n\t// intersect if they have at least one point in common.\r\n\tintersects: function (bounds) { // (Bounds) -> Boolean\r\n\t\tbounds = toBounds(bounds);\r\n\r\n\t\tvar min = this.min,\r\n\t\t max = this.max,\r\n\t\t min2 = bounds.min,\r\n\t\t max2 = bounds.max,\r\n\t\t xIntersects = (max2.x >= min.x) && (min2.x <= max.x),\r\n\t\t yIntersects = (max2.y >= min.y) && (min2.y <= max.y);\r\n\r\n\t\treturn xIntersects && yIntersects;\r\n\t},\r\n\r\n\t// @method overlaps(otherBounds: Bounds): Boolean\r\n\t// Returns `true` if the rectangle overlaps the given bounds. Two bounds\r\n\t// overlap if their intersection is an area.\r\n\toverlaps: function (bounds) { // (Bounds) -> Boolean\r\n\t\tbounds = toBounds(bounds);\r\n\r\n\t\tvar min = this.min,\r\n\t\t max = this.max,\r\n\t\t min2 = bounds.min,\r\n\t\t max2 = bounds.max,\r\n\t\t xOverlaps = (max2.x > min.x) && (min2.x < max.x),\r\n\t\t yOverlaps = (max2.y > min.y) && (min2.y < max.y);\r\n\r\n\t\treturn xOverlaps && yOverlaps;\r\n\t},\r\n\r\n\tisValid: function () {\r\n\t\treturn !!(this.min && this.max);\r\n\t}\r\n};\r\n\r\n\r\n// @factory L.bounds(corner1: Point, corner2: Point)\r\n// Creates a Bounds object from two corners coordinate pairs.\r\n// @alternative\r\n// @factory L.bounds(points: Point[])\r\n// Creates a Bounds object from the given array of points.\r\nexport function toBounds(a, b) {\r\n\tif (!a || a instanceof Bounds) {\r\n\t\treturn a;\r\n\t}\r\n\treturn new Bounds(a, b);\r\n}\r\n","import {LatLng, toLatLng} from './LatLng';\r\n\r\n/*\r\n * @class LatLngBounds\r\n * @aka L.LatLngBounds\r\n *\r\n * Represents a rectangular geographical area on a map.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * var corner1 = L.latLng(40.712, -74.227),\r\n * corner2 = L.latLng(40.774, -74.125),\r\n * bounds = L.latLngBounds(corner1, corner2);\r\n * ```\r\n *\r\n * All Leaflet methods that accept LatLngBounds objects also accept them in a simple Array form (unless noted otherwise), so the bounds example above can be passed like this:\r\n *\r\n * ```js\r\n * map.fitBounds([\r\n * \t[40.712, -74.227],\r\n * \t[40.774, -74.125]\r\n * ]);\r\n * ```\r\n *\r\n * Caution: if the area crosses the antimeridian (often confused with the International Date Line), you must specify corners _outside_ the [-180, 180] degrees longitude range.\r\n *\r\n * Note that `LatLngBounds` does not inherit from Leafet's `Class` object,\r\n * which means new classes can't inherit from it, and new methods\r\n * can't be added to it with the `include` function.\r\n */\r\n\r\nexport function LatLngBounds(corner1, corner2) { // (LatLng, LatLng) or (LatLng[])\r\n\tif (!corner1) { return; }\r\n\r\n\tvar latlngs = corner2 ? [corner1, corner2] : corner1;\r\n\r\n\tfor (var i = 0, len = latlngs.length; i < len; i++) {\r\n\t\tthis.extend(latlngs[i]);\r\n\t}\r\n}\r\n\r\nLatLngBounds.prototype = {\r\n\r\n\t// @method extend(latlng: LatLng): this\r\n\t// Extend the bounds to contain the given point\r\n\r\n\t// @alternative\r\n\t// @method extend(otherBounds: LatLngBounds): this\r\n\t// Extend the bounds to contain the given bounds\r\n\textend: function (obj) {\r\n\t\tvar sw = this._southWest,\r\n\t\t ne = this._northEast,\r\n\t\t sw2, ne2;\r\n\r\n\t\tif (obj instanceof LatLng) {\r\n\t\t\tsw2 = obj;\r\n\t\t\tne2 = obj;\r\n\r\n\t\t} else if (obj instanceof LatLngBounds) {\r\n\t\t\tsw2 = obj._southWest;\r\n\t\t\tne2 = obj._northEast;\r\n\r\n\t\t\tif (!sw2 || !ne2) { return this; }\r\n\r\n\t\t} else {\r\n\t\t\treturn obj ? this.extend(toLatLng(obj) || toLatLngBounds(obj)) : this;\r\n\t\t}\r\n\r\n\t\tif (!sw && !ne) {\r\n\t\t\tthis._southWest = new LatLng(sw2.lat, sw2.lng);\r\n\t\t\tthis._northEast = new LatLng(ne2.lat, ne2.lng);\r\n\t\t} else {\r\n\t\t\tsw.lat = Math.min(sw2.lat, sw.lat);\r\n\t\t\tsw.lng = Math.min(sw2.lng, sw.lng);\r\n\t\t\tne.lat = Math.max(ne2.lat, ne.lat);\r\n\t\t\tne.lng = Math.max(ne2.lng, ne.lng);\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method pad(bufferRatio: Number): LatLngBounds\r\n\t// Returns bounds created by extending or retracting the current bounds by a given ratio in each direction.\r\n\t// For example, a ratio of 0.5 extends the bounds by 50% in each direction.\r\n\t// Negative values will retract the bounds.\r\n\tpad: function (bufferRatio) {\r\n\t\tvar sw = this._southWest,\r\n\t\t ne = this._northEast,\r\n\t\t heightBuffer = Math.abs(sw.lat - ne.lat) * bufferRatio,\r\n\t\t widthBuffer = Math.abs(sw.lng - ne.lng) * bufferRatio;\r\n\r\n\t\treturn new LatLngBounds(\r\n\t\t new LatLng(sw.lat - heightBuffer, sw.lng - widthBuffer),\r\n\t\t new LatLng(ne.lat + heightBuffer, ne.lng + widthBuffer));\r\n\t},\r\n\r\n\t// @method getCenter(): LatLng\r\n\t// Returns the center point of the bounds.\r\n\tgetCenter: function () {\r\n\t\treturn new LatLng(\r\n\t\t (this._southWest.lat + this._northEast.lat) / 2,\r\n\t\t (this._southWest.lng + this._northEast.lng) / 2);\r\n\t},\r\n\r\n\t// @method getSouthWest(): LatLng\r\n\t// Returns the south-west point of the bounds.\r\n\tgetSouthWest: function () {\r\n\t\treturn this._southWest;\r\n\t},\r\n\r\n\t// @method getNorthEast(): LatLng\r\n\t// Returns the north-east point of the bounds.\r\n\tgetNorthEast: function () {\r\n\t\treturn this._northEast;\r\n\t},\r\n\r\n\t// @method getNorthWest(): LatLng\r\n\t// Returns the north-west point of the bounds.\r\n\tgetNorthWest: function () {\r\n\t\treturn new LatLng(this.getNorth(), this.getWest());\r\n\t},\r\n\r\n\t// @method getSouthEast(): LatLng\r\n\t// Returns the south-east point of the bounds.\r\n\tgetSouthEast: function () {\r\n\t\treturn new LatLng(this.getSouth(), this.getEast());\r\n\t},\r\n\r\n\t// @method getWest(): Number\r\n\t// Returns the west longitude of the bounds\r\n\tgetWest: function () {\r\n\t\treturn this._southWest.lng;\r\n\t},\r\n\r\n\t// @method getSouth(): Number\r\n\t// Returns the south latitude of the bounds\r\n\tgetSouth: function () {\r\n\t\treturn this._southWest.lat;\r\n\t},\r\n\r\n\t// @method getEast(): Number\r\n\t// Returns the east longitude of the bounds\r\n\tgetEast: function () {\r\n\t\treturn this._northEast.lng;\r\n\t},\r\n\r\n\t// @method getNorth(): Number\r\n\t// Returns the north latitude of the bounds\r\n\tgetNorth: function () {\r\n\t\treturn this._northEast.lat;\r\n\t},\r\n\r\n\t// @method contains(otherBounds: LatLngBounds): Boolean\r\n\t// Returns `true` if the rectangle contains the given one.\r\n\r\n\t// @alternative\r\n\t// @method contains (latlng: LatLng): Boolean\r\n\t// Returns `true` if the rectangle contains the given point.\r\n\tcontains: function (obj) { // (LatLngBounds) or (LatLng) -> Boolean\r\n\t\tif (typeof obj[0] === 'number' || obj instanceof LatLng || 'lat' in obj) {\r\n\t\t\tobj = toLatLng(obj);\r\n\t\t} else {\r\n\t\t\tobj = toLatLngBounds(obj);\r\n\t\t}\r\n\r\n\t\tvar sw = this._southWest,\r\n\t\t ne = this._northEast,\r\n\t\t sw2, ne2;\r\n\r\n\t\tif (obj instanceof LatLngBounds) {\r\n\t\t\tsw2 = obj.getSouthWest();\r\n\t\t\tne2 = obj.getNorthEast();\r\n\t\t} else {\r\n\t\t\tsw2 = ne2 = obj;\r\n\t\t}\r\n\r\n\t\treturn (sw2.lat >= sw.lat) && (ne2.lat <= ne.lat) &&\r\n\t\t (sw2.lng >= sw.lng) && (ne2.lng <= ne.lng);\r\n\t},\r\n\r\n\t// @method intersects(otherBounds: LatLngBounds): Boolean\r\n\t// Returns `true` if the rectangle intersects the given bounds. Two bounds intersect if they have at least one point in common.\r\n\tintersects: function (bounds) {\r\n\t\tbounds = toLatLngBounds(bounds);\r\n\r\n\t\tvar sw = this._southWest,\r\n\t\t ne = this._northEast,\r\n\t\t sw2 = bounds.getSouthWest(),\r\n\t\t ne2 = bounds.getNorthEast(),\r\n\r\n\t\t latIntersects = (ne2.lat >= sw.lat) && (sw2.lat <= ne.lat),\r\n\t\t lngIntersects = (ne2.lng >= sw.lng) && (sw2.lng <= ne.lng);\r\n\r\n\t\treturn latIntersects && lngIntersects;\r\n\t},\r\n\r\n\t// @method overlaps(otherBounds: Bounds): Boolean\r\n\t// Returns `true` if the rectangle overlaps the given bounds. Two bounds overlap if their intersection is an area.\r\n\toverlaps: function (bounds) {\r\n\t\tbounds = toLatLngBounds(bounds);\r\n\r\n\t\tvar sw = this._southWest,\r\n\t\t ne = this._northEast,\r\n\t\t sw2 = bounds.getSouthWest(),\r\n\t\t ne2 = bounds.getNorthEast(),\r\n\r\n\t\t latOverlaps = (ne2.lat > sw.lat) && (sw2.lat < ne.lat),\r\n\t\t lngOverlaps = (ne2.lng > sw.lng) && (sw2.lng < ne.lng);\r\n\r\n\t\treturn latOverlaps && lngOverlaps;\r\n\t},\r\n\r\n\t// @method toBBoxString(): String\r\n\t// Returns a string with bounding box coordinates in a 'southwest_lng,southwest_lat,northeast_lng,northeast_lat' format. Useful for sending requests to web services that return geo data.\r\n\ttoBBoxString: function () {\r\n\t\treturn [this.getWest(), this.getSouth(), this.getEast(), this.getNorth()].join(',');\r\n\t},\r\n\r\n\t// @method equals(otherBounds: LatLngBounds, maxMargin?: Number): Boolean\r\n\t// Returns `true` if the rectangle is equivalent (within a small margin of error) to the given bounds. The margin of error can be overridden by setting `maxMargin` to a small number.\r\n\tequals: function (bounds, maxMargin) {\r\n\t\tif (!bounds) { return false; }\r\n\r\n\t\tbounds = toLatLngBounds(bounds);\r\n\r\n\t\treturn this._southWest.equals(bounds.getSouthWest(), maxMargin) &&\r\n\t\t this._northEast.equals(bounds.getNorthEast(), maxMargin);\r\n\t},\r\n\r\n\t// @method isValid(): Boolean\r\n\t// Returns `true` if the bounds are properly initialized.\r\n\tisValid: function () {\r\n\t\treturn !!(this._southWest && this._northEast);\r\n\t}\r\n};\r\n\r\n// TODO International date line?\r\n\r\n// @factory L.latLngBounds(corner1: LatLng, corner2: LatLng)\r\n// Creates a `LatLngBounds` object by defining two diagonally opposite corners of the rectangle.\r\n\r\n// @alternative\r\n// @factory L.latLngBounds(latlngs: LatLng[])\r\n// Creates a `LatLngBounds` object defined by the geographical points it contains. Very useful for zooming the map to fit a particular set of locations with [`fitBounds`](#map-fitbounds).\r\nexport function toLatLngBounds(a, b) {\r\n\tif (a instanceof LatLngBounds) {\r\n\t\treturn a;\r\n\t}\r\n\treturn new LatLngBounds(a, b);\r\n}\r\n","import * as Util from '../core/Util';\r\nimport {Earth} from './crs/CRS.Earth';\r\nimport {toLatLngBounds} from './LatLngBounds';\r\n\r\n/* @class LatLng\r\n * @aka L.LatLng\r\n *\r\n * Represents a geographical point with a certain latitude and longitude.\r\n *\r\n * @example\r\n *\r\n * ```\r\n * var latlng = L.latLng(50.5, 30.5);\r\n * ```\r\n *\r\n * All Leaflet methods that accept LatLng objects also accept them in a simple Array form and simple object form (unless noted otherwise), so these lines are equivalent:\r\n *\r\n * ```\r\n * map.panTo([50, 30]);\r\n * map.panTo({lon: 30, lat: 50});\r\n * map.panTo({lat: 50, lng: 30});\r\n * map.panTo(L.latLng(50, 30));\r\n * ```\r\n *\r\n * Note that `LatLng` does not inherit from Leaflet's `Class` object,\r\n * which means new classes can't inherit from it, and new methods\r\n * can't be added to it with the `include` function.\r\n */\r\n\r\nexport function LatLng(lat, lng, alt) {\r\n\tif (isNaN(lat) || isNaN(lng)) {\r\n\t\tthrow new Error('Invalid LatLng object: (' + lat + ', ' + lng + ')');\r\n\t}\r\n\r\n\t// @property lat: Number\r\n\t// Latitude in degrees\r\n\tthis.lat = +lat;\r\n\r\n\t// @property lng: Number\r\n\t// Longitude in degrees\r\n\tthis.lng = +lng;\r\n\r\n\t// @property alt: Number\r\n\t// Altitude in meters (optional)\r\n\tif (alt !== undefined) {\r\n\t\tthis.alt = +alt;\r\n\t}\r\n}\r\n\r\nLatLng.prototype = {\r\n\t// @method equals(otherLatLng: LatLng, maxMargin?: Number): Boolean\r\n\t// Returns `true` if the given `LatLng` point is at the same position (within a small margin of error). The margin of error can be overridden by setting `maxMargin` to a small number.\r\n\tequals: function (obj, maxMargin) {\r\n\t\tif (!obj) { return false; }\r\n\r\n\t\tobj = toLatLng(obj);\r\n\r\n\t\tvar margin = Math.max(\r\n\t\t Math.abs(this.lat - obj.lat),\r\n\t\t Math.abs(this.lng - obj.lng));\r\n\r\n\t\treturn margin <= (maxMargin === undefined ? 1.0E-9 : maxMargin);\r\n\t},\r\n\r\n\t// @method toString(): String\r\n\t// Returns a string representation of the point (for debugging purposes).\r\n\ttoString: function (precision) {\r\n\t\treturn 'LatLng(' +\r\n\t\t Util.formatNum(this.lat, precision) + ', ' +\r\n\t\t Util.formatNum(this.lng, precision) + ')';\r\n\t},\r\n\r\n\t// @method distanceTo(otherLatLng: LatLng): Number\r\n\t// Returns the distance (in meters) to the given `LatLng` calculated using the [Spherical Law of Cosines](https://en.wikipedia.org/wiki/Spherical_law_of_cosines).\r\n\tdistanceTo: function (other) {\r\n\t\treturn Earth.distance(this, toLatLng(other));\r\n\t},\r\n\r\n\t// @method wrap(): LatLng\r\n\t// Returns a new `LatLng` object with the longitude wrapped so it's always between -180 and +180 degrees.\r\n\twrap: function () {\r\n\t\treturn Earth.wrapLatLng(this);\r\n\t},\r\n\r\n\t// @method toBounds(sizeInMeters: Number): LatLngBounds\r\n\t// Returns a new `LatLngBounds` object in which each boundary is `sizeInMeters/2` meters apart from the `LatLng`.\r\n\ttoBounds: function (sizeInMeters) {\r\n\t\tvar latAccuracy = 180 * sizeInMeters / 40075017,\r\n\t\t lngAccuracy = latAccuracy / Math.cos((Math.PI / 180) * this.lat);\r\n\r\n\t\treturn toLatLngBounds(\r\n\t\t [this.lat - latAccuracy, this.lng - lngAccuracy],\r\n\t\t [this.lat + latAccuracy, this.lng + lngAccuracy]);\r\n\t},\r\n\r\n\tclone: function () {\r\n\t\treturn new LatLng(this.lat, this.lng, this.alt);\r\n\t}\r\n};\r\n\r\n\r\n\r\n// @factory L.latLng(latitude: Number, longitude: Number, altitude?: Number): LatLng\r\n// Creates an object representing a geographical point with the given latitude and longitude (and optionally altitude).\r\n\r\n// @alternative\r\n// @factory L.latLng(coords: Array): LatLng\r\n// Expects an array of the form `[Number, Number]` or `[Number, Number, Number]` instead.\r\n\r\n// @alternative\r\n// @factory L.latLng(coords: Object): LatLng\r\n// Expects an plain object of the form `{lat: Number, lng: Number}` or `{lat: Number, lng: Number, alt: Number}` instead.\r\n\r\nexport function toLatLng(a, b, c) {\r\n\tif (a instanceof LatLng) {\r\n\t\treturn a;\r\n\t}\r\n\tif (Util.isArray(a) && typeof a[0] !== 'object') {\r\n\t\tif (a.length === 3) {\r\n\t\t\treturn new LatLng(a[0], a[1], a[2]);\r\n\t\t}\r\n\t\tif (a.length === 2) {\r\n\t\t\treturn new LatLng(a[0], a[1]);\r\n\t\t}\r\n\t\treturn null;\r\n\t}\r\n\tif (a === undefined || a === null) {\r\n\t\treturn a;\r\n\t}\r\n\tif (typeof a === 'object' && 'lat' in a) {\r\n\t\treturn new LatLng(a.lat, 'lng' in a ? a.lng : a.lon, a.alt);\r\n\t}\r\n\tif (b === undefined) {\r\n\t\treturn null;\r\n\t}\r\n\treturn new LatLng(a, b, c);\r\n}\r\n","\r\nimport {Bounds} from '../../geometry/Bounds';\r\nimport {LatLng} from '../LatLng';\r\nimport {LatLngBounds} from '../LatLngBounds';\r\nimport * as Util from '../../core/Util';\r\n\r\n/*\r\n * @namespace CRS\r\n * @crs L.CRS.Base\r\n * Object that defines coordinate reference systems for projecting\r\n * geographical points into pixel (screen) coordinates and back (and to\r\n * coordinates in other units for [WMS](https://en.wikipedia.org/wiki/Web_Map_Service) services). See\r\n * [spatial reference system](http://en.wikipedia.org/wiki/Coordinate_reference_system).\r\n *\r\n * Leaflet defines the most usual CRSs by default. If you want to use a\r\n * CRS not defined by default, take a look at the\r\n * [Proj4Leaflet](https://github.com/kartena/Proj4Leaflet) plugin.\r\n *\r\n * Note that the CRS instances do not inherit from Leafet's `Class` object,\r\n * and can't be instantiated. Also, new classes can't inherit from them,\r\n * and methods can't be added to them with the `include` function.\r\n */\r\n\r\nexport var CRS = {\r\n\t// @method latLngToPoint(latlng: LatLng, zoom: Number): Point\r\n\t// Projects geographical coordinates into pixel coordinates for a given zoom.\r\n\tlatLngToPoint: function (latlng, zoom) {\r\n\t\tvar projectedPoint = this.projection.project(latlng),\r\n\t\t scale = this.scale(zoom);\r\n\r\n\t\treturn this.transformation._transform(projectedPoint, scale);\r\n\t},\r\n\r\n\t// @method pointToLatLng(point: Point, zoom: Number): LatLng\r\n\t// The inverse of `latLngToPoint`. Projects pixel coordinates on a given\r\n\t// zoom into geographical coordinates.\r\n\tpointToLatLng: function (point, zoom) {\r\n\t\tvar scale = this.scale(zoom),\r\n\t\t untransformedPoint = this.transformation.untransform(point, scale);\r\n\r\n\t\treturn this.projection.unproject(untransformedPoint);\r\n\t},\r\n\r\n\t// @method project(latlng: LatLng): Point\r\n\t// Projects geographical coordinates into coordinates in units accepted for\r\n\t// this CRS (e.g. meters for EPSG:3857, for passing it to WMS services).\r\n\tproject: function (latlng) {\r\n\t\treturn this.projection.project(latlng);\r\n\t},\r\n\r\n\t// @method unproject(point: Point): LatLng\r\n\t// Given a projected coordinate returns the corresponding LatLng.\r\n\t// The inverse of `project`.\r\n\tunproject: function (point) {\r\n\t\treturn this.projection.unproject(point);\r\n\t},\r\n\r\n\t// @method scale(zoom: Number): Number\r\n\t// Returns the scale used when transforming projected coordinates into\r\n\t// pixel coordinates for a particular zoom. For example, it returns\r\n\t// `256 * 2^zoom` for Mercator-based CRS.\r\n\tscale: function (zoom) {\r\n\t\treturn 256 * Math.pow(2, zoom);\r\n\t},\r\n\r\n\t// @method zoom(scale: Number): Number\r\n\t// Inverse of `scale()`, returns the zoom level corresponding to a scale\r\n\t// factor of `scale`.\r\n\tzoom: function (scale) {\r\n\t\treturn Math.log(scale / 256) / Math.LN2;\r\n\t},\r\n\r\n\t// @method getProjectedBounds(zoom: Number): Bounds\r\n\t// Returns the projection's bounds scaled and transformed for the provided `zoom`.\r\n\tgetProjectedBounds: function (zoom) {\r\n\t\tif (this.infinite) { return null; }\r\n\r\n\t\tvar b = this.projection.bounds,\r\n\t\t s = this.scale(zoom),\r\n\t\t min = this.transformation.transform(b.min, s),\r\n\t\t max = this.transformation.transform(b.max, s);\r\n\r\n\t\treturn new Bounds(min, max);\r\n\t},\r\n\r\n\t// @method distance(latlng1: LatLng, latlng2: LatLng): Number\r\n\t// Returns the distance between two geographical coordinates.\r\n\r\n\t// @property code: String\r\n\t// Standard code name of the CRS passed into WMS services (e.g. `'EPSG:3857'`)\r\n\t//\r\n\t// @property wrapLng: Number[]\r\n\t// An array of two numbers defining whether the longitude (horizontal) coordinate\r\n\t// axis wraps around a given range and how. Defaults to `[-180, 180]` in most\r\n\t// geographical CRSs. If `undefined`, the longitude axis does not wrap around.\r\n\t//\r\n\t// @property wrapLat: Number[]\r\n\t// Like `wrapLng`, but for the latitude (vertical) axis.\r\n\r\n\t// wrapLng: [min, max],\r\n\t// wrapLat: [min, max],\r\n\r\n\t// @property infinite: Boolean\r\n\t// If true, the coordinate space will be unbounded (infinite in both axes)\r\n\tinfinite: false,\r\n\r\n\t// @method wrapLatLng(latlng: LatLng): LatLng\r\n\t// Returns a `LatLng` where lat and lng has been wrapped according to the\r\n\t// CRS's `wrapLat` and `wrapLng` properties, if they are outside the CRS's bounds.\r\n\twrapLatLng: function (latlng) {\r\n\t\tvar lng = this.wrapLng ? Util.wrapNum(latlng.lng, this.wrapLng, true) : latlng.lng,\r\n\t\t lat = this.wrapLat ? Util.wrapNum(latlng.lat, this.wrapLat, true) : latlng.lat,\r\n\t\t alt = latlng.alt;\r\n\r\n\t\treturn new LatLng(lat, lng, alt);\r\n\t},\r\n\r\n\t// @method wrapLatLngBounds(bounds: LatLngBounds): LatLngBounds\r\n\t// Returns a `LatLngBounds` with the same size as the given one, ensuring\r\n\t// that its center is within the CRS's bounds.\r\n\t// Only accepts actual `L.LatLngBounds` instances, not arrays.\r\n\twrapLatLngBounds: function (bounds) {\r\n\t\tvar center = bounds.getCenter(),\r\n\t\t newCenter = this.wrapLatLng(center),\r\n\t\t latShift = center.lat - newCenter.lat,\r\n\t\t lngShift = center.lng - newCenter.lng;\r\n\r\n\t\tif (latShift === 0 && lngShift === 0) {\r\n\t\t\treturn bounds;\r\n\t\t}\r\n\r\n\t\tvar sw = bounds.getSouthWest(),\r\n\t\t ne = bounds.getNorthEast(),\r\n\t\t newSw = new LatLng(sw.lat - latShift, sw.lng - lngShift),\r\n\t\t newNe = new LatLng(ne.lat - latShift, ne.lng - lngShift);\r\n\r\n\t\treturn new LatLngBounds(newSw, newNe);\r\n\t}\r\n};\r\n","import {CRS} from './CRS';\nimport * as Util from '../../core/Util';\n\n/*\n * @namespace CRS\n * @crs L.CRS.Earth\n *\n * Serves as the base for CRS that are global such that they cover the earth.\n * Can only be used as the base for other CRS and cannot be used directly,\n * since it does not have a `code`, `projection` or `transformation`. `distance()` returns\n * meters.\n */\n\nexport var Earth = Util.extend({}, CRS, {\n\twrapLng: [-180, 180],\n\n\t// Mean Earth Radius, as recommended for use by\n\t// the International Union of Geodesy and Geophysics,\n\t// see http://rosettacode.org/wiki/Haversine_formula\n\tR: 6371000,\n\n\t// distance between two geographical points using spherical law of cosines approximation\n\tdistance: function (latlng1, latlng2) {\n\t\tvar rad = Math.PI / 180,\n\t\t lat1 = latlng1.lat * rad,\n\t\t lat2 = latlng2.lat * rad,\n\t\t sinDLat = Math.sin((latlng2.lat - latlng1.lat) * rad / 2),\n\t\t sinDLon = Math.sin((latlng2.lng - latlng1.lng) * rad / 2),\n\t\t a = sinDLat * sinDLat + Math.cos(lat1) * Math.cos(lat2) * sinDLon * sinDLon,\n\t\t c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n\t\treturn this.R * c;\n\t}\n});\n","import {LatLng} from '../LatLng';\r\nimport {Bounds} from '../../geometry/Bounds';\r\nimport {Point} from '../../geometry/Point';\r\n\r\n/*\r\n * @namespace Projection\r\n * @projection L.Projection.SphericalMercator\r\n *\r\n * Spherical Mercator projection — the most common projection for online maps,\r\n * used by almost all free and commercial tile providers. Assumes that Earth is\r\n * a sphere. Used by the `EPSG:3857` CRS.\r\n */\r\n\r\nvar earthRadius = 6378137;\r\n\r\nexport var SphericalMercator = {\r\n\r\n\tR: earthRadius,\r\n\tMAX_LATITUDE: 85.0511287798,\r\n\r\n\tproject: function (latlng) {\r\n\t\tvar d = Math.PI / 180,\r\n\t\t max = this.MAX_LATITUDE,\r\n\t\t lat = Math.max(Math.min(max, latlng.lat), -max),\r\n\t\t sin = Math.sin(lat * d);\r\n\r\n\t\treturn new Point(\r\n\t\t\tthis.R * latlng.lng * d,\r\n\t\t\tthis.R * Math.log((1 + sin) / (1 - sin)) / 2);\r\n\t},\r\n\r\n\tunproject: function (point) {\r\n\t\tvar d = 180 / Math.PI;\r\n\r\n\t\treturn new LatLng(\r\n\t\t\t(2 * Math.atan(Math.exp(point.y / this.R)) - (Math.PI / 2)) * d,\r\n\t\t\tpoint.x * d / this.R);\r\n\t},\r\n\r\n\tbounds: (function () {\r\n\t\tvar d = earthRadius * Math.PI;\r\n\t\treturn new Bounds([-d, -d], [d, d]);\r\n\t})()\r\n};\r\n","import {Point} from './Point';\r\nimport * as Util from '../core/Util';\r\n\r\n/*\r\n * @class Transformation\r\n * @aka L.Transformation\r\n *\r\n * Represents an affine transformation: a set of coefficients `a`, `b`, `c`, `d`\r\n * for transforming a point of a form `(x, y)` into `(a*x + b, c*y + d)` and doing\r\n * the reverse. Used by Leaflet in its projections code.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * var transformation = L.transformation(2, 5, -1, 10),\r\n * \tp = L.point(1, 2),\r\n * \tp2 = transformation.transform(p), // L.point(7, 8)\r\n * \tp3 = transformation.untransform(p2); // L.point(1, 2)\r\n * ```\r\n */\r\n\r\n\r\n// factory new L.Transformation(a: Number, b: Number, c: Number, d: Number)\r\n// Creates a `Transformation` object with the given coefficients.\r\nexport function Transformation(a, b, c, d) {\r\n\tif (Util.isArray(a)) {\r\n\t\t// use array properties\r\n\t\tthis._a = a[0];\r\n\t\tthis._b = a[1];\r\n\t\tthis._c = a[2];\r\n\t\tthis._d = a[3];\r\n\t\treturn;\r\n\t}\r\n\tthis._a = a;\r\n\tthis._b = b;\r\n\tthis._c = c;\r\n\tthis._d = d;\r\n}\r\n\r\nTransformation.prototype = {\r\n\t// @method transform(point: Point, scale?: Number): Point\r\n\t// Returns a transformed point, optionally multiplied by the given scale.\r\n\t// Only accepts actual `L.Point` instances, not arrays.\r\n\ttransform: function (point, scale) { // (Point, Number) -> Point\r\n\t\treturn this._transform(point.clone(), scale);\r\n\t},\r\n\r\n\t// destructive transform (faster)\r\n\t_transform: function (point, scale) {\r\n\t\tscale = scale || 1;\r\n\t\tpoint.x = scale * (this._a * point.x + this._b);\r\n\t\tpoint.y = scale * (this._c * point.y + this._d);\r\n\t\treturn point;\r\n\t},\r\n\r\n\t// @method untransform(point: Point, scale?: Number): Point\r\n\t// Returns the reverse transformation of the given point, optionally divided\r\n\t// by the given scale. Only accepts actual `L.Point` instances, not arrays.\r\n\tuntransform: function (point, scale) {\r\n\t\tscale = scale || 1;\r\n\t\treturn new Point(\r\n\t\t (point.x / scale - this._b) / this._a,\r\n\t\t (point.y / scale - this._d) / this._c);\r\n\t}\r\n};\r\n\r\n// factory L.transformation(a: Number, b: Number, c: Number, d: Number)\r\n\r\n// @factory L.transformation(a: Number, b: Number, c: Number, d: Number)\r\n// Instantiates a Transformation object with the given coefficients.\r\n\r\n// @alternative\r\n// @factory L.transformation(coefficients: Array): Transformation\r\n// Expects an coefficients array of the form\r\n// `[a: Number, b: Number, c: Number, d: Number]`.\r\n\r\nexport function toTransformation(a, b, c, d) {\r\n\treturn new Transformation(a, b, c, d);\r\n}\r\n","import {Earth} from './CRS.Earth';\r\nimport {SphericalMercator} from '../projection/Projection.SphericalMercator';\r\nimport {toTransformation} from '../../geometry/Transformation';\r\nimport * as Util from '../../core/Util';\r\n\r\n/*\r\n * @namespace CRS\r\n * @crs L.CRS.EPSG3857\r\n *\r\n * The most common CRS for online maps, used by almost all free and commercial\r\n * tile providers. Uses Spherical Mercator projection. Set in by default in\r\n * Map's `crs` option.\r\n */\r\n\r\nexport var EPSG3857 = Util.extend({}, Earth, {\r\n\tcode: 'EPSG:3857',\r\n\tprojection: SphericalMercator,\r\n\r\n\ttransformation: (function () {\r\n\t\tvar scale = 0.5 / (Math.PI * SphericalMercator.R);\r\n\t\treturn toTransformation(scale, 0.5, -scale, 0.5);\r\n\t}())\r\n});\r\n\r\nexport var EPSG900913 = Util.extend({}, EPSG3857, {\r\n\tcode: 'EPSG:900913'\r\n});\r\n","import * as Browser from '../../core/Browser';\n\n// @namespace SVG; @section\n// There are several static functions which can be called without instantiating L.SVG:\n\n// @function create(name: String): SVGElement\n// Returns a instance of [SVGElement](https://developer.mozilla.org/docs/Web/API/SVGElement),\n// corresponding to the class name passed. For example, using 'line' will return\n// an instance of [SVGLineElement](https://developer.mozilla.org/docs/Web/API/SVGLineElement).\nexport function svgCreate(name) {\n\treturn document.createElementNS('http://www.w3.org/2000/svg', name);\n}\n\n// @function pointsToPath(rings: Point[], closed: Boolean): String\n// Generates a SVG path string for multiple rings, with each ring turning\n// into \"M..L..L..\" instructions\nexport function pointsToPath(rings, closed) {\n\tvar str = '',\n\ti, j, len, len2, points, p;\n\n\tfor (i = 0, len = rings.length; i < len; i++) {\n\t\tpoints = rings[i];\n\n\t\tfor (j = 0, len2 = points.length; j < len2; j++) {\n\t\t\tp = points[j];\n\t\t\tstr += (j ? 'L' : 'M') + p.x + ' ' + p.y;\n\t\t}\n\n\t\t// closes the ring for polygons; \"x\" is VML syntax\n\t\tstr += closed ? (Browser.svg ? 'z' : 'x') : '';\n\t}\n\n\t// SVG complains about empty path strings\n\treturn str || 'M0 0';\n}\n\n\n\n\n","import * as Util from './Util';\r\nimport {svgCreate} from '../layer/vector/SVG.Util';\r\n\r\n/*\r\n * @namespace Browser\r\n * @aka L.Browser\r\n *\r\n * A namespace with static properties for browser/feature detection used by Leaflet internally.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * if (L.Browser.ielt9) {\r\n * alert('Upgrade your browser, dude!');\r\n * }\r\n * ```\r\n */\r\n\r\nvar style = document.documentElement.style;\r\n\r\n// @property ie: Boolean; `true` for all Internet Explorer versions (not Edge).\r\nexport var ie = 'ActiveXObject' in window;\r\n\r\n// @property ielt9: Boolean; `true` for Internet Explorer versions less than 9.\r\nexport var ielt9 = ie && !document.addEventListener;\r\n\r\n// @property edge: Boolean; `true` for the Edge web browser.\r\nexport var edge = 'msLaunchUri' in navigator && !('documentMode' in document);\r\n\r\n// @property webkit: Boolean;\r\n// `true` for webkit-based browsers like Chrome and Safari (including mobile versions).\r\nexport var webkit = userAgentContains('webkit');\r\n\r\n// @property android: Boolean\r\n// `true` for any browser running on an Android platform.\r\nexport var android = userAgentContains('android');\r\n\r\n// @property android23: Boolean; `true` for browsers running on Android 2 or Android 3.\r\nexport var android23 = userAgentContains('android 2') || userAgentContains('android 3');\r\n\r\n/* See https://stackoverflow.com/a/17961266 for details on detecting stock Android */\r\nvar webkitVer = parseInt(/WebKit\\/([0-9]+)|$/.exec(navigator.userAgent)[1], 10); // also matches AppleWebKit\r\n// @property androidStock: Boolean; `true` for the Android stock browser (i.e. not Chrome)\r\nexport var androidStock = android && userAgentContains('Google') && webkitVer < 537 && !('AudioNode' in window);\r\n\r\n// @property opera: Boolean; `true` for the Opera browser\r\nexport var opera = !!window.opera;\r\n\r\n// @property chrome: Boolean; `true` for the Chrome browser.\r\nexport var chrome = userAgentContains('chrome');\r\n\r\n// @property gecko: Boolean; `true` for gecko-based browsers like Firefox.\r\nexport var gecko = userAgentContains('gecko') && !webkit && !opera && !ie;\r\n\r\n// @property safari: Boolean; `true` for the Safari browser.\r\nexport var safari = !chrome && userAgentContains('safari');\r\n\r\nexport var phantom = userAgentContains('phantom');\r\n\r\n// @property opera12: Boolean\r\n// `true` for the Opera browser supporting CSS transforms (version 12 or later).\r\nexport var opera12 = 'OTransition' in style;\r\n\r\n// @property win: Boolean; `true` when the browser is running in a Windows platform\r\nexport var win = navigator.platform.indexOf('Win') === 0;\r\n\r\n// @property ie3d: Boolean; `true` for all Internet Explorer versions supporting CSS transforms.\r\nexport var ie3d = ie && ('transition' in style);\r\n\r\n// @property webkit3d: Boolean; `true` for webkit-based browsers supporting CSS transforms.\r\nexport var webkit3d = ('WebKitCSSMatrix' in window) && ('m11' in new window.WebKitCSSMatrix()) && !android23;\r\n\r\n// @property gecko3d: Boolean; `true` for gecko-based browsers supporting CSS transforms.\r\nexport var gecko3d = 'MozPerspective' in style;\r\n\r\n// @property any3d: Boolean\r\n// `true` for all browsers supporting CSS transforms.\r\nexport var any3d = !window.L_DISABLE_3D && (ie3d || webkit3d || gecko3d) && !opera12 && !phantom;\r\n\r\n// @property mobile: Boolean; `true` for all browsers running in a mobile device.\r\nexport var mobile = typeof orientation !== 'undefined' || userAgentContains('mobile');\r\n\r\n// @property mobileWebkit: Boolean; `true` for all webkit-based browsers in a mobile device.\r\nexport var mobileWebkit = mobile && webkit;\r\n\r\n// @property mobileWebkit3d: Boolean\r\n// `true` for all webkit-based browsers in a mobile device supporting CSS transforms.\r\nexport var mobileWebkit3d = mobile && webkit3d;\r\n\r\n// @property msPointer: Boolean\r\n// `true` for browsers implementing the Microsoft touch events model (notably IE10).\r\nexport var msPointer = !window.PointerEvent && window.MSPointerEvent;\r\n\r\n// @property pointer: Boolean\r\n// `true` for all browsers supporting [pointer events](https://msdn.microsoft.com/en-us/library/dn433244%28v=vs.85%29.aspx).\r\nexport var pointer = !webkit && !!(window.PointerEvent || msPointer);\r\n\r\n// @property touch: Boolean\r\n// `true` for all browsers supporting [touch events](https://developer.mozilla.org/docs/Web/API/Touch_events).\r\n// This does not necessarily mean that the browser is running in a computer with\r\n// a touchscreen, it only means that the browser is capable of understanding\r\n// touch events.\r\nexport var touch = !window.L_NO_TOUCH && (pointer || 'ontouchstart' in window ||\r\n\t\t(window.DocumentTouch && document instanceof window.DocumentTouch));\r\n\r\n// @property mobileOpera: Boolean; `true` for the Opera browser in a mobile device.\r\nexport var mobileOpera = mobile && opera;\r\n\r\n// @property mobileGecko: Boolean\r\n// `true` for gecko-based browsers running in a mobile device.\r\nexport var mobileGecko = mobile && gecko;\r\n\r\n// @property retina: Boolean\r\n// `true` for browsers on a high-resolution \"retina\" screen or on any screen when browser's display zoom is more than 100%.\r\nexport var retina = (window.devicePixelRatio || (window.screen.deviceXDPI / window.screen.logicalXDPI)) > 1;\r\n\r\n// @property passiveEvents: Boolean\r\n// `true` for browsers that support passive events.\r\nexport var passiveEvents = (function () {\r\n\tvar supportsPassiveOption = false;\r\n\ttry {\r\n\t\tvar opts = Object.defineProperty({}, 'passive', {\r\n\t\t\tget: function () {\r\n\t\t\t\tsupportsPassiveOption = true;\r\n\t\t\t}\r\n\t\t});\r\n\t\twindow.addEventListener('testPassiveEventSupport', Util.falseFn, opts);\r\n\t\twindow.removeEventListener('testPassiveEventSupport', Util.falseFn, opts);\r\n\t} catch (e) {\r\n\t\t// Errors can safely be ignored since this is only a browser support test.\r\n\t}\r\n\treturn supportsPassiveOption;\r\n});\r\n\r\n// @property canvas: Boolean\r\n// `true` when the browser supports [``](https://developer.mozilla.org/docs/Web/API/Canvas_API).\r\nexport var canvas = (function () {\r\n\treturn !!document.createElement('canvas').getContext;\r\n}());\r\n\r\n// @property svg: Boolean\r\n// `true` when the browser supports [SVG](https://developer.mozilla.org/docs/Web/SVG).\r\nexport var svg = !!(document.createElementNS && svgCreate('svg').createSVGRect);\r\n\r\n// @property vml: Boolean\r\n// `true` if the browser supports [VML](https://en.wikipedia.org/wiki/Vector_Markup_Language).\r\nexport var vml = !svg && (function () {\r\n\ttry {\r\n\t\tvar div = document.createElement('div');\r\n\t\tdiv.innerHTML = '';\r\n\r\n\t\tvar shape = div.firstChild;\r\n\t\tshape.style.behavior = 'url(#default#VML)';\r\n\r\n\t\treturn shape && (typeof shape.adj === 'object');\r\n\r\n\t} catch (e) {\r\n\t\treturn false;\r\n\t}\r\n}());\r\n\r\n\r\nfunction userAgentContains(str) {\r\n\treturn navigator.userAgent.toLowerCase().indexOf(str) >= 0;\r\n}\r\n","import * as DomEvent from './DomEvent';\nimport * as Util from '../core/Util';\nimport * as Browser from '../core/Browser';\n\n/*\n * Extends L.DomEvent to provide touch support for Internet Explorer and Windows-based devices.\n */\n\n\nvar POINTER_DOWN = Browser.msPointer ? 'MSPointerDown' : 'pointerdown';\nvar POINTER_MOVE = Browser.msPointer ? 'MSPointerMove' : 'pointermove';\nvar POINTER_UP = Browser.msPointer ? 'MSPointerUp' : 'pointerup';\nvar POINTER_CANCEL = Browser.msPointer ? 'MSPointerCancel' : 'pointercancel';\nvar TAG_WHITE_LIST = ['INPUT', 'SELECT', 'OPTION'];\n\nvar _pointers = {};\nvar _pointerDocListener = false;\n\n// DomEvent.DoubleTap needs to know about this\nexport var _pointersCount = 0;\n\n// Provides a touch events wrapper for (ms)pointer events.\n// ref http://www.w3.org/TR/pointerevents/ https://www.w3.org/Bugs/Public/show_bug.cgi?id=22890\n\nexport function addPointerListener(obj, type, handler, id) {\n\tif (type === 'touchstart') {\n\t\t_addPointerStart(obj, handler, id);\n\n\t} else if (type === 'touchmove') {\n\t\t_addPointerMove(obj, handler, id);\n\n\t} else if (type === 'touchend') {\n\t\t_addPointerEnd(obj, handler, id);\n\t}\n\n\treturn this;\n}\n\nexport function removePointerListener(obj, type, id) {\n\tvar handler = obj['_leaflet_' + type + id];\n\n\tif (type === 'touchstart') {\n\t\tobj.removeEventListener(POINTER_DOWN, handler, false);\n\n\t} else if (type === 'touchmove') {\n\t\tobj.removeEventListener(POINTER_MOVE, handler, false);\n\n\t} else if (type === 'touchend') {\n\t\tobj.removeEventListener(POINTER_UP, handler, false);\n\t\tobj.removeEventListener(POINTER_CANCEL, handler, false);\n\t}\n\n\treturn this;\n}\n\nfunction _addPointerStart(obj, handler, id) {\n\tvar onDown = Util.bind(function (e) {\n\t\tif (e.pointerType !== 'mouse' && e.MSPOINTER_TYPE_MOUSE && e.pointerType !== e.MSPOINTER_TYPE_MOUSE) {\n\t\t\t// In IE11, some touch events needs to fire for form controls, or\n\t\t\t// the controls will stop working. We keep a whitelist of tag names that\n\t\t\t// need these events. For other target tags, we prevent default on the event.\n\t\t\tif (TAG_WHITE_LIST.indexOf(e.target.tagName) < 0) {\n\t\t\t\tDomEvent.preventDefault(e);\n\t\t\t} else {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t_handlePointer(e, handler);\n\t});\n\n\tobj['_leaflet_touchstart' + id] = onDown;\n\tobj.addEventListener(POINTER_DOWN, onDown, false);\n\n\t// need to keep track of what pointers and how many are active to provide e.touches emulation\n\tif (!_pointerDocListener) {\n\t\t// we listen documentElement as any drags that end by moving the touch off the screen get fired there\n\t\tdocument.documentElement.addEventListener(POINTER_DOWN, _globalPointerDown, true);\n\t\tdocument.documentElement.addEventListener(POINTER_MOVE, _globalPointerMove, true);\n\t\tdocument.documentElement.addEventListener(POINTER_UP, _globalPointerUp, true);\n\t\tdocument.documentElement.addEventListener(POINTER_CANCEL, _globalPointerUp, true);\n\n\t\t_pointerDocListener = true;\n\t}\n}\n\nfunction _globalPointerDown(e) {\n\t_pointers[e.pointerId] = e;\n\t_pointersCount++;\n}\n\nfunction _globalPointerMove(e) {\n\tif (_pointers[e.pointerId]) {\n\t\t_pointers[e.pointerId] = e;\n\t}\n}\n\nfunction _globalPointerUp(e) {\n\tdelete _pointers[e.pointerId];\n\t_pointersCount--;\n}\n\nfunction _handlePointer(e, handler) {\n\te.touches = [];\n\tfor (var i in _pointers) {\n\t\te.touches.push(_pointers[i]);\n\t}\n\te.changedTouches = [e];\n\n\thandler(e);\n}\n\nfunction _addPointerMove(obj, handler, id) {\n\tvar onMove = function (e) {\n\t\t// don't fire touch moves when mouse isn't down\n\t\tif ((e.pointerType === e.MSPOINTER_TYPE_MOUSE || e.pointerType === 'mouse') && e.buttons === 0) { return; }\n\n\t\t_handlePointer(e, handler);\n\t};\n\n\tobj['_leaflet_touchmove' + id] = onMove;\n\tobj.addEventListener(POINTER_MOVE, onMove, false);\n}\n\nfunction _addPointerEnd(obj, handler, id) {\n\tvar onUp = function (e) {\n\t\t_handlePointer(e, handler);\n\t};\n\n\tobj['_leaflet_touchend' + id] = onUp;\n\tobj.addEventListener(POINTER_UP, onUp, false);\n\tobj.addEventListener(POINTER_CANCEL, onUp, false);\n}\n\n","import * as Browser from '../core/Browser';\r\nimport {_pointersCount} from './DomEvent.Pointer';\r\n\r\n/*\r\n * Extends the event handling code with double tap support for mobile browsers.\r\n */\r\n\r\nvar _touchstart = Browser.msPointer ? 'MSPointerDown' : Browser.pointer ? 'pointerdown' : 'touchstart';\r\nvar _touchend = Browser.msPointer ? 'MSPointerUp' : Browser.pointer ? 'pointerup' : 'touchend';\r\nvar _pre = '_leaflet_';\r\n\r\n// inspired by Zepto touch code by Thomas Fuchs\r\nexport function addDoubleTapListener(obj, handler, id) {\r\n\tvar last, touch,\r\n\t doubleTap = false,\r\n\t delay = 250;\r\n\r\n\tfunction onTouchStart(e) {\r\n\t\tvar count;\r\n\r\n\t\tif (Browser.pointer) {\r\n\t\t\tif ((!Browser.edge) || e.pointerType === 'mouse') { return; }\r\n\t\t\tcount = _pointersCount;\r\n\t\t} else {\r\n\t\t\tcount = e.touches.length;\r\n\t\t}\r\n\r\n\t\tif (count > 1) { return; }\r\n\r\n\t\tvar now = Date.now(),\r\n\t\t delta = now - (last || now);\r\n\r\n\t\ttouch = e.touches ? e.touches[0] : e;\r\n\t\tdoubleTap = (delta > 0 && delta <= delay);\r\n\t\tlast = now;\r\n\t}\r\n\r\n\tfunction onTouchEnd(e) {\r\n\t\tif (doubleTap && !touch.cancelBubble) {\r\n\t\t\tif (Browser.pointer) {\r\n\t\t\t\tif ((!Browser.edge) || e.pointerType === 'mouse') { return; }\r\n\t\t\t\t// work around .type being readonly with MSPointer* events\r\n\t\t\t\tvar newTouch = {},\r\n\t\t\t\t prop, i;\r\n\r\n\t\t\t\tfor (i in touch) {\r\n\t\t\t\t\tprop = touch[i];\r\n\t\t\t\t\tnewTouch[i] = prop && prop.bind ? prop.bind(touch) : prop;\r\n\t\t\t\t}\r\n\t\t\t\ttouch = newTouch;\r\n\t\t\t}\r\n\t\t\ttouch.type = 'dblclick';\r\n\t\t\ttouch.button = 0;\r\n\t\t\thandler(touch);\r\n\t\t\tlast = null;\r\n\t\t}\r\n\t}\r\n\r\n\tobj[_pre + _touchstart + id] = onTouchStart;\r\n\tobj[_pre + _touchend + id] = onTouchEnd;\r\n\tobj[_pre + 'dblclick' + id] = handler;\r\n\r\n\tobj.addEventListener(_touchstart, onTouchStart, Browser.passiveEvents ? {passive: false} : false);\r\n\tobj.addEventListener(_touchend, onTouchEnd, Browser.passiveEvents ? {passive: false} : false);\r\n\r\n\t// On some platforms (notably, chrome<55 on win10 + touchscreen + mouse),\r\n\t// the browser doesn't fire touchend/pointerup events but does fire\r\n\t// native dblclicks. See #4127.\r\n\t// Edge 14 also fires native dblclicks, but only for pointerType mouse, see #5180.\r\n\tobj.addEventListener('dblclick', handler, false);\r\n\r\n\treturn this;\r\n}\r\n\r\nexport function removeDoubleTapListener(obj, id) {\r\n\tvar touchstart = obj[_pre + _touchstart + id],\r\n\t touchend = obj[_pre + _touchend + id],\r\n\t dblclick = obj[_pre + 'dblclick' + id];\r\n\r\n\tobj.removeEventListener(_touchstart, touchstart, Browser.passiveEvents ? {passive: false} : false);\r\n\tobj.removeEventListener(_touchend, touchend, Browser.passiveEvents ? {passive: false} : false);\r\n\tif (!Browser.edge) {\r\n\t\tobj.removeEventListener('dblclick', dblclick, false);\r\n\t}\r\n\r\n\treturn this;\r\n}\r\n","import * as DomEvent from './DomEvent';\r\nimport * as Util from '../core/Util';\r\nimport {Point} from '../geometry/Point';\r\nimport * as Browser from '../core/Browser';\r\n\r\n/*\r\n * @namespace DomUtil\r\n *\r\n * Utility functions to work with the [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model)\r\n * tree, used by Leaflet internally.\r\n *\r\n * Most functions expecting or returning a `HTMLElement` also work for\r\n * SVG elements. The only difference is that classes refer to CSS classes\r\n * in HTML and SVG classes in SVG.\r\n */\r\n\r\n\r\n// @property TRANSFORM: String\r\n// Vendor-prefixed transform style name (e.g. `'webkitTransform'` for WebKit).\r\nexport var TRANSFORM = testProp(\r\n\t['transform', 'webkitTransform', 'OTransform', 'MozTransform', 'msTransform']);\r\n\r\n// webkitTransition comes first because some browser versions that drop vendor prefix don't do\r\n// the same for the transitionend event, in particular the Android 4.1 stock browser\r\n\r\n// @property TRANSITION: String\r\n// Vendor-prefixed transition style name.\r\nexport var TRANSITION = testProp(\r\n\t['webkitTransition', 'transition', 'OTransition', 'MozTransition', 'msTransition']);\r\n\r\n// @property TRANSITION_END: String\r\n// Vendor-prefixed transitionend event name.\r\nexport var TRANSITION_END =\r\n\tTRANSITION === 'webkitTransition' || TRANSITION === 'OTransition' ? TRANSITION + 'End' : 'transitionend';\r\n\r\n\r\n// @function get(id: String|HTMLElement): HTMLElement\r\n// Returns an element given its DOM id, or returns the element itself\r\n// if it was passed directly.\r\nexport function get(id) {\r\n\treturn typeof id === 'string' ? document.getElementById(id) : id;\r\n}\r\n\r\n// @function getStyle(el: HTMLElement, styleAttrib: String): String\r\n// Returns the value for a certain style attribute on an element,\r\n// including computed values or values set through CSS.\r\nexport function getStyle(el, style) {\r\n\tvar value = el.style[style] || (el.currentStyle && el.currentStyle[style]);\r\n\r\n\tif ((!value || value === 'auto') && document.defaultView) {\r\n\t\tvar css = document.defaultView.getComputedStyle(el, null);\r\n\t\tvalue = css ? css[style] : null;\r\n\t}\r\n\treturn value === 'auto' ? null : value;\r\n}\r\n\r\n// @function create(tagName: String, className?: String, container?: HTMLElement): HTMLElement\r\n// Creates an HTML element with `tagName`, sets its class to `className`, and optionally appends it to `container` element.\r\nexport function create(tagName, className, container) {\r\n\tvar el = document.createElement(tagName);\r\n\tel.className = className || '';\r\n\r\n\tif (container) {\r\n\t\tcontainer.appendChild(el);\r\n\t}\r\n\treturn el;\r\n}\r\n\r\n// @function remove(el: HTMLElement)\r\n// Removes `el` from its parent element\r\nexport function remove(el) {\r\n\tvar parent = el.parentNode;\r\n\tif (parent) {\r\n\t\tparent.removeChild(el);\r\n\t}\r\n}\r\n\r\n// @function empty(el: HTMLElement)\r\n// Removes all of `el`'s children elements from `el`\r\nexport function empty(el) {\r\n\twhile (el.firstChild) {\r\n\t\tel.removeChild(el.firstChild);\r\n\t}\r\n}\r\n\r\n// @function toFront(el: HTMLElement)\r\n// Makes `el` the last child of its parent, so it renders in front of the other children.\r\nexport function toFront(el) {\r\n\tvar parent = el.parentNode;\r\n\tif (parent && parent.lastChild !== el) {\r\n\t\tparent.appendChild(el);\r\n\t}\r\n}\r\n\r\n// @function toBack(el: HTMLElement)\r\n// Makes `el` the first child of its parent, so it renders behind the other children.\r\nexport function toBack(el) {\r\n\tvar parent = el.parentNode;\r\n\tif (parent && parent.firstChild !== el) {\r\n\t\tparent.insertBefore(el, parent.firstChild);\r\n\t}\r\n}\r\n\r\n// @function hasClass(el: HTMLElement, name: String): Boolean\r\n// Returns `true` if the element's class attribute contains `name`.\r\nexport function hasClass(el, name) {\r\n\tif (el.classList !== undefined) {\r\n\t\treturn el.classList.contains(name);\r\n\t}\r\n\tvar className = getClass(el);\r\n\treturn className.length > 0 && new RegExp('(^|\\\\s)' + name + '(\\\\s|$)').test(className);\r\n}\r\n\r\n// @function addClass(el: HTMLElement, name: String)\r\n// Adds `name` to the element's class attribute.\r\nexport function addClass(el, name) {\r\n\tif (el.classList !== undefined) {\r\n\t\tvar classes = Util.splitWords(name);\r\n\t\tfor (var i = 0, len = classes.length; i < len; i++) {\r\n\t\t\tel.classList.add(classes[i]);\r\n\t\t}\r\n\t} else if (!hasClass(el, name)) {\r\n\t\tvar className = getClass(el);\r\n\t\tsetClass(el, (className ? className + ' ' : '') + name);\r\n\t}\r\n}\r\n\r\n// @function removeClass(el: HTMLElement, name: String)\r\n// Removes `name` from the element's class attribute.\r\nexport function removeClass(el, name) {\r\n\tif (el.classList !== undefined) {\r\n\t\tel.classList.remove(name);\r\n\t} else {\r\n\t\tsetClass(el, Util.trim((' ' + getClass(el) + ' ').replace(' ' + name + ' ', ' ')));\r\n\t}\r\n}\r\n\r\n// @function setClass(el: HTMLElement, name: String)\r\n// Sets the element's class.\r\nexport function setClass(el, name) {\r\n\tif (el.className.baseVal === undefined) {\r\n\t\tel.className = name;\r\n\t} else {\r\n\t\t// in case of SVG element\r\n\t\tel.className.baseVal = name;\r\n\t}\r\n}\r\n\r\n// @function getClass(el: HTMLElement): String\r\n// Returns the element's class.\r\nexport function getClass(el) {\r\n\t// Check if the element is an SVGElementInstance and use the correspondingElement instead\r\n\t// (Required for linked SVG elements in IE11.)\r\n\tif (el.correspondingElement) {\r\n\t\tel = el.correspondingElement;\r\n\t}\r\n\treturn el.className.baseVal === undefined ? el.className : el.className.baseVal;\r\n}\r\n\r\n// @function setOpacity(el: HTMLElement, opacity: Number)\r\n// Set the opacity of an element (including old IE support).\r\n// `opacity` must be a number from `0` to `1`.\r\nexport function setOpacity(el, value) {\r\n\tif ('opacity' in el.style) {\r\n\t\tel.style.opacity = value;\r\n\t} else if ('filter' in el.style) {\r\n\t\t_setOpacityIE(el, value);\r\n\t}\r\n}\r\n\r\nfunction _setOpacityIE(el, value) {\r\n\tvar filter = false,\r\n\t filterName = 'DXImageTransform.Microsoft.Alpha';\r\n\r\n\t// filters collection throws an error if we try to retrieve a filter that doesn't exist\r\n\ttry {\r\n\t\tfilter = el.filters.item(filterName);\r\n\t} catch (e) {\r\n\t\t// don't set opacity to 1 if we haven't already set an opacity,\r\n\t\t// it isn't needed and breaks transparent pngs.\r\n\t\tif (value === 1) { return; }\r\n\t}\r\n\r\n\tvalue = Math.round(value * 100);\r\n\r\n\tif (filter) {\r\n\t\tfilter.Enabled = (value !== 100);\r\n\t\tfilter.Opacity = value;\r\n\t} else {\r\n\t\tel.style.filter += ' progid:' + filterName + '(opacity=' + value + ')';\r\n\t}\r\n}\r\n\r\n// @function testProp(props: String[]): String|false\r\n// Goes through the array of style names and returns the first name\r\n// that is a valid style name for an element. If no such name is found,\r\n// it returns false. Useful for vendor-prefixed styles like `transform`.\r\nexport function testProp(props) {\r\n\tvar style = document.documentElement.style;\r\n\r\n\tfor (var i = 0; i < props.length; i++) {\r\n\t\tif (props[i] in style) {\r\n\t\t\treturn props[i];\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n// @function setTransform(el: HTMLElement, offset: Point, scale?: Number)\r\n// Resets the 3D CSS transform of `el` so it is translated by `offset` pixels\r\n// and optionally scaled by `scale`. Does not have an effect if the\r\n// browser doesn't support 3D CSS transforms.\r\nexport function setTransform(el, offset, scale) {\r\n\tvar pos = offset || new Point(0, 0);\r\n\r\n\tel.style[TRANSFORM] =\r\n\t\t(Browser.ie3d ?\r\n\t\t\t'translate(' + pos.x + 'px,' + pos.y + 'px)' :\r\n\t\t\t'translate3d(' + pos.x + 'px,' + pos.y + 'px,0)') +\r\n\t\t(scale ? ' scale(' + scale + ')' : '');\r\n}\r\n\r\n// @function setPosition(el: HTMLElement, position: Point)\r\n// Sets the position of `el` to coordinates specified by `position`,\r\n// using CSS translate or top/left positioning depending on the browser\r\n// (used by Leaflet internally to position its layers).\r\nexport function setPosition(el, point) {\r\n\r\n\t/*eslint-disable */\r\n\tel._leaflet_pos = point;\r\n\t/* eslint-enable */\r\n\r\n\tif (Browser.any3d) {\r\n\t\tsetTransform(el, point);\r\n\t} else {\r\n\t\tel.style.left = point.x + 'px';\r\n\t\tel.style.top = point.y + 'px';\r\n\t}\r\n}\r\n\r\n// @function getPosition(el: HTMLElement): Point\r\n// Returns the coordinates of an element previously positioned with setPosition.\r\nexport function getPosition(el) {\r\n\t// this method is only used for elements previously positioned using setPosition,\r\n\t// so it's safe to cache the position for performance\r\n\r\n\treturn el._leaflet_pos || new Point(0, 0);\r\n}\r\n\r\n// @function disableTextSelection()\r\n// Prevents the user from generating `selectstart` DOM events, usually generated\r\n// when the user drags the mouse through a page with text. Used internally\r\n// by Leaflet to override the behaviour of any click-and-drag interaction on\r\n// the map. Affects drag interactions on the whole document.\r\n\r\n// @function enableTextSelection()\r\n// Cancels the effects of a previous [`L.DomUtil.disableTextSelection`](#domutil-disabletextselection).\r\nexport var disableTextSelection;\r\nexport var enableTextSelection;\r\nvar _userSelect;\r\nif ('onselectstart' in document) {\r\n\tdisableTextSelection = function () {\r\n\t\tDomEvent.on(window, 'selectstart', DomEvent.preventDefault);\r\n\t};\r\n\tenableTextSelection = function () {\r\n\t\tDomEvent.off(window, 'selectstart', DomEvent.preventDefault);\r\n\t};\r\n} else {\r\n\tvar userSelectProperty = testProp(\r\n\t\t['userSelect', 'WebkitUserSelect', 'OUserSelect', 'MozUserSelect', 'msUserSelect']);\r\n\r\n\tdisableTextSelection = function () {\r\n\t\tif (userSelectProperty) {\r\n\t\t\tvar style = document.documentElement.style;\r\n\t\t\t_userSelect = style[userSelectProperty];\r\n\t\t\tstyle[userSelectProperty] = 'none';\r\n\t\t}\r\n\t};\r\n\tenableTextSelection = function () {\r\n\t\tif (userSelectProperty) {\r\n\t\t\tdocument.documentElement.style[userSelectProperty] = _userSelect;\r\n\t\t\t_userSelect = undefined;\r\n\t\t}\r\n\t};\r\n}\r\n\r\n// @function disableImageDrag()\r\n// As [`L.DomUtil.disableTextSelection`](#domutil-disabletextselection), but\r\n// for `dragstart` DOM events, usually generated when the user drags an image.\r\nexport function disableImageDrag() {\r\n\tDomEvent.on(window, 'dragstart', DomEvent.preventDefault);\r\n}\r\n\r\n// @function enableImageDrag()\r\n// Cancels the effects of a previous [`L.DomUtil.disableImageDrag`](#domutil-disabletextselection).\r\nexport function enableImageDrag() {\r\n\tDomEvent.off(window, 'dragstart', DomEvent.preventDefault);\r\n}\r\n\r\nvar _outlineElement, _outlineStyle;\r\n// @function preventOutline(el: HTMLElement)\r\n// Makes the [outline](https://developer.mozilla.org/docs/Web/CSS/outline)\r\n// of the element `el` invisible. Used internally by Leaflet to prevent\r\n// focusable elements from displaying an outline when the user performs a\r\n// drag interaction on them.\r\nexport function preventOutline(element) {\r\n\twhile (element.tabIndex === -1) {\r\n\t\telement = element.parentNode;\r\n\t}\r\n\tif (!element.style) { return; }\r\n\trestoreOutline();\r\n\t_outlineElement = element;\r\n\t_outlineStyle = element.style.outline;\r\n\telement.style.outline = 'none';\r\n\tDomEvent.on(window, 'keydown', restoreOutline);\r\n}\r\n\r\n// @function restoreOutline()\r\n// Cancels the effects of a previous [`L.DomUtil.preventOutline`]().\r\nexport function restoreOutline() {\r\n\tif (!_outlineElement) { return; }\r\n\t_outlineElement.style.outline = _outlineStyle;\r\n\t_outlineElement = undefined;\r\n\t_outlineStyle = undefined;\r\n\tDomEvent.off(window, 'keydown', restoreOutline);\r\n}\r\n\r\n// @function getSizedParentNode(el: HTMLElement): HTMLElement\r\n// Finds the closest parent node which size (width and height) is not null.\r\nexport function getSizedParentNode(element) {\r\n\tdo {\r\n\t\telement = element.parentNode;\r\n\t} while ((!element.offsetWidth || !element.offsetHeight) && element !== document.body);\r\n\treturn element;\r\n}\r\n\r\n// @function getScale(el: HTMLElement): Object\r\n// Computes the CSS scale currently applied on the element.\r\n// Returns an object with `x` and `y` members as horizontal and vertical scales respectively,\r\n// and `boundingClientRect` as the result of [`getBoundingClientRect()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect).\r\nexport function getScale(element) {\r\n\tvar rect = element.getBoundingClientRect(); // Read-only in old browsers.\r\n\r\n\treturn {\r\n\t\tx: rect.width / element.offsetWidth || 1,\r\n\t\ty: rect.height / element.offsetHeight || 1,\r\n\t\tboundingClientRect: rect\r\n\t};\r\n}\r\n","import {Point} from '../geometry/Point';\r\nimport * as Util from '../core/Util';\r\nimport * as Browser from '../core/Browser';\r\nimport {addPointerListener, removePointerListener} from './DomEvent.Pointer';\r\nimport {addDoubleTapListener, removeDoubleTapListener} from './DomEvent.DoubleTap';\r\nimport {getScale} from './DomUtil';\r\n\r\n/*\r\n * @namespace DomEvent\r\n * Utility functions to work with the [DOM events](https://developer.mozilla.org/docs/Web/API/Event), used by Leaflet internally.\r\n */\r\n\r\n// Inspired by John Resig, Dean Edwards and YUI addEvent implementations.\r\n\r\n// @function on(el: HTMLElement, types: String, fn: Function, context?: Object): this\r\n// Adds a listener function (`fn`) to a particular DOM event type of the\r\n// element `el`. You can optionally specify the context of the listener\r\n// (object the `this` keyword will point to). You can also pass several\r\n// space-separated types (e.g. `'click dblclick'`).\r\n\r\n// @alternative\r\n// @function on(el: HTMLElement, eventMap: Object, context?: Object): this\r\n// Adds a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}`\r\nexport function on(obj, types, fn, context) {\r\n\r\n\tif (typeof types === 'object') {\r\n\t\tfor (var type in types) {\r\n\t\t\taddOne(obj, type, types[type], fn);\r\n\t\t}\r\n\t} else {\r\n\t\ttypes = Util.splitWords(types);\r\n\r\n\t\tfor (var i = 0, len = types.length; i < len; i++) {\r\n\t\t\taddOne(obj, types[i], fn, context);\r\n\t\t}\r\n\t}\r\n\r\n\treturn this;\r\n}\r\n\r\nvar eventsKey = '_leaflet_events';\r\n\r\n// @function off(el: HTMLElement, types: String, fn: Function, context?: Object): this\r\n// Removes a previously added listener function.\r\n// Note that if you passed a custom context to on, you must pass the same\r\n// context to `off` in order to remove the listener.\r\n\r\n// @alternative\r\n// @function off(el: HTMLElement, eventMap: Object, context?: Object): this\r\n// Removes a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}`\r\nexport function off(obj, types, fn, context) {\r\n\r\n\tif (typeof types === 'object') {\r\n\t\tfor (var type in types) {\r\n\t\t\tremoveOne(obj, type, types[type], fn);\r\n\t\t}\r\n\t} else if (types) {\r\n\t\ttypes = Util.splitWords(types);\r\n\r\n\t\tfor (var i = 0, len = types.length; i < len; i++) {\r\n\t\t\tremoveOne(obj, types[i], fn, context);\r\n\t\t}\r\n\t} else {\r\n\t\tfor (var j in obj[eventsKey]) {\r\n\t\t\tremoveOne(obj, j, obj[eventsKey][j]);\r\n\t\t}\r\n\t\tdelete obj[eventsKey];\r\n\t}\r\n\r\n\treturn this;\r\n}\r\n\r\nfunction addOne(obj, type, fn, context) {\r\n\tvar id = type + Util.stamp(fn) + (context ? '_' + Util.stamp(context) : '');\r\n\r\n\tif (obj[eventsKey] && obj[eventsKey][id]) { return this; }\r\n\r\n\tvar handler = function (e) {\r\n\t\treturn fn.call(context || obj, e || window.event);\r\n\t};\r\n\r\n\tvar originalHandler = handler;\r\n\r\n\tif (Browser.pointer && type.indexOf('touch') === 0) {\r\n\t\t// Needs DomEvent.Pointer.js\r\n\t\taddPointerListener(obj, type, handler, id);\r\n\r\n\t} else if (Browser.touch && (type === 'dblclick') && addDoubleTapListener &&\r\n\t !(Browser.pointer && Browser.chrome)) {\r\n\t\t// Chrome >55 does not need the synthetic dblclicks from addDoubleTapListener\r\n\t\t// See #5180\r\n\t\taddDoubleTapListener(obj, handler, id);\r\n\r\n\t} else if ('addEventListener' in obj) {\r\n\r\n\t\tif (type === 'mousewheel') {\r\n\t\t\tobj.addEventListener('onwheel' in obj ? 'wheel' : 'mousewheel', handler, Browser.passiveEvents ? {passive: false} : false);\r\n\r\n\t\t} else if ((type === 'mouseenter') || (type === 'mouseleave')) {\r\n\t\t\thandler = function (e) {\r\n\t\t\t\te = e || window.event;\r\n\t\t\t\tif (isExternalTarget(obj, e)) {\r\n\t\t\t\t\toriginalHandler(e);\r\n\t\t\t\t}\r\n\t\t\t};\r\n\t\t\tobj.addEventListener(type === 'mouseenter' ? 'mouseover' : 'mouseout', handler, false);\r\n\r\n\t\t} else {\r\n\t\t\tif (type === 'click' && Browser.android) {\r\n\t\t\t\thandler = function (e) {\r\n\t\t\t\t\tfilterClick(e, originalHandler);\r\n\t\t\t\t};\r\n\t\t\t}\r\n\t\t\tobj.addEventListener(type, handler, false);\r\n\t\t}\r\n\r\n\t} else if ('attachEvent' in obj) {\r\n\t\tobj.attachEvent('on' + type, handler);\r\n\t}\r\n\r\n\tobj[eventsKey] = obj[eventsKey] || {};\r\n\tobj[eventsKey][id] = handler;\r\n}\r\n\r\nfunction removeOne(obj, type, fn, context) {\r\n\r\n\tvar id = type + Util.stamp(fn) + (context ? '_' + Util.stamp(context) : ''),\r\n\t handler = obj[eventsKey] && obj[eventsKey][id];\r\n\r\n\tif (!handler) { return this; }\r\n\r\n\tif (Browser.pointer && type.indexOf('touch') === 0) {\r\n\t\tremovePointerListener(obj, type, id);\r\n\r\n\t} else if (Browser.touch && (type === 'dblclick') && removeDoubleTapListener &&\r\n\t !(Browser.pointer && Browser.chrome)) {\r\n\t\tremoveDoubleTapListener(obj, id);\r\n\r\n\t} else if ('removeEventListener' in obj) {\r\n\r\n\t\tif (type === 'mousewheel') {\r\n\t\t\tobj.removeEventListener('onwheel' in obj ? 'wheel' : 'mousewheel', handler, Browser.passiveEvents ? {passive: false} : false);\r\n\r\n\t\t} else {\r\n\t\t\tobj.removeEventListener(\r\n\t\t\t\ttype === 'mouseenter' ? 'mouseover' :\r\n\t\t\t\ttype === 'mouseleave' ? 'mouseout' : type, handler, false);\r\n\t\t}\r\n\r\n\t} else if ('detachEvent' in obj) {\r\n\t\tobj.detachEvent('on' + type, handler);\r\n\t}\r\n\r\n\tobj[eventsKey][id] = null;\r\n}\r\n\r\n// @function stopPropagation(ev: DOMEvent): this\r\n// Stop the given event from propagation to parent elements. Used inside the listener functions:\r\n// ```js\r\n// L.DomEvent.on(div, 'click', function (ev) {\r\n// \tL.DomEvent.stopPropagation(ev);\r\n// });\r\n// ```\r\nexport function stopPropagation(e) {\r\n\r\n\tif (e.stopPropagation) {\r\n\t\te.stopPropagation();\r\n\t} else if (e.originalEvent) { // In case of Leaflet event.\r\n\t\te.originalEvent._stopped = true;\r\n\t} else {\r\n\t\te.cancelBubble = true;\r\n\t}\r\n\tskipped(e);\r\n\r\n\treturn this;\r\n}\r\n\r\n// @function disableScrollPropagation(el: HTMLElement): this\r\n// Adds `stopPropagation` to the element's `'mousewheel'` events (plus browser variants).\r\nexport function disableScrollPropagation(el) {\r\n\taddOne(el, 'mousewheel', stopPropagation);\r\n\treturn this;\r\n}\r\n\r\n// @function disableClickPropagation(el: HTMLElement): this\r\n// Adds `stopPropagation` to the element's `'click'`, `'doubleclick'`,\r\n// `'mousedown'` and `'touchstart'` events (plus browser variants).\r\nexport function disableClickPropagation(el) {\r\n\ton(el, 'mousedown touchstart dblclick', stopPropagation);\r\n\taddOne(el, 'click', fakeStop);\r\n\treturn this;\r\n}\r\n\r\n// @function preventDefault(ev: DOMEvent): this\r\n// Prevents the default action of the DOM Event `ev` from happening (such as\r\n// following a link in the href of the a element, or doing a POST request\r\n// with page reload when a `` is submitted).\r\n// Use it inside listener functions.\r\nexport function preventDefault(e) {\r\n\tif (e.preventDefault) {\r\n\t\te.preventDefault();\r\n\t} else {\r\n\t\te.returnValue = false;\r\n\t}\r\n\treturn this;\r\n}\r\n\r\n// @function stop(ev: DOMEvent): this\r\n// Does `stopPropagation` and `preventDefault` at the same time.\r\nexport function stop(e) {\r\n\tpreventDefault(e);\r\n\tstopPropagation(e);\r\n\treturn this;\r\n}\r\n\r\n// @function getMousePosition(ev: DOMEvent, container?: HTMLElement): Point\r\n// Gets normalized mouse position from a DOM event relative to the\r\n// `container` (border excluded) or to the whole page if not specified.\r\nexport function getMousePosition(e, container) {\r\n\tif (!container) {\r\n\t\treturn new Point(e.clientX, e.clientY);\r\n\t}\r\n\r\n\tvar scale = getScale(container),\r\n\t offset = scale.boundingClientRect; // left and top values are in page scale (like the event clientX/Y)\r\n\r\n\treturn new Point(\r\n\t\t// offset.left/top values are in page scale (like clientX/Y),\r\n\t\t// whereas clientLeft/Top (border width) values are the original values (before CSS scale applies).\r\n\t\t(e.clientX - offset.left) / scale.x - container.clientLeft,\r\n\t\t(e.clientY - offset.top) / scale.y - container.clientTop\r\n\t);\r\n}\r\n\r\n// Chrome on Win scrolls double the pixels as in other platforms (see #4538),\r\n// and Firefox scrolls device pixels, not CSS pixels\r\nvar wheelPxFactor =\r\n\t(Browser.win && Browser.chrome) ? 2 * window.devicePixelRatio :\r\n\tBrowser.gecko ? window.devicePixelRatio : 1;\r\n\r\n// @function getWheelDelta(ev: DOMEvent): Number\r\n// Gets normalized wheel delta from a mousewheel DOM event, in vertical\r\n// pixels scrolled (negative if scrolling down).\r\n// Events from pointing devices without precise scrolling are mapped to\r\n// a best guess of 60 pixels.\r\nexport function getWheelDelta(e) {\r\n\treturn (Browser.edge) ? e.wheelDeltaY / 2 : // Don't trust window-geometry-based delta\r\n\t (e.deltaY && e.deltaMode === 0) ? -e.deltaY / wheelPxFactor : // Pixels\r\n\t (e.deltaY && e.deltaMode === 1) ? -e.deltaY * 20 : // Lines\r\n\t (e.deltaY && e.deltaMode === 2) ? -e.deltaY * 60 : // Pages\r\n\t (e.deltaX || e.deltaZ) ? 0 :\t// Skip horizontal/depth wheel events\r\n\t e.wheelDelta ? (e.wheelDeltaY || e.wheelDelta) / 2 : // Legacy IE pixels\r\n\t (e.detail && Math.abs(e.detail) < 32765) ? -e.detail * 20 : // Legacy Moz lines\r\n\t e.detail ? e.detail / -32765 * 60 : // Legacy Moz pages\r\n\t 0;\r\n}\r\n\r\nvar skipEvents = {};\r\n\r\nexport function fakeStop(e) {\r\n\t// fakes stopPropagation by setting a special event flag, checked/reset with skipped(e)\r\n\tskipEvents[e.type] = true;\r\n}\r\n\r\nexport function skipped(e) {\r\n\tvar events = skipEvents[e.type];\r\n\t// reset when checking, as it's only used in map container and propagates outside of the map\r\n\tskipEvents[e.type] = false;\r\n\treturn events;\r\n}\r\n\r\n// check if element really left/entered the event target (for mouseenter/mouseleave)\r\nexport function isExternalTarget(el, e) {\r\n\r\n\tvar related = e.relatedTarget;\r\n\r\n\tif (!related) { return true; }\r\n\r\n\ttry {\r\n\t\twhile (related && (related !== el)) {\r\n\t\t\trelated = related.parentNode;\r\n\t\t}\r\n\t} catch (err) {\r\n\t\treturn false;\r\n\t}\r\n\treturn (related !== el);\r\n}\r\n\r\nvar lastClick;\r\n\r\n// this is a horrible workaround for a bug in Android where a single touch triggers two click events\r\nfunction filterClick(e, handler) {\r\n\tvar timeStamp = (e.timeStamp || (e.originalEvent && e.originalEvent.timeStamp)),\r\n\t elapsed = lastClick && (timeStamp - lastClick);\r\n\r\n\t// are they closer together than 500ms yet more than 100ms?\r\n\t// Android typically triggers them ~300ms apart while multiple listeners\r\n\t// on the same event should be triggered far faster;\r\n\t// or check if click is simulated on the element, and if it is, reject any non-simulated events\r\n\r\n\tif ((elapsed && elapsed > 100 && elapsed < 500) || (e.target._simulatedClick && !e._simulated)) {\r\n\t\tstop(e);\r\n\t\treturn;\r\n\t}\r\n\tlastClick = timeStamp;\r\n\r\n\thandler(e);\r\n}\r\n\r\n// @function addListener(…): this\r\n// Alias to [`L.DomEvent.on`](#domevent-on)\r\nexport {on as addListener};\r\n\r\n// @function removeListener(…): this\r\n// Alias to [`L.DomEvent.off`](#domevent-off)\r\nexport {off as removeListener};\r\n","import * as Util from '../core/Util';\nimport {Evented} from '../core/Events';\nimport * as DomUtil from '../dom/DomUtil';\n\n\n/*\n * @class PosAnimation\n * @aka L.PosAnimation\n * @inherits Evented\n * Used internally for panning animations, utilizing CSS3 Transitions for modern browsers and a timer fallback for IE6-9.\n *\n * @example\n * ```js\n * var fx = new L.PosAnimation();\n * fx.run(el, [300, 500], 0.5);\n * ```\n *\n * @constructor L.PosAnimation()\n * Creates a `PosAnimation` object.\n *\n */\n\nexport var PosAnimation = Evented.extend({\n\n\t// @method run(el: HTMLElement, newPos: Point, duration?: Number, easeLinearity?: Number)\n\t// Run an animation of a given element to a new position, optionally setting\n\t// duration in seconds (`0.25` by default) and easing linearity factor (3rd\n\t// argument of the [cubic bezier curve](http://cubic-bezier.com/#0,0,.5,1),\n\t// `0.5` by default).\n\trun: function (el, newPos, duration, easeLinearity) {\n\t\tthis.stop();\n\n\t\tthis._el = el;\n\t\tthis._inProgress = true;\n\t\tthis._duration = duration || 0.25;\n\t\tthis._easeOutPower = 1 / Math.max(easeLinearity || 0.5, 0.2);\n\n\t\tthis._startPos = DomUtil.getPosition(el);\n\t\tthis._offset = newPos.subtract(this._startPos);\n\t\tthis._startTime = +new Date();\n\n\t\t// @event start: Event\n\t\t// Fired when the animation starts\n\t\tthis.fire('start');\n\n\t\tthis._animate();\n\t},\n\n\t// @method stop()\n\t// Stops the animation (if currently running).\n\tstop: function () {\n\t\tif (!this._inProgress) { return; }\n\n\t\tthis._step(true);\n\t\tthis._complete();\n\t},\n\n\t_animate: function () {\n\t\t// animation loop\n\t\tthis._animId = Util.requestAnimFrame(this._animate, this);\n\t\tthis._step();\n\t},\n\n\t_step: function (round) {\n\t\tvar elapsed = (+new Date()) - this._startTime,\n\t\t duration = this._duration * 1000;\n\n\t\tif (elapsed < duration) {\n\t\t\tthis._runFrame(this._easeOut(elapsed / duration), round);\n\t\t} else {\n\t\t\tthis._runFrame(1);\n\t\t\tthis._complete();\n\t\t}\n\t},\n\n\t_runFrame: function (progress, round) {\n\t\tvar pos = this._startPos.add(this._offset.multiplyBy(progress));\n\t\tif (round) {\n\t\t\tpos._round();\n\t\t}\n\t\tDomUtil.setPosition(this._el, pos);\n\n\t\t// @event step: Event\n\t\t// Fired continuously during the animation.\n\t\tthis.fire('step');\n\t},\n\n\t_complete: function () {\n\t\tUtil.cancelAnimFrame(this._animId);\n\n\t\tthis._inProgress = false;\n\t\t// @event end: Event\n\t\t// Fired when the animation ends.\n\t\tthis.fire('end');\n\t},\n\n\t_easeOut: function (t) {\n\t\treturn 1 - Math.pow(1 - t, this._easeOutPower);\n\t}\n});\n","import * as Util from '../core/Util';\r\nimport {Evented} from '../core/Events';\r\nimport {EPSG3857} from '../geo/crs/CRS.EPSG3857';\r\nimport {Point, toPoint} from '../geometry/Point';\r\nimport {Bounds, toBounds} from '../geometry/Bounds';\r\nimport {LatLng, toLatLng} from '../geo/LatLng';\r\nimport {LatLngBounds, toLatLngBounds} from '../geo/LatLngBounds';\r\nimport * as Browser from '../core/Browser';\r\nimport * as DomEvent from '../dom/DomEvent';\r\nimport * as DomUtil from '../dom/DomUtil';\r\nimport {PosAnimation} from '../dom/PosAnimation';\r\n\r\n/*\r\n * @class Map\r\n * @aka L.Map\r\n * @inherits Evented\r\n *\r\n * The central class of the API — it is used to create a map on a page and manipulate it.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * // initialize the map on the \"map\" div with a given center and zoom\r\n * var map = L.map('map', {\r\n * \tcenter: [51.505, -0.09],\r\n * \tzoom: 13\r\n * });\r\n * ```\r\n *\r\n */\r\n\r\nexport var Map = Evented.extend({\r\n\r\n\toptions: {\r\n\t\t// @section Map State Options\r\n\t\t// @option crs: CRS = L.CRS.EPSG3857\r\n\t\t// The [Coordinate Reference System](#crs) to use. Don't change this if you're not\r\n\t\t// sure what it means.\r\n\t\tcrs: EPSG3857,\r\n\r\n\t\t// @option center: LatLng = undefined\r\n\t\t// Initial geographic center of the map\r\n\t\tcenter: undefined,\r\n\r\n\t\t// @option zoom: Number = undefined\r\n\t\t// Initial map zoom level\r\n\t\tzoom: undefined,\r\n\r\n\t\t// @option minZoom: Number = *\r\n\t\t// Minimum zoom level of the map.\r\n\t\t// If not specified and at least one `GridLayer` or `TileLayer` is in the map,\r\n\t\t// the lowest of their `minZoom` options will be used instead.\r\n\t\tminZoom: undefined,\r\n\r\n\t\t// @option maxZoom: Number = *\r\n\t\t// Maximum zoom level of the map.\r\n\t\t// If not specified and at least one `GridLayer` or `TileLayer` is in the map,\r\n\t\t// the highest of their `maxZoom` options will be used instead.\r\n\t\tmaxZoom: undefined,\r\n\r\n\t\t// @option layers: Layer[] = []\r\n\t\t// Array of layers that will be added to the map initially\r\n\t\tlayers: [],\r\n\r\n\t\t// @option maxBounds: LatLngBounds = null\r\n\t\t// When this option is set, the map restricts the view to the given\r\n\t\t// geographical bounds, bouncing the user back if the user tries to pan\r\n\t\t// outside the view. To set the restriction dynamically, use\r\n\t\t// [`setMaxBounds`](#map-setmaxbounds) method.\r\n\t\tmaxBounds: undefined,\r\n\r\n\t\t// @option renderer: Renderer = *\r\n\t\t// The default method for drawing vector layers on the map. `L.SVG`\r\n\t\t// or `L.Canvas` by default depending on browser support.\r\n\t\trenderer: undefined,\r\n\r\n\r\n\t\t// @section Animation Options\r\n\t\t// @option zoomAnimation: Boolean = true\r\n\t\t// Whether the map zoom animation is enabled. By default it's enabled\r\n\t\t// in all browsers that support CSS3 Transitions except Android.\r\n\t\tzoomAnimation: true,\r\n\r\n\t\t// @option zoomAnimationThreshold: Number = 4\r\n\t\t// Won't animate zoom if the zoom difference exceeds this value.\r\n\t\tzoomAnimationThreshold: 4,\r\n\r\n\t\t// @option fadeAnimation: Boolean = true\r\n\t\t// Whether the tile fade animation is enabled. By default it's enabled\r\n\t\t// in all browsers that support CSS3 Transitions except Android.\r\n\t\tfadeAnimation: true,\r\n\r\n\t\t// @option markerZoomAnimation: Boolean = true\r\n\t\t// Whether markers animate their zoom with the zoom animation, if disabled\r\n\t\t// they will disappear for the length of the animation. By default it's\r\n\t\t// enabled in all browsers that support CSS3 Transitions except Android.\r\n\t\tmarkerZoomAnimation: true,\r\n\r\n\t\t// @option transform3DLimit: Number = 2^23\r\n\t\t// Defines the maximum size of a CSS translation transform. The default\r\n\t\t// value should not be changed unless a web browser positions layers in\r\n\t\t// the wrong place after doing a large `panBy`.\r\n\t\ttransform3DLimit: 8388608, // Precision limit of a 32-bit float\r\n\r\n\t\t// @section Interaction Options\r\n\t\t// @option zoomSnap: Number = 1\r\n\t\t// Forces the map's zoom level to always be a multiple of this, particularly\r\n\t\t// right after a [`fitBounds()`](#map-fitbounds) or a pinch-zoom.\r\n\t\t// By default, the zoom level snaps to the nearest integer; lower values\r\n\t\t// (e.g. `0.5` or `0.1`) allow for greater granularity. A value of `0`\r\n\t\t// means the zoom level will not be snapped after `fitBounds` or a pinch-zoom.\r\n\t\tzoomSnap: 1,\r\n\r\n\t\t// @option zoomDelta: Number = 1\r\n\t\t// Controls how much the map's zoom level will change after a\r\n\t\t// [`zoomIn()`](#map-zoomin), [`zoomOut()`](#map-zoomout), pressing `+`\r\n\t\t// or `-` on the keyboard, or using the [zoom controls](#control-zoom).\r\n\t\t// Values smaller than `1` (e.g. `0.5`) allow for greater granularity.\r\n\t\tzoomDelta: 1,\r\n\r\n\t\t// @option trackResize: Boolean = true\r\n\t\t// Whether the map automatically handles browser window resize to update itself.\r\n\t\ttrackResize: true\r\n\t},\r\n\r\n\tinitialize: function (id, options) { // (HTMLElement or String, Object)\r\n\t\toptions = Util.setOptions(this, options);\r\n\r\n\t\t// Make sure to assign internal flags at the beginning,\r\n\t\t// to avoid inconsistent state in some edge cases.\r\n\t\tthis._handlers = [];\r\n\t\tthis._layers = {};\r\n\t\tthis._zoomBoundLayers = {};\r\n\t\tthis._sizeChanged = true;\r\n\r\n\t\tthis._initContainer(id);\r\n\t\tthis._initLayout();\r\n\r\n\t\t// hack for https://github.com/Leaflet/Leaflet/issues/1980\r\n\t\tthis._onResize = Util.bind(this._onResize, this);\r\n\r\n\t\tthis._initEvents();\r\n\r\n\t\tif (options.maxBounds) {\r\n\t\t\tthis.setMaxBounds(options.maxBounds);\r\n\t\t}\r\n\r\n\t\tif (options.zoom !== undefined) {\r\n\t\t\tthis._zoom = this._limitZoom(options.zoom);\r\n\t\t}\r\n\r\n\t\tif (options.center && options.zoom !== undefined) {\r\n\t\t\tthis.setView(toLatLng(options.center), options.zoom, {reset: true});\r\n\t\t}\r\n\r\n\t\tthis.callInitHooks();\r\n\r\n\t\t// don't animate on browsers without hardware-accelerated transitions or old Android/Opera\r\n\t\tthis._zoomAnimated = DomUtil.TRANSITION && Browser.any3d && !Browser.mobileOpera &&\r\n\t\t\t\tthis.options.zoomAnimation;\r\n\r\n\t\t// zoom transitions run with the same duration for all layers, so if one of transitionend events\r\n\t\t// happens after starting zoom animation (propagating to the map pane), we know that it ended globally\r\n\t\tif (this._zoomAnimated) {\r\n\t\t\tthis._createAnimProxy();\r\n\t\t\tDomEvent.on(this._proxy, DomUtil.TRANSITION_END, this._catchTransitionEnd, this);\r\n\t\t}\r\n\r\n\t\tthis._addLayers(this.options.layers);\r\n\t},\r\n\r\n\r\n\t// @section Methods for modifying map state\r\n\r\n\t// @method setView(center: LatLng, zoom: Number, options?: Zoom/pan options): this\r\n\t// Sets the view of the map (geographical center and zoom) with the given\r\n\t// animation options.\r\n\tsetView: function (center, zoom, options) {\r\n\r\n\t\tzoom = zoom === undefined ? this._zoom : this._limitZoom(zoom);\r\n\t\tcenter = this._limitCenter(toLatLng(center), zoom, this.options.maxBounds);\r\n\t\toptions = options || {};\r\n\r\n\t\tthis._stop();\r\n\r\n\t\tif (this._loaded && !options.reset && options !== true) {\r\n\r\n\t\t\tif (options.animate !== undefined) {\r\n\t\t\t\toptions.zoom = Util.extend({animate: options.animate}, options.zoom);\r\n\t\t\t\toptions.pan = Util.extend({animate: options.animate, duration: options.duration}, options.pan);\r\n\t\t\t}\r\n\r\n\t\t\t// try animating pan or zoom\r\n\t\t\tvar moved = (this._zoom !== zoom) ?\r\n\t\t\t\tthis._tryAnimatedZoom && this._tryAnimatedZoom(center, zoom, options.zoom) :\r\n\t\t\t\tthis._tryAnimatedPan(center, options.pan);\r\n\r\n\t\t\tif (moved) {\r\n\t\t\t\t// prevent resize handler call, the view will refresh after animation anyway\r\n\t\t\t\tclearTimeout(this._sizeTimer);\r\n\t\t\t\treturn this;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// animation didn't start, just reset the map view\r\n\t\tthis._resetView(center, zoom);\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method setZoom(zoom: Number, options?: Zoom/pan options): this\r\n\t// Sets the zoom of the map.\r\n\tsetZoom: function (zoom, options) {\r\n\t\tif (!this._loaded) {\r\n\t\t\tthis._zoom = zoom;\r\n\t\t\treturn this;\r\n\t\t}\r\n\t\treturn this.setView(this.getCenter(), zoom, {zoom: options});\r\n\t},\r\n\r\n\t// @method zoomIn(delta?: Number, options?: Zoom options): this\r\n\t// Increases the zoom of the map by `delta` ([`zoomDelta`](#map-zoomdelta) by default).\r\n\tzoomIn: function (delta, options) {\r\n\t\tdelta = delta || (Browser.any3d ? this.options.zoomDelta : 1);\r\n\t\treturn this.setZoom(this._zoom + delta, options);\r\n\t},\r\n\r\n\t// @method zoomOut(delta?: Number, options?: Zoom options): this\r\n\t// Decreases the zoom of the map by `delta` ([`zoomDelta`](#map-zoomdelta) by default).\r\n\tzoomOut: function (delta, options) {\r\n\t\tdelta = delta || (Browser.any3d ? this.options.zoomDelta : 1);\r\n\t\treturn this.setZoom(this._zoom - delta, options);\r\n\t},\r\n\r\n\t// @method setZoomAround(latlng: LatLng, zoom: Number, options: Zoom options): this\r\n\t// Zooms the map while keeping a specified geographical point on the map\r\n\t// stationary (e.g. used internally for scroll zoom and double-click zoom).\r\n\t// @alternative\r\n\t// @method setZoomAround(offset: Point, zoom: Number, options: Zoom options): this\r\n\t// Zooms the map while keeping a specified pixel on the map (relative to the top-left corner) stationary.\r\n\tsetZoomAround: function (latlng, zoom, options) {\r\n\t\tvar scale = this.getZoomScale(zoom),\r\n\t\t viewHalf = this.getSize().divideBy(2),\r\n\t\t containerPoint = latlng instanceof Point ? latlng : this.latLngToContainerPoint(latlng),\r\n\r\n\t\t centerOffset = containerPoint.subtract(viewHalf).multiplyBy(1 - 1 / scale),\r\n\t\t newCenter = this.containerPointToLatLng(viewHalf.add(centerOffset));\r\n\r\n\t\treturn this.setView(newCenter, zoom, {zoom: options});\r\n\t},\r\n\r\n\t_getBoundsCenterZoom: function (bounds, options) {\r\n\r\n\t\toptions = options || {};\r\n\t\tbounds = bounds.getBounds ? bounds.getBounds() : toLatLngBounds(bounds);\r\n\r\n\t\tvar paddingTL = toPoint(options.paddingTopLeft || options.padding || [0, 0]),\r\n\t\t paddingBR = toPoint(options.paddingBottomRight || options.padding || [0, 0]),\r\n\r\n\t\t zoom = this.getBoundsZoom(bounds, false, paddingTL.add(paddingBR));\r\n\r\n\t\tzoom = (typeof options.maxZoom === 'number') ? Math.min(options.maxZoom, zoom) : zoom;\r\n\r\n\t\tif (zoom === Infinity) {\r\n\t\t\treturn {\r\n\t\t\t\tcenter: bounds.getCenter(),\r\n\t\t\t\tzoom: zoom\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\tvar paddingOffset = paddingBR.subtract(paddingTL).divideBy(2),\r\n\r\n\t\t swPoint = this.project(bounds.getSouthWest(), zoom),\r\n\t\t nePoint = this.project(bounds.getNorthEast(), zoom),\r\n\t\t center = this.unproject(swPoint.add(nePoint).divideBy(2).add(paddingOffset), zoom);\r\n\r\n\t\treturn {\r\n\t\t\tcenter: center,\r\n\t\t\tzoom: zoom\r\n\t\t};\r\n\t},\r\n\r\n\t// @method fitBounds(bounds: LatLngBounds, options?: fitBounds options): this\r\n\t// Sets a map view that contains the given geographical bounds with the\r\n\t// maximum zoom level possible.\r\n\tfitBounds: function (bounds, options) {\r\n\r\n\t\tbounds = toLatLngBounds(bounds);\r\n\r\n\t\tif (!bounds.isValid()) {\r\n\t\t\tthrow new Error('Bounds are not valid.');\r\n\t\t}\r\n\r\n\t\tvar target = this._getBoundsCenterZoom(bounds, options);\r\n\t\treturn this.setView(target.center, target.zoom, options);\r\n\t},\r\n\r\n\t// @method fitWorld(options?: fitBounds options): this\r\n\t// Sets a map view that mostly contains the whole world with the maximum\r\n\t// zoom level possible.\r\n\tfitWorld: function (options) {\r\n\t\treturn this.fitBounds([[-90, -180], [90, 180]], options);\r\n\t},\r\n\r\n\t// @method panTo(latlng: LatLng, options?: Pan options): this\r\n\t// Pans the map to a given center.\r\n\tpanTo: function (center, options) { // (LatLng)\r\n\t\treturn this.setView(center, this._zoom, {pan: options});\r\n\t},\r\n\r\n\t// @method panBy(offset: Point, options?: Pan options): this\r\n\t// Pans the map by a given number of pixels (animated).\r\n\tpanBy: function (offset, options) {\r\n\t\toffset = toPoint(offset).round();\r\n\t\toptions = options || {};\r\n\r\n\t\tif (!offset.x && !offset.y) {\r\n\t\t\treturn this.fire('moveend');\r\n\t\t}\r\n\t\t// If we pan too far, Chrome gets issues with tiles\r\n\t\t// and makes them disappear or appear in the wrong place (slightly offset) #2602\r\n\t\tif (options.animate !== true && !this.getSize().contains(offset)) {\r\n\t\t\tthis._resetView(this.unproject(this.project(this.getCenter()).add(offset)), this.getZoom());\r\n\t\t\treturn this;\r\n\t\t}\r\n\r\n\t\tif (!this._panAnim) {\r\n\t\t\tthis._panAnim = new PosAnimation();\r\n\r\n\t\t\tthis._panAnim.on({\r\n\t\t\t\t'step': this._onPanTransitionStep,\r\n\t\t\t\t'end': this._onPanTransitionEnd\r\n\t\t\t}, this);\r\n\t\t}\r\n\r\n\t\t// don't fire movestart if animating inertia\r\n\t\tif (!options.noMoveStart) {\r\n\t\t\tthis.fire('movestart');\r\n\t\t}\r\n\r\n\t\t// animate pan unless animate: false specified\r\n\t\tif (options.animate !== false) {\r\n\t\t\tDomUtil.addClass(this._mapPane, 'leaflet-pan-anim');\r\n\r\n\t\t\tvar newPos = this._getMapPanePos().subtract(offset).round();\r\n\t\t\tthis._panAnim.run(this._mapPane, newPos, options.duration || 0.25, options.easeLinearity);\r\n\t\t} else {\r\n\t\t\tthis._rawPanBy(offset);\r\n\t\t\tthis.fire('move').fire('moveend');\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method flyTo(latlng: LatLng, zoom?: Number, options?: Zoom/pan options): this\r\n\t// Sets the view of the map (geographical center and zoom) performing a smooth\r\n\t// pan-zoom animation.\r\n\tflyTo: function (targetCenter, targetZoom, options) {\r\n\r\n\t\toptions = options || {};\r\n\t\tif (options.animate === false || !Browser.any3d) {\r\n\t\t\treturn this.setView(targetCenter, targetZoom, options);\r\n\t\t}\r\n\r\n\t\tthis._stop();\r\n\r\n\t\tvar from = this.project(this.getCenter()),\r\n\t\t to = this.project(targetCenter),\r\n\t\t size = this.getSize(),\r\n\t\t startZoom = this._zoom;\r\n\r\n\t\ttargetCenter = toLatLng(targetCenter);\r\n\t\ttargetZoom = targetZoom === undefined ? startZoom : targetZoom;\r\n\r\n\t\tvar w0 = Math.max(size.x, size.y),\r\n\t\t w1 = w0 * this.getZoomScale(startZoom, targetZoom),\r\n\t\t u1 = (to.distanceTo(from)) || 1,\r\n\t\t rho = 1.42,\r\n\t\t rho2 = rho * rho;\r\n\r\n\t\tfunction r(i) {\r\n\t\t\tvar s1 = i ? -1 : 1,\r\n\t\t\t s2 = i ? w1 : w0,\r\n\t\t\t t1 = w1 * w1 - w0 * w0 + s1 * rho2 * rho2 * u1 * u1,\r\n\t\t\t b1 = 2 * s2 * rho2 * u1,\r\n\t\t\t b = t1 / b1,\r\n\t\t\t sq = Math.sqrt(b * b + 1) - b;\r\n\r\n\t\t\t // workaround for floating point precision bug when sq = 0, log = -Infinite,\r\n\t\t\t // thus triggering an infinite loop in flyTo\r\n\t\t\t var log = sq < 0.000000001 ? -18 : Math.log(sq);\r\n\r\n\t\t\treturn log;\r\n\t\t}\r\n\r\n\t\tfunction sinh(n) { return (Math.exp(n) - Math.exp(-n)) / 2; }\r\n\t\tfunction cosh(n) { return (Math.exp(n) + Math.exp(-n)) / 2; }\r\n\t\tfunction tanh(n) { return sinh(n) / cosh(n); }\r\n\r\n\t\tvar r0 = r(0);\r\n\r\n\t\tfunction w(s) { return w0 * (cosh(r0) / cosh(r0 + rho * s)); }\r\n\t\tfunction u(s) { return w0 * (cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2; }\r\n\r\n\t\tfunction easeOut(t) { return 1 - Math.pow(1 - t, 1.5); }\r\n\r\n\t\tvar start = Date.now(),\r\n\t\t S = (r(1) - r0) / rho,\r\n\t\t duration = options.duration ? 1000 * options.duration : 1000 * S * 0.8;\r\n\r\n\t\tfunction frame() {\r\n\t\t\tvar t = (Date.now() - start) / duration,\r\n\t\t\t s = easeOut(t) * S;\r\n\r\n\t\t\tif (t <= 1) {\r\n\t\t\t\tthis._flyToFrame = Util.requestAnimFrame(frame, this);\r\n\r\n\t\t\t\tthis._move(\r\n\t\t\t\t\tthis.unproject(from.add(to.subtract(from).multiplyBy(u(s) / u1)), startZoom),\r\n\t\t\t\t\tthis.getScaleZoom(w0 / w(s), startZoom),\r\n\t\t\t\t\t{flyTo: true});\r\n\r\n\t\t\t} else {\r\n\t\t\t\tthis\r\n\t\t\t\t\t._move(targetCenter, targetZoom)\r\n\t\t\t\t\t._moveEnd(true);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis._moveStart(true, options.noMoveStart);\r\n\r\n\t\tframe.call(this);\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method flyToBounds(bounds: LatLngBounds, options?: fitBounds options): this\r\n\t// Sets the view of the map with a smooth animation like [`flyTo`](#map-flyto),\r\n\t// but takes a bounds parameter like [`fitBounds`](#map-fitbounds).\r\n\tflyToBounds: function (bounds, options) {\r\n\t\tvar target = this._getBoundsCenterZoom(bounds, options);\r\n\t\treturn this.flyTo(target.center, target.zoom, options);\r\n\t},\r\n\r\n\t// @method setMaxBounds(bounds: Bounds): this\r\n\t// Restricts the map view to the given bounds (see the [maxBounds](#map-maxbounds) option).\r\n\tsetMaxBounds: function (bounds) {\r\n\t\tbounds = toLatLngBounds(bounds);\r\n\r\n\t\tif (!bounds.isValid()) {\r\n\t\t\tthis.options.maxBounds = null;\r\n\t\t\treturn this.off('moveend', this._panInsideMaxBounds);\r\n\t\t} else if (this.options.maxBounds) {\r\n\t\t\tthis.off('moveend', this._panInsideMaxBounds);\r\n\t\t}\r\n\r\n\t\tthis.options.maxBounds = bounds;\r\n\r\n\t\tif (this._loaded) {\r\n\t\t\tthis._panInsideMaxBounds();\r\n\t\t}\r\n\r\n\t\treturn this.on('moveend', this._panInsideMaxBounds);\r\n\t},\r\n\r\n\t// @method setMinZoom(zoom: Number): this\r\n\t// Sets the lower limit for the available zoom levels (see the [minZoom](#map-minzoom) option).\r\n\tsetMinZoom: function (zoom) {\r\n\t\tvar oldZoom = this.options.minZoom;\r\n\t\tthis.options.minZoom = zoom;\r\n\r\n\t\tif (this._loaded && oldZoom !== zoom) {\r\n\t\t\tthis.fire('zoomlevelschange');\r\n\r\n\t\t\tif (this.getZoom() < this.options.minZoom) {\r\n\t\t\t\treturn this.setZoom(zoom);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method setMaxZoom(zoom: Number): this\r\n\t// Sets the upper limit for the available zoom levels (see the [maxZoom](#map-maxzoom) option).\r\n\tsetMaxZoom: function (zoom) {\r\n\t\tvar oldZoom = this.options.maxZoom;\r\n\t\tthis.options.maxZoom = zoom;\r\n\r\n\t\tif (this._loaded && oldZoom !== zoom) {\r\n\t\t\tthis.fire('zoomlevelschange');\r\n\r\n\t\t\tif (this.getZoom() > this.options.maxZoom) {\r\n\t\t\t\treturn this.setZoom(zoom);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method panInsideBounds(bounds: LatLngBounds, options?: Pan options): this\r\n\t// Pans the map to the closest view that would lie inside the given bounds (if it's not already), controlling the animation using the options specific, if any.\r\n\tpanInsideBounds: function (bounds, options) {\r\n\t\tthis._enforcingBounds = true;\r\n\t\tvar center = this.getCenter(),\r\n\t\t newCenter = this._limitCenter(center, this._zoom, toLatLngBounds(bounds));\r\n\r\n\t\tif (!center.equals(newCenter)) {\r\n\t\t\tthis.panTo(newCenter, options);\r\n\t\t}\r\n\r\n\t\tthis._enforcingBounds = false;\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method panInside(latlng: LatLng, options?: options): this\r\n\t// Pans the map the minimum amount to make the `latlng` visible. Use\r\n\t// `padding`, `paddingTopLeft` and `paddingTopRight` options to fit\r\n\t// the display to more restricted bounds, like [`fitBounds`](#map-fitbounds).\r\n\t// If `latlng` is already within the (optionally padded) display bounds,\r\n\t// the map will not be panned.\r\n\tpanInside: function (latlng, options) {\r\n\t\toptions = options || {};\r\n\r\n\t\tvar paddingTL = toPoint(options.paddingTopLeft || options.padding || [0, 0]),\r\n\t\t paddingBR = toPoint(options.paddingBottomRight || options.padding || [0, 0]),\r\n\t\t center = this.getCenter(),\r\n\t\t pixelCenter = this.project(center),\r\n\t\t pixelPoint = this.project(latlng),\r\n\t\t pixelBounds = this.getPixelBounds(),\r\n\t\t halfPixelBounds = pixelBounds.getSize().divideBy(2),\r\n\t\t paddedBounds = toBounds([pixelBounds.min.add(paddingTL), pixelBounds.max.subtract(paddingBR)]);\r\n\r\n\t\tif (!paddedBounds.contains(pixelPoint)) {\r\n\t\t\tthis._enforcingBounds = true;\r\n\t\t\tvar diff = pixelCenter.subtract(pixelPoint),\r\n\t\t\t newCenter = toPoint(pixelPoint.x + diff.x, pixelPoint.y + diff.y);\r\n\r\n\t\t\tif (pixelPoint.x < paddedBounds.min.x || pixelPoint.x > paddedBounds.max.x) {\r\n\t\t\t\tnewCenter.x = pixelCenter.x - diff.x;\r\n\t\t\t\tif (diff.x > 0) {\r\n\t\t\t\t\tnewCenter.x += halfPixelBounds.x - paddingTL.x;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tnewCenter.x -= halfPixelBounds.x - paddingBR.x;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (pixelPoint.y < paddedBounds.min.y || pixelPoint.y > paddedBounds.max.y) {\r\n\t\t\t\tnewCenter.y = pixelCenter.y - diff.y;\r\n\t\t\t\tif (diff.y > 0) {\r\n\t\t\t\t\tnewCenter.y += halfPixelBounds.y - paddingTL.y;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tnewCenter.y -= halfPixelBounds.y - paddingBR.y;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tthis.panTo(this.unproject(newCenter), options);\r\n\t\t\tthis._enforcingBounds = false;\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method invalidateSize(options: Zoom/pan options): this\r\n\t// Checks if the map container size changed and updates the map if so —\r\n\t// call it after you've changed the map size dynamically, also animating\r\n\t// pan by default. If `options.pan` is `false`, panning will not occur.\r\n\t// If `options.debounceMoveend` is `true`, it will delay `moveend` event so\r\n\t// that it doesn't happen often even if the method is called many\r\n\t// times in a row.\r\n\r\n\t// @alternative\r\n\t// @method invalidateSize(animate: Boolean): this\r\n\t// Checks if the map container size changed and updates the map if so —\r\n\t// call it after you've changed the map size dynamically, also animating\r\n\t// pan by default.\r\n\tinvalidateSize: function (options) {\r\n\t\tif (!this._loaded) { return this; }\r\n\r\n\t\toptions = Util.extend({\r\n\t\t\tanimate: false,\r\n\t\t\tpan: true\r\n\t\t}, options === true ? {animate: true} : options);\r\n\r\n\t\tvar oldSize = this.getSize();\r\n\t\tthis._sizeChanged = true;\r\n\t\tthis._lastCenter = null;\r\n\r\n\t\tvar newSize = this.getSize(),\r\n\t\t oldCenter = oldSize.divideBy(2).round(),\r\n\t\t newCenter = newSize.divideBy(2).round(),\r\n\t\t offset = oldCenter.subtract(newCenter);\r\n\r\n\t\tif (!offset.x && !offset.y) { return this; }\r\n\r\n\t\tif (options.animate && options.pan) {\r\n\t\t\tthis.panBy(offset);\r\n\r\n\t\t} else {\r\n\t\t\tif (options.pan) {\r\n\t\t\t\tthis._rawPanBy(offset);\r\n\t\t\t}\r\n\r\n\t\t\tthis.fire('move');\r\n\r\n\t\t\tif (options.debounceMoveend) {\r\n\t\t\t\tclearTimeout(this._sizeTimer);\r\n\t\t\t\tthis._sizeTimer = setTimeout(Util.bind(this.fire, this, 'moveend'), 200);\r\n\t\t\t} else {\r\n\t\t\t\tthis.fire('moveend');\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// @section Map state change events\r\n\t\t// @event resize: ResizeEvent\r\n\t\t// Fired when the map is resized.\r\n\t\treturn this.fire('resize', {\r\n\t\t\toldSize: oldSize,\r\n\t\t\tnewSize: newSize\r\n\t\t});\r\n\t},\r\n\r\n\t// @section Methods for modifying map state\r\n\t// @method stop(): this\r\n\t// Stops the currently running `panTo` or `flyTo` animation, if any.\r\n\tstop: function () {\r\n\t\tthis.setZoom(this._limitZoom(this._zoom));\r\n\t\tif (!this.options.zoomSnap) {\r\n\t\t\tthis.fire('viewreset');\r\n\t\t}\r\n\t\treturn this._stop();\r\n\t},\r\n\r\n\t// @section Geolocation methods\r\n\t// @method locate(options?: Locate options): this\r\n\t// Tries to locate the user using the Geolocation API, firing a [`locationfound`](#map-locationfound)\r\n\t// event with location data on success or a [`locationerror`](#map-locationerror) event on failure,\r\n\t// and optionally sets the map view to the user's location with respect to\r\n\t// detection accuracy (or to the world view if geolocation failed).\r\n\t// Note that, if your page doesn't use HTTPS, this method will fail in\r\n\t// modern browsers ([Chrome 50 and newer](https://sites.google.com/a/chromium.org/dev/Home/chromium-security/deprecating-powerful-features-on-insecure-origins))\r\n\t// See `Locate options` for more details.\r\n\tlocate: function (options) {\r\n\r\n\t\toptions = this._locateOptions = Util.extend({\r\n\t\t\ttimeout: 10000,\r\n\t\t\twatch: false\r\n\t\t\t// setView: false\r\n\t\t\t// maxZoom: \r\n\t\t\t// maximumAge: 0\r\n\t\t\t// enableHighAccuracy: false\r\n\t\t}, options);\r\n\r\n\t\tif (!('geolocation' in navigator)) {\r\n\t\t\tthis._handleGeolocationError({\r\n\t\t\t\tcode: 0,\r\n\t\t\t\tmessage: 'Geolocation not supported.'\r\n\t\t\t});\r\n\t\t\treturn this;\r\n\t\t}\r\n\r\n\t\tvar onResponse = Util.bind(this._handleGeolocationResponse, this),\r\n\t\t onError = Util.bind(this._handleGeolocationError, this);\r\n\r\n\t\tif (options.watch) {\r\n\t\t\tthis._locationWatchId =\r\n\t\t\t navigator.geolocation.watchPosition(onResponse, onError, options);\r\n\t\t} else {\r\n\t\t\tnavigator.geolocation.getCurrentPosition(onResponse, onError, options);\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method stopLocate(): this\r\n\t// Stops watching location previously initiated by `map.locate({watch: true})`\r\n\t// and aborts resetting the map view if map.locate was called with\r\n\t// `{setView: true}`.\r\n\tstopLocate: function () {\r\n\t\tif (navigator.geolocation && navigator.geolocation.clearWatch) {\r\n\t\t\tnavigator.geolocation.clearWatch(this._locationWatchId);\r\n\t\t}\r\n\t\tif (this._locateOptions) {\r\n\t\t\tthis._locateOptions.setView = false;\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t_handleGeolocationError: function (error) {\r\n\t\tvar c = error.code,\r\n\t\t message = error.message ||\r\n\t\t (c === 1 ? 'permission denied' :\r\n\t\t (c === 2 ? 'position unavailable' : 'timeout'));\r\n\r\n\t\tif (this._locateOptions.setView && !this._loaded) {\r\n\t\t\tthis.fitWorld();\r\n\t\t}\r\n\r\n\t\t// @section Location events\r\n\t\t// @event locationerror: ErrorEvent\r\n\t\t// Fired when geolocation (using the [`locate`](#map-locate) method) failed.\r\n\t\tthis.fire('locationerror', {\r\n\t\t\tcode: c,\r\n\t\t\tmessage: 'Geolocation error: ' + message + '.'\r\n\t\t});\r\n\t},\r\n\r\n\t_handleGeolocationResponse: function (pos) {\r\n\t\tvar lat = pos.coords.latitude,\r\n\t\t lng = pos.coords.longitude,\r\n\t\t latlng = new LatLng(lat, lng),\r\n\t\t bounds = latlng.toBounds(pos.coords.accuracy * 2),\r\n\t\t options = this._locateOptions;\r\n\r\n\t\tif (options.setView) {\r\n\t\t\tvar zoom = this.getBoundsZoom(bounds);\r\n\t\t\tthis.setView(latlng, options.maxZoom ? Math.min(zoom, options.maxZoom) : zoom);\r\n\t\t}\r\n\r\n\t\tvar data = {\r\n\t\t\tlatlng: latlng,\r\n\t\t\tbounds: bounds,\r\n\t\t\ttimestamp: pos.timestamp\r\n\t\t};\r\n\r\n\t\tfor (var i in pos.coords) {\r\n\t\t\tif (typeof pos.coords[i] === 'number') {\r\n\t\t\t\tdata[i] = pos.coords[i];\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// @event locationfound: LocationEvent\r\n\t\t// Fired when geolocation (using the [`locate`](#map-locate) method)\r\n\t\t// went successfully.\r\n\t\tthis.fire('locationfound', data);\r\n\t},\r\n\r\n\t// TODO Appropriate docs section?\r\n\t// @section Other Methods\r\n\t// @method addHandler(name: String, HandlerClass: Function): this\r\n\t// Adds a new `Handler` to the map, given its name and constructor function.\r\n\taddHandler: function (name, HandlerClass) {\r\n\t\tif (!HandlerClass) { return this; }\r\n\r\n\t\tvar handler = this[name] = new HandlerClass(this);\r\n\r\n\t\tthis._handlers.push(handler);\r\n\r\n\t\tif (this.options[name]) {\r\n\t\t\thandler.enable();\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method remove(): this\r\n\t// Destroys the map and clears all related event listeners.\r\n\tremove: function () {\r\n\r\n\t\tthis._initEvents(true);\r\n\r\n\t\tif (this._containerId !== this._container._leaflet_id) {\r\n\t\t\tthrow new Error('Map container is being reused by another instance');\r\n\t\t}\r\n\r\n\t\ttry {\r\n\t\t\t// throws error in IE6-8\r\n\t\t\tdelete this._container._leaflet_id;\r\n\t\t\tdelete this._containerId;\r\n\t\t} catch (e) {\r\n\t\t\t/*eslint-disable */\r\n\t\t\tthis._container._leaflet_id = undefined;\r\n\t\t\t/* eslint-enable */\r\n\t\t\tthis._containerId = undefined;\r\n\t\t}\r\n\r\n\t\tif (this._locationWatchId !== undefined) {\r\n\t\t\tthis.stopLocate();\r\n\t\t}\r\n\r\n\t\tthis._stop();\r\n\r\n\t\tDomUtil.remove(this._mapPane);\r\n\r\n\t\tif (this._clearControlPos) {\r\n\t\t\tthis._clearControlPos();\r\n\t\t}\r\n\t\tif (this._resizeRequest) {\r\n\t\t\tUtil.cancelAnimFrame(this._resizeRequest);\r\n\t\t\tthis._resizeRequest = null;\r\n\t\t}\r\n\r\n\t\tthis._clearHandlers();\r\n\r\n\t\tif (this._loaded) {\r\n\t\t\t// @section Map state change events\r\n\t\t\t// @event unload: Event\r\n\t\t\t// Fired when the map is destroyed with [remove](#map-remove) method.\r\n\t\t\tthis.fire('unload');\r\n\t\t}\r\n\r\n\t\tvar i;\r\n\t\tfor (i in this._layers) {\r\n\t\t\tthis._layers[i].remove();\r\n\t\t}\r\n\t\tfor (i in this._panes) {\r\n\t\t\tDomUtil.remove(this._panes[i]);\r\n\t\t}\r\n\r\n\t\tthis._layers = [];\r\n\t\tthis._panes = [];\r\n\t\tdelete this._mapPane;\r\n\t\tdelete this._renderer;\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @section Other Methods\r\n\t// @method createPane(name: String, container?: HTMLElement): HTMLElement\r\n\t// Creates a new [map pane](#map-pane) with the given name if it doesn't exist already,\r\n\t// then returns it. The pane is created as a child of `container`, or\r\n\t// as a child of the main map pane if not set.\r\n\tcreatePane: function (name, container) {\r\n\t\tvar className = 'leaflet-pane' + (name ? ' leaflet-' + name.replace('Pane', '') + '-pane' : ''),\r\n\t\t pane = DomUtil.create('div', className, container || this._mapPane);\r\n\r\n\t\tif (name) {\r\n\t\t\tthis._panes[name] = pane;\r\n\t\t}\r\n\t\treturn pane;\r\n\t},\r\n\r\n\t// @section Methods for Getting Map State\r\n\r\n\t// @method getCenter(): LatLng\r\n\t// Returns the geographical center of the map view\r\n\tgetCenter: function () {\r\n\t\tthis._checkIfLoaded();\r\n\r\n\t\tif (this._lastCenter && !this._moved()) {\r\n\t\t\treturn this._lastCenter;\r\n\t\t}\r\n\t\treturn this.layerPointToLatLng(this._getCenterLayerPoint());\r\n\t},\r\n\r\n\t// @method getZoom(): Number\r\n\t// Returns the current zoom level of the map view\r\n\tgetZoom: function () {\r\n\t\treturn this._zoom;\r\n\t},\r\n\r\n\t// @method getBounds(): LatLngBounds\r\n\t// Returns the geographical bounds visible in the current map view\r\n\tgetBounds: function () {\r\n\t\tvar bounds = this.getPixelBounds(),\r\n\t\t sw = this.unproject(bounds.getBottomLeft()),\r\n\t\t ne = this.unproject(bounds.getTopRight());\r\n\r\n\t\treturn new LatLngBounds(sw, ne);\r\n\t},\r\n\r\n\t// @method getMinZoom(): Number\r\n\t// Returns the minimum zoom level of the map (if set in the `minZoom` option of the map or of any layers), or `0` by default.\r\n\tgetMinZoom: function () {\r\n\t\treturn this.options.minZoom === undefined ? this._layersMinZoom || 0 : this.options.minZoom;\r\n\t},\r\n\r\n\t// @method getMaxZoom(): Number\r\n\t// Returns the maximum zoom level of the map (if set in the `maxZoom` option of the map or of any layers).\r\n\tgetMaxZoom: function () {\r\n\t\treturn this.options.maxZoom === undefined ?\r\n\t\t\t(this._layersMaxZoom === undefined ? Infinity : this._layersMaxZoom) :\r\n\t\t\tthis.options.maxZoom;\r\n\t},\r\n\r\n\t// @method getBoundsZoom(bounds: LatLngBounds, inside?: Boolean, padding?: Point): Number\r\n\t// Returns the maximum zoom level on which the given bounds fit to the map\r\n\t// view in its entirety. If `inside` (optional) is set to `true`, the method\r\n\t// instead returns the minimum zoom level on which the map view fits into\r\n\t// the given bounds in its entirety.\r\n\tgetBoundsZoom: function (bounds, inside, padding) { // (LatLngBounds[, Boolean, Point]) -> Number\r\n\t\tbounds = toLatLngBounds(bounds);\r\n\t\tpadding = toPoint(padding || [0, 0]);\r\n\r\n\t\tvar zoom = this.getZoom() || 0,\r\n\t\t min = this.getMinZoom(),\r\n\t\t max = this.getMaxZoom(),\r\n\t\t nw = bounds.getNorthWest(),\r\n\t\t se = bounds.getSouthEast(),\r\n\t\t size = this.getSize().subtract(padding),\r\n\t\t boundsSize = toBounds(this.project(se, zoom), this.project(nw, zoom)).getSize(),\r\n\t\t snap = Browser.any3d ? this.options.zoomSnap : 1,\r\n\t\t scalex = size.x / boundsSize.x,\r\n\t\t scaley = size.y / boundsSize.y,\r\n\t\t scale = inside ? Math.max(scalex, scaley) : Math.min(scalex, scaley);\r\n\r\n\t\tzoom = this.getScaleZoom(scale, zoom);\r\n\r\n\t\tif (snap) {\r\n\t\t\tzoom = Math.round(zoom / (snap / 100)) * (snap / 100); // don't jump if within 1% of a snap level\r\n\t\t\tzoom = inside ? Math.ceil(zoom / snap) * snap : Math.floor(zoom / snap) * snap;\r\n\t\t}\r\n\r\n\t\treturn Math.max(min, Math.min(max, zoom));\r\n\t},\r\n\r\n\t// @method getSize(): Point\r\n\t// Returns the current size of the map container (in pixels).\r\n\tgetSize: function () {\r\n\t\tif (!this._size || this._sizeChanged) {\r\n\t\t\tthis._size = new Point(\r\n\t\t\t\tthis._container.clientWidth || 0,\r\n\t\t\t\tthis._container.clientHeight || 0);\r\n\r\n\t\t\tthis._sizeChanged = false;\r\n\t\t}\r\n\t\treturn this._size.clone();\r\n\t},\r\n\r\n\t// @method getPixelBounds(): Bounds\r\n\t// Returns the bounds of the current map view in projected pixel\r\n\t// coordinates (sometimes useful in layer and overlay implementations).\r\n\tgetPixelBounds: function (center, zoom) {\r\n\t\tvar topLeftPoint = this._getTopLeftPoint(center, zoom);\r\n\t\treturn new Bounds(topLeftPoint, topLeftPoint.add(this.getSize()));\r\n\t},\r\n\r\n\t// TODO: Check semantics - isn't the pixel origin the 0,0 coord relative to\r\n\t// the map pane? \"left point of the map layer\" can be confusing, specially\r\n\t// since there can be negative offsets.\r\n\t// @method getPixelOrigin(): Point\r\n\t// Returns the projected pixel coordinates of the top left point of\r\n\t// the map layer (useful in custom layer and overlay implementations).\r\n\tgetPixelOrigin: function () {\r\n\t\tthis._checkIfLoaded();\r\n\t\treturn this._pixelOrigin;\r\n\t},\r\n\r\n\t// @method getPixelWorldBounds(zoom?: Number): Bounds\r\n\t// Returns the world's bounds in pixel coordinates for zoom level `zoom`.\r\n\t// If `zoom` is omitted, the map's current zoom level is used.\r\n\tgetPixelWorldBounds: function (zoom) {\r\n\t\treturn this.options.crs.getProjectedBounds(zoom === undefined ? this.getZoom() : zoom);\r\n\t},\r\n\r\n\t// @section Other Methods\r\n\r\n\t// @method getPane(pane: String|HTMLElement): HTMLElement\r\n\t// Returns a [map pane](#map-pane), given its name or its HTML element (its identity).\r\n\tgetPane: function (pane) {\r\n\t\treturn typeof pane === 'string' ? this._panes[pane] : pane;\r\n\t},\r\n\r\n\t// @method getPanes(): Object\r\n\t// Returns a plain object containing the names of all [panes](#map-pane) as keys and\r\n\t// the panes as values.\r\n\tgetPanes: function () {\r\n\t\treturn this._panes;\r\n\t},\r\n\r\n\t// @method getContainer: HTMLElement\r\n\t// Returns the HTML element that contains the map.\r\n\tgetContainer: function () {\r\n\t\treturn this._container;\r\n\t},\r\n\r\n\r\n\t// @section Conversion Methods\r\n\r\n\t// @method getZoomScale(toZoom: Number, fromZoom: Number): Number\r\n\t// Returns the scale factor to be applied to a map transition from zoom level\r\n\t// `fromZoom` to `toZoom`. Used internally to help with zoom animations.\r\n\tgetZoomScale: function (toZoom, fromZoom) {\r\n\t\t// TODO replace with universal implementation after refactoring projections\r\n\t\tvar crs = this.options.crs;\r\n\t\tfromZoom = fromZoom === undefined ? this._zoom : fromZoom;\r\n\t\treturn crs.scale(toZoom) / crs.scale(fromZoom);\r\n\t},\r\n\r\n\t// @method getScaleZoom(scale: Number, fromZoom: Number): Number\r\n\t// Returns the zoom level that the map would end up at, if it is at `fromZoom`\r\n\t// level and everything is scaled by a factor of `scale`. Inverse of\r\n\t// [`getZoomScale`](#map-getZoomScale).\r\n\tgetScaleZoom: function (scale, fromZoom) {\r\n\t\tvar crs = this.options.crs;\r\n\t\tfromZoom = fromZoom === undefined ? this._zoom : fromZoom;\r\n\t\tvar zoom = crs.zoom(scale * crs.scale(fromZoom));\r\n\t\treturn isNaN(zoom) ? Infinity : zoom;\r\n\t},\r\n\r\n\t// @method project(latlng: LatLng, zoom: Number): Point\r\n\t// Projects a geographical coordinate `LatLng` according to the projection\r\n\t// of the map's CRS, then scales it according to `zoom` and the CRS's\r\n\t// `Transformation`. The result is pixel coordinate relative to\r\n\t// the CRS origin.\r\n\tproject: function (latlng, zoom) {\r\n\t\tzoom = zoom === undefined ? this._zoom : zoom;\r\n\t\treturn this.options.crs.latLngToPoint(toLatLng(latlng), zoom);\r\n\t},\r\n\r\n\t// @method unproject(point: Point, zoom: Number): LatLng\r\n\t// Inverse of [`project`](#map-project).\r\n\tunproject: function (point, zoom) {\r\n\t\tzoom = zoom === undefined ? this._zoom : zoom;\r\n\t\treturn this.options.crs.pointToLatLng(toPoint(point), zoom);\r\n\t},\r\n\r\n\t// @method layerPointToLatLng(point: Point): LatLng\r\n\t// Given a pixel coordinate relative to the [origin pixel](#map-getpixelorigin),\r\n\t// returns the corresponding geographical coordinate (for the current zoom level).\r\n\tlayerPointToLatLng: function (point) {\r\n\t\tvar projectedPoint = toPoint(point).add(this.getPixelOrigin());\r\n\t\treturn this.unproject(projectedPoint);\r\n\t},\r\n\r\n\t// @method latLngToLayerPoint(latlng: LatLng): Point\r\n\t// Given a geographical coordinate, returns the corresponding pixel coordinate\r\n\t// relative to the [origin pixel](#map-getpixelorigin).\r\n\tlatLngToLayerPoint: function (latlng) {\r\n\t\tvar projectedPoint = this.project(toLatLng(latlng))._round();\r\n\t\treturn projectedPoint._subtract(this.getPixelOrigin());\r\n\t},\r\n\r\n\t// @method wrapLatLng(latlng: LatLng): LatLng\r\n\t// Returns a `LatLng` where `lat` and `lng` has been wrapped according to the\r\n\t// map's CRS's `wrapLat` and `wrapLng` properties, if they are outside the\r\n\t// CRS's bounds.\r\n\t// By default this means longitude is wrapped around the dateline so its\r\n\t// value is between -180 and +180 degrees.\r\n\twrapLatLng: function (latlng) {\r\n\t\treturn this.options.crs.wrapLatLng(toLatLng(latlng));\r\n\t},\r\n\r\n\t// @method wrapLatLngBounds(bounds: LatLngBounds): LatLngBounds\r\n\t// Returns a `LatLngBounds` with the same size as the given one, ensuring that\r\n\t// its center is within the CRS's bounds.\r\n\t// By default this means the center longitude is wrapped around the dateline so its\r\n\t// value is between -180 and +180 degrees, and the majority of the bounds\r\n\t// overlaps the CRS's bounds.\r\n\twrapLatLngBounds: function (latlng) {\r\n\t\treturn this.options.crs.wrapLatLngBounds(toLatLngBounds(latlng));\r\n\t},\r\n\r\n\t// @method distance(latlng1: LatLng, latlng2: LatLng): Number\r\n\t// Returns the distance between two geographical coordinates according to\r\n\t// the map's CRS. By default this measures distance in meters.\r\n\tdistance: function (latlng1, latlng2) {\r\n\t\treturn this.options.crs.distance(toLatLng(latlng1), toLatLng(latlng2));\r\n\t},\r\n\r\n\t// @method containerPointToLayerPoint(point: Point): Point\r\n\t// Given a pixel coordinate relative to the map container, returns the corresponding\r\n\t// pixel coordinate relative to the [origin pixel](#map-getpixelorigin).\r\n\tcontainerPointToLayerPoint: function (point) { // (Point)\r\n\t\treturn toPoint(point).subtract(this._getMapPanePos());\r\n\t},\r\n\r\n\t// @method layerPointToContainerPoint(point: Point): Point\r\n\t// Given a pixel coordinate relative to the [origin pixel](#map-getpixelorigin),\r\n\t// returns the corresponding pixel coordinate relative to the map container.\r\n\tlayerPointToContainerPoint: function (point) { // (Point)\r\n\t\treturn toPoint(point).add(this._getMapPanePos());\r\n\t},\r\n\r\n\t// @method containerPointToLatLng(point: Point): LatLng\r\n\t// Given a pixel coordinate relative to the map container, returns\r\n\t// the corresponding geographical coordinate (for the current zoom level).\r\n\tcontainerPointToLatLng: function (point) {\r\n\t\tvar layerPoint = this.containerPointToLayerPoint(toPoint(point));\r\n\t\treturn this.layerPointToLatLng(layerPoint);\r\n\t},\r\n\r\n\t// @method latLngToContainerPoint(latlng: LatLng): Point\r\n\t// Given a geographical coordinate, returns the corresponding pixel coordinate\r\n\t// relative to the map container.\r\n\tlatLngToContainerPoint: function (latlng) {\r\n\t\treturn this.layerPointToContainerPoint(this.latLngToLayerPoint(toLatLng(latlng)));\r\n\t},\r\n\r\n\t// @method mouseEventToContainerPoint(ev: MouseEvent): Point\r\n\t// Given a MouseEvent object, returns the pixel coordinate relative to the\r\n\t// map container where the event took place.\r\n\tmouseEventToContainerPoint: function (e) {\r\n\t\treturn DomEvent.getMousePosition(e, this._container);\r\n\t},\r\n\r\n\t// @method mouseEventToLayerPoint(ev: MouseEvent): Point\r\n\t// Given a MouseEvent object, returns the pixel coordinate relative to\r\n\t// the [origin pixel](#map-getpixelorigin) where the event took place.\r\n\tmouseEventToLayerPoint: function (e) {\r\n\t\treturn this.containerPointToLayerPoint(this.mouseEventToContainerPoint(e));\r\n\t},\r\n\r\n\t// @method mouseEventToLatLng(ev: MouseEvent): LatLng\r\n\t// Given a MouseEvent object, returns geographical coordinate where the\r\n\t// event took place.\r\n\tmouseEventToLatLng: function (e) { // (MouseEvent)\r\n\t\treturn this.layerPointToLatLng(this.mouseEventToLayerPoint(e));\r\n\t},\r\n\r\n\r\n\t// map initialization methods\r\n\r\n\t_initContainer: function (id) {\r\n\t\tvar container = this._container = DomUtil.get(id);\r\n\r\n\t\tif (!container) {\r\n\t\t\tthrow new Error('Map container not found.');\r\n\t\t} else if (container._leaflet_id) {\r\n\t\t\tthrow new Error('Map container is already initialized.');\r\n\t\t}\r\n\r\n\t\tDomEvent.on(container, 'scroll', this._onScroll, this);\r\n\t\tthis._containerId = Util.stamp(container);\r\n\t},\r\n\r\n\t_initLayout: function () {\r\n\t\tvar container = this._container;\r\n\r\n\t\tthis._fadeAnimated = this.options.fadeAnimation && Browser.any3d;\r\n\r\n\t\tDomUtil.addClass(container, 'leaflet-container' +\r\n\t\t\t(Browser.touch ? ' leaflet-touch' : '') +\r\n\t\t\t(Browser.retina ? ' leaflet-retina' : '') +\r\n\t\t\t(Browser.ielt9 ? ' leaflet-oldie' : '') +\r\n\t\t\t(Browser.safari ? ' leaflet-safari' : '') +\r\n\t\t\t(this._fadeAnimated ? ' leaflet-fade-anim' : ''));\r\n\r\n\t\tvar position = DomUtil.getStyle(container, 'position');\r\n\r\n\t\tif (position !== 'absolute' && position !== 'relative' && position !== 'fixed') {\r\n\t\t\tcontainer.style.position = 'relative';\r\n\t\t}\r\n\r\n\t\tthis._initPanes();\r\n\r\n\t\tif (this._initControlPos) {\r\n\t\t\tthis._initControlPos();\r\n\t\t}\r\n\t},\r\n\r\n\t_initPanes: function () {\r\n\t\tvar panes = this._panes = {};\r\n\t\tthis._paneRenderers = {};\r\n\r\n\t\t// @section\r\n\t\t//\r\n\t\t// Panes are DOM elements used to control the ordering of layers on the map. You\r\n\t\t// can access panes with [`map.getPane`](#map-getpane) or\r\n\t\t// [`map.getPanes`](#map-getpanes) methods. New panes can be created with the\r\n\t\t// [`map.createPane`](#map-createpane) method.\r\n\t\t//\r\n\t\t// Every map has the following default panes that differ only in zIndex.\r\n\t\t//\r\n\t\t// @pane mapPane: HTMLElement = 'auto'\r\n\t\t// Pane that contains all other map panes\r\n\r\n\t\tthis._mapPane = this.createPane('mapPane', this._container);\r\n\t\tDomUtil.setPosition(this._mapPane, new Point(0, 0));\r\n\r\n\t\t// @pane tilePane: HTMLElement = 200\r\n\t\t// Pane for `GridLayer`s and `TileLayer`s\r\n\t\tthis.createPane('tilePane');\r\n\t\t// @pane overlayPane: HTMLElement = 400\r\n\t\t// Pane for vectors (`Path`s, like `Polyline`s and `Polygon`s), `ImageOverlay`s and `VideoOverlay`s\r\n\t\tthis.createPane('shadowPane');\r\n\t\t// @pane shadowPane: HTMLElement = 500\r\n\t\t// Pane for overlay shadows (e.g. `Marker` shadows)\r\n\t\tthis.createPane('overlayPane');\r\n\t\t// @pane markerPane: HTMLElement = 600\r\n\t\t// Pane for `Icon`s of `Marker`s\r\n\t\tthis.createPane('markerPane');\r\n\t\t// @pane tooltipPane: HTMLElement = 650\r\n\t\t// Pane for `Tooltip`s.\r\n\t\tthis.createPane('tooltipPane');\r\n\t\t// @pane popupPane: HTMLElement = 700\r\n\t\t// Pane for `Popup`s.\r\n\t\tthis.createPane('popupPane');\r\n\r\n\t\tif (!this.options.markerZoomAnimation) {\r\n\t\t\tDomUtil.addClass(panes.markerPane, 'leaflet-zoom-hide');\r\n\t\t\tDomUtil.addClass(panes.shadowPane, 'leaflet-zoom-hide');\r\n\t\t}\r\n\t},\r\n\r\n\r\n\t// private methods that modify map state\r\n\r\n\t// @section Map state change events\r\n\t_resetView: function (center, zoom) {\r\n\t\tDomUtil.setPosition(this._mapPane, new Point(0, 0));\r\n\r\n\t\tvar loading = !this._loaded;\r\n\t\tthis._loaded = true;\r\n\t\tzoom = this._limitZoom(zoom);\r\n\r\n\t\tthis.fire('viewprereset');\r\n\r\n\t\tvar zoomChanged = this._zoom !== zoom;\r\n\t\tthis\r\n\t\t\t._moveStart(zoomChanged, false)\r\n\t\t\t._move(center, zoom)\r\n\t\t\t._moveEnd(zoomChanged);\r\n\r\n\t\t// @event viewreset: Event\r\n\t\t// Fired when the map needs to redraw its content (this usually happens\r\n\t\t// on map zoom or load). Very useful for creating custom overlays.\r\n\t\tthis.fire('viewreset');\r\n\r\n\t\t// @event load: Event\r\n\t\t// Fired when the map is initialized (when its center and zoom are set\r\n\t\t// for the first time).\r\n\t\tif (loading) {\r\n\t\t\tthis.fire('load');\r\n\t\t}\r\n\t},\r\n\r\n\t_moveStart: function (zoomChanged, noMoveStart) {\r\n\t\t// @event zoomstart: Event\r\n\t\t// Fired when the map zoom is about to change (e.g. before zoom animation).\r\n\t\t// @event movestart: Event\r\n\t\t// Fired when the view of the map starts changing (e.g. user starts dragging the map).\r\n\t\tif (zoomChanged) {\r\n\t\t\tthis.fire('zoomstart');\r\n\t\t}\r\n\t\tif (!noMoveStart) {\r\n\t\t\tthis.fire('movestart');\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t_move: function (center, zoom, data) {\r\n\t\tif (zoom === undefined) {\r\n\t\t\tzoom = this._zoom;\r\n\t\t}\r\n\t\tvar zoomChanged = this._zoom !== zoom;\r\n\r\n\t\tthis._zoom = zoom;\r\n\t\tthis._lastCenter = center;\r\n\t\tthis._pixelOrigin = this._getNewPixelOrigin(center);\r\n\r\n\t\t// @event zoom: Event\r\n\t\t// Fired repeatedly during any change in zoom level, including zoom\r\n\t\t// and fly animations.\r\n\t\tif (zoomChanged || (data && data.pinch)) {\t// Always fire 'zoom' if pinching because #3530\r\n\t\t\tthis.fire('zoom', data);\r\n\t\t}\r\n\r\n\t\t// @event move: Event\r\n\t\t// Fired repeatedly during any movement of the map, including pan and\r\n\t\t// fly animations.\r\n\t\treturn this.fire('move', data);\r\n\t},\r\n\r\n\t_moveEnd: function (zoomChanged) {\r\n\t\t// @event zoomend: Event\r\n\t\t// Fired when the map has changed, after any animations.\r\n\t\tif (zoomChanged) {\r\n\t\t\tthis.fire('zoomend');\r\n\t\t}\r\n\r\n\t\t// @event moveend: Event\r\n\t\t// Fired when the center of the map stops changing (e.g. user stopped\r\n\t\t// dragging the map).\r\n\t\treturn this.fire('moveend');\r\n\t},\r\n\r\n\t_stop: function () {\r\n\t\tUtil.cancelAnimFrame(this._flyToFrame);\r\n\t\tif (this._panAnim) {\r\n\t\t\tthis._panAnim.stop();\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t_rawPanBy: function (offset) {\r\n\t\tDomUtil.setPosition(this._mapPane, this._getMapPanePos().subtract(offset));\r\n\t},\r\n\r\n\t_getZoomSpan: function () {\r\n\t\treturn this.getMaxZoom() - this.getMinZoom();\r\n\t},\r\n\r\n\t_panInsideMaxBounds: function () {\r\n\t\tif (!this._enforcingBounds) {\r\n\t\t\tthis.panInsideBounds(this.options.maxBounds);\r\n\t\t}\r\n\t},\r\n\r\n\t_checkIfLoaded: function () {\r\n\t\tif (!this._loaded) {\r\n\t\t\tthrow new Error('Set map center and zoom first.');\r\n\t\t}\r\n\t},\r\n\r\n\t// DOM event handling\r\n\r\n\t// @section Interaction events\r\n\t_initEvents: function (remove) {\r\n\t\tthis._targets = {};\r\n\t\tthis._targets[Util.stamp(this._container)] = this;\r\n\r\n\t\tvar onOff = remove ? DomEvent.off : DomEvent.on;\r\n\r\n\t\t// @event click: MouseEvent\r\n\t\t// Fired when the user clicks (or taps) the map.\r\n\t\t// @event dblclick: MouseEvent\r\n\t\t// Fired when the user double-clicks (or double-taps) the map.\r\n\t\t// @event mousedown: MouseEvent\r\n\t\t// Fired when the user pushes the mouse button on the map.\r\n\t\t// @event mouseup: MouseEvent\r\n\t\t// Fired when the user releases the mouse button on the map.\r\n\t\t// @event mouseover: MouseEvent\r\n\t\t// Fired when the mouse enters the map.\r\n\t\t// @event mouseout: MouseEvent\r\n\t\t// Fired when the mouse leaves the map.\r\n\t\t// @event mousemove: MouseEvent\r\n\t\t// Fired while the mouse moves over the map.\r\n\t\t// @event contextmenu: MouseEvent\r\n\t\t// Fired when the user pushes the right mouse button on the map, prevents\r\n\t\t// default browser context menu from showing if there are listeners on\r\n\t\t// this event. Also fired on mobile when the user holds a single touch\r\n\t\t// for a second (also called long press).\r\n\t\t// @event keypress: KeyboardEvent\r\n\t\t// Fired when the user presses a key from the keyboard that produces a character value while the map is focused.\r\n\t\t// @event keydown: KeyboardEvent\r\n\t\t// Fired when the user presses a key from the keyboard while the map is focused. Unlike the `keypress` event,\r\n\t\t// the `keydown` event is fired for keys that produce a character value and for keys\r\n\t\t// that do not produce a character value.\r\n\t\t// @event keyup: KeyboardEvent\r\n\t\t// Fired when the user releases a key from the keyboard while the map is focused.\r\n\t\tonOff(this._container, 'click dblclick mousedown mouseup ' +\r\n\t\t\t'mouseover mouseout mousemove contextmenu keypress keydown keyup', this._handleDOMEvent, this);\r\n\r\n\t\tif (this.options.trackResize) {\r\n\t\t\tonOff(window, 'resize', this._onResize, this);\r\n\t\t}\r\n\r\n\t\tif (Browser.any3d && this.options.transform3DLimit) {\r\n\t\t\t(remove ? this.off : this.on).call(this, 'moveend', this._onMoveEnd);\r\n\t\t}\r\n\t},\r\n\r\n\t_onResize: function () {\r\n\t\tUtil.cancelAnimFrame(this._resizeRequest);\r\n\t\tthis._resizeRequest = Util.requestAnimFrame(\r\n\t\t function () { this.invalidateSize({debounceMoveend: true}); }, this);\r\n\t},\r\n\r\n\t_onScroll: function () {\r\n\t\tthis._container.scrollTop = 0;\r\n\t\tthis._container.scrollLeft = 0;\r\n\t},\r\n\r\n\t_onMoveEnd: function () {\r\n\t\tvar pos = this._getMapPanePos();\r\n\t\tif (Math.max(Math.abs(pos.x), Math.abs(pos.y)) >= this.options.transform3DLimit) {\r\n\t\t\t// https://bugzilla.mozilla.org/show_bug.cgi?id=1203873 but Webkit also have\r\n\t\t\t// a pixel offset on very high values, see: http://jsfiddle.net/dg6r5hhb/\r\n\t\t\tthis._resetView(this.getCenter(), this.getZoom());\r\n\t\t}\r\n\t},\r\n\r\n\t_findEventTargets: function (e, type) {\r\n\t\tvar targets = [],\r\n\t\t target,\r\n\t\t isHover = type === 'mouseout' || type === 'mouseover',\r\n\t\t src = e.target || e.srcElement,\r\n\t\t dragging = false;\r\n\r\n\t\twhile (src) {\r\n\t\t\ttarget = this._targets[Util.stamp(src)];\r\n\t\t\tif (target && (type === 'click' || type === 'preclick') && !e._simulated && this._draggableMoved(target)) {\r\n\t\t\t\t// Prevent firing click after you just dragged an object.\r\n\t\t\t\tdragging = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tif (target && target.listens(type, true)) {\r\n\t\t\t\tif (isHover && !DomEvent.isExternalTarget(src, e)) { break; }\r\n\t\t\t\ttargets.push(target);\r\n\t\t\t\tif (isHover) { break; }\r\n\t\t\t}\r\n\t\t\tif (src === this._container) { break; }\r\n\t\t\tsrc = src.parentNode;\r\n\t\t}\r\n\t\tif (!targets.length && !dragging && !isHover && DomEvent.isExternalTarget(src, e)) {\r\n\t\t\ttargets = [this];\r\n\t\t}\r\n\t\treturn targets;\r\n\t},\r\n\r\n\t_handleDOMEvent: function (e) {\r\n\t\tif (!this._loaded || DomEvent.skipped(e)) { return; }\r\n\r\n\t\tvar type = e.type;\r\n\r\n\t\tif (type === 'mousedown' || type === 'keypress' || type === 'keyup' || type === 'keydown') {\r\n\t\t\t// prevents outline when clicking on keyboard-focusable element\r\n\t\t\tDomUtil.preventOutline(e.target || e.srcElement);\r\n\t\t}\r\n\r\n\t\tthis._fireDOMEvent(e, type);\r\n\t},\r\n\r\n\t_mouseEvents: ['click', 'dblclick', 'mouseover', 'mouseout', 'contextmenu'],\r\n\r\n\t_fireDOMEvent: function (e, type, targets) {\r\n\r\n\t\tif (e.type === 'click') {\r\n\t\t\t// Fire a synthetic 'preclick' event which propagates up (mainly for closing popups).\r\n\t\t\t// @event preclick: MouseEvent\r\n\t\t\t// Fired before mouse click on the map (sometimes useful when you\r\n\t\t\t// want something to happen on click before any existing click\r\n\t\t\t// handlers start running).\r\n\t\t\tvar synth = Util.extend({}, e);\r\n\t\t\tsynth.type = 'preclick';\r\n\t\t\tthis._fireDOMEvent(synth, synth.type, targets);\r\n\t\t}\r\n\r\n\t\tif (e._stopped) { return; }\r\n\r\n\t\t// Find the layer the event is propagating from and its parents.\r\n\t\ttargets = (targets || []).concat(this._findEventTargets(e, type));\r\n\r\n\t\tif (!targets.length) { return; }\r\n\r\n\t\tvar target = targets[0];\r\n\t\tif (type === 'contextmenu' && target.listens(type, true)) {\r\n\t\t\tDomEvent.preventDefault(e);\r\n\t\t}\r\n\r\n\t\tvar data = {\r\n\t\t\toriginalEvent: e\r\n\t\t};\r\n\r\n\t\tif (e.type !== 'keypress' && e.type !== 'keydown' && e.type !== 'keyup') {\r\n\t\t\tvar isMarker = target.getLatLng && (!target._radius || target._radius <= 10);\r\n\t\t\tdata.containerPoint = isMarker ?\r\n\t\t\t\tthis.latLngToContainerPoint(target.getLatLng()) : this.mouseEventToContainerPoint(e);\r\n\t\t\tdata.layerPoint = this.containerPointToLayerPoint(data.containerPoint);\r\n\t\t\tdata.latlng = isMarker ? target.getLatLng() : this.layerPointToLatLng(data.layerPoint);\r\n\t\t}\r\n\r\n\t\tfor (var i = 0; i < targets.length; i++) {\r\n\t\t\ttargets[i].fire(type, data, true);\r\n\t\t\tif (data.originalEvent._stopped ||\r\n\t\t\t\t(targets[i].options.bubblingMouseEvents === false && Util.indexOf(this._mouseEvents, type) !== -1)) { return; }\r\n\t\t}\r\n\t},\r\n\r\n\t_draggableMoved: function (obj) {\r\n\t\tobj = obj.dragging && obj.dragging.enabled() ? obj : this;\r\n\t\treturn (obj.dragging && obj.dragging.moved()) || (this.boxZoom && this.boxZoom.moved());\r\n\t},\r\n\r\n\t_clearHandlers: function () {\r\n\t\tfor (var i = 0, len = this._handlers.length; i < len; i++) {\r\n\t\t\tthis._handlers[i].disable();\r\n\t\t}\r\n\t},\r\n\r\n\t// @section Other Methods\r\n\r\n\t// @method whenReady(fn: Function, context?: Object): this\r\n\t// Runs the given function `fn` when the map gets initialized with\r\n\t// a view (center and zoom) and at least one layer, or immediately\r\n\t// if it's already initialized, optionally passing a function context.\r\n\twhenReady: function (callback, context) {\r\n\t\tif (this._loaded) {\r\n\t\t\tcallback.call(context || this, {target: this});\r\n\t\t} else {\r\n\t\t\tthis.on('load', callback, context);\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\r\n\t// private methods for getting map state\r\n\r\n\t_getMapPanePos: function () {\r\n\t\treturn DomUtil.getPosition(this._mapPane) || new Point(0, 0);\r\n\t},\r\n\r\n\t_moved: function () {\r\n\t\tvar pos = this._getMapPanePos();\r\n\t\treturn pos && !pos.equals([0, 0]);\r\n\t},\r\n\r\n\t_getTopLeftPoint: function (center, zoom) {\r\n\t\tvar pixelOrigin = center && zoom !== undefined ?\r\n\t\t\tthis._getNewPixelOrigin(center, zoom) :\r\n\t\t\tthis.getPixelOrigin();\r\n\t\treturn pixelOrigin.subtract(this._getMapPanePos());\r\n\t},\r\n\r\n\t_getNewPixelOrigin: function (center, zoom) {\r\n\t\tvar viewHalf = this.getSize()._divideBy(2);\r\n\t\treturn this.project(center, zoom)._subtract(viewHalf)._add(this._getMapPanePos())._round();\r\n\t},\r\n\r\n\t_latLngToNewLayerPoint: function (latlng, zoom, center) {\r\n\t\tvar topLeft = this._getNewPixelOrigin(center, zoom);\r\n\t\treturn this.project(latlng, zoom)._subtract(topLeft);\r\n\t},\r\n\r\n\t_latLngBoundsToNewLayerBounds: function (latLngBounds, zoom, center) {\r\n\t\tvar topLeft = this._getNewPixelOrigin(center, zoom);\r\n\t\treturn toBounds([\r\n\t\t\tthis.project(latLngBounds.getSouthWest(), zoom)._subtract(topLeft),\r\n\t\t\tthis.project(latLngBounds.getNorthWest(), zoom)._subtract(topLeft),\r\n\t\t\tthis.project(latLngBounds.getSouthEast(), zoom)._subtract(topLeft),\r\n\t\t\tthis.project(latLngBounds.getNorthEast(), zoom)._subtract(topLeft)\r\n\t\t]);\r\n\t},\r\n\r\n\t// layer point of the current center\r\n\t_getCenterLayerPoint: function () {\r\n\t\treturn this.containerPointToLayerPoint(this.getSize()._divideBy(2));\r\n\t},\r\n\r\n\t// offset of the specified place to the current center in pixels\r\n\t_getCenterOffset: function (latlng) {\r\n\t\treturn this.latLngToLayerPoint(latlng).subtract(this._getCenterLayerPoint());\r\n\t},\r\n\r\n\t// adjust center for view to get inside bounds\r\n\t_limitCenter: function (center, zoom, bounds) {\r\n\r\n\t\tif (!bounds) { return center; }\r\n\r\n\t\tvar centerPoint = this.project(center, zoom),\r\n\t\t viewHalf = this.getSize().divideBy(2),\r\n\t\t viewBounds = new Bounds(centerPoint.subtract(viewHalf), centerPoint.add(viewHalf)),\r\n\t\t offset = this._getBoundsOffset(viewBounds, bounds, zoom);\r\n\r\n\t\t// If offset is less than a pixel, ignore.\r\n\t\t// This prevents unstable projections from getting into\r\n\t\t// an infinite loop of tiny offsets.\r\n\t\tif (offset.round().equals([0, 0])) {\r\n\t\t\treturn center;\r\n\t\t}\r\n\r\n\t\treturn this.unproject(centerPoint.add(offset), zoom);\r\n\t},\r\n\r\n\t// adjust offset for view to get inside bounds\r\n\t_limitOffset: function (offset, bounds) {\r\n\t\tif (!bounds) { return offset; }\r\n\r\n\t\tvar viewBounds = this.getPixelBounds(),\r\n\t\t newBounds = new Bounds(viewBounds.min.add(offset), viewBounds.max.add(offset));\r\n\r\n\t\treturn offset.add(this._getBoundsOffset(newBounds, bounds));\r\n\t},\r\n\r\n\t// returns offset needed for pxBounds to get inside maxBounds at a specified zoom\r\n\t_getBoundsOffset: function (pxBounds, maxBounds, zoom) {\r\n\t\tvar projectedMaxBounds = toBounds(\r\n\t\t this.project(maxBounds.getNorthEast(), zoom),\r\n\t\t this.project(maxBounds.getSouthWest(), zoom)\r\n\t\t ),\r\n\t\t minOffset = projectedMaxBounds.min.subtract(pxBounds.min),\r\n\t\t maxOffset = projectedMaxBounds.max.subtract(pxBounds.max),\r\n\r\n\t\t dx = this._rebound(minOffset.x, -maxOffset.x),\r\n\t\t dy = this._rebound(minOffset.y, -maxOffset.y);\r\n\r\n\t\treturn new Point(dx, dy);\r\n\t},\r\n\r\n\t_rebound: function (left, right) {\r\n\t\treturn left + right > 0 ?\r\n\t\t\tMath.round(left - right) / 2 :\r\n\t\t\tMath.max(0, Math.ceil(left)) - Math.max(0, Math.floor(right));\r\n\t},\r\n\r\n\t_limitZoom: function (zoom) {\r\n\t\tvar min = this.getMinZoom(),\r\n\t\t max = this.getMaxZoom(),\r\n\t\t snap = Browser.any3d ? this.options.zoomSnap : 1;\r\n\t\tif (snap) {\r\n\t\t\tzoom = Math.round(zoom / snap) * snap;\r\n\t\t}\r\n\t\treturn Math.max(min, Math.min(max, zoom));\r\n\t},\r\n\r\n\t_onPanTransitionStep: function () {\r\n\t\tthis.fire('move');\r\n\t},\r\n\r\n\t_onPanTransitionEnd: function () {\r\n\t\tDomUtil.removeClass(this._mapPane, 'leaflet-pan-anim');\r\n\t\tthis.fire('moveend');\r\n\t},\r\n\r\n\t_tryAnimatedPan: function (center, options) {\r\n\t\t// difference between the new and current centers in pixels\r\n\t\tvar offset = this._getCenterOffset(center)._trunc();\r\n\r\n\t\t// don't animate too far unless animate: true specified in options\r\n\t\tif ((options && options.animate) !== true && !this.getSize().contains(offset)) { return false; }\r\n\r\n\t\tthis.panBy(offset, options);\r\n\r\n\t\treturn true;\r\n\t},\r\n\r\n\t_createAnimProxy: function () {\r\n\r\n\t\tvar proxy = this._proxy = DomUtil.create('div', 'leaflet-proxy leaflet-zoom-animated');\r\n\t\tthis._panes.mapPane.appendChild(proxy);\r\n\r\n\t\tthis.on('zoomanim', function (e) {\r\n\t\t\tvar prop = DomUtil.TRANSFORM,\r\n\t\t\t transform = this._proxy.style[prop];\r\n\r\n\t\t\tDomUtil.setTransform(this._proxy, this.project(e.center, e.zoom), this.getZoomScale(e.zoom, 1));\r\n\r\n\t\t\t// workaround for case when transform is the same and so transitionend event is not fired\r\n\t\t\tif (transform === this._proxy.style[prop] && this._animatingZoom) {\r\n\t\t\t\tthis._onZoomTransitionEnd();\r\n\t\t\t}\r\n\t\t}, this);\r\n\r\n\t\tthis.on('load moveend', this._animMoveEnd, this);\r\n\r\n\t\tthis._on('unload', this._destroyAnimProxy, this);\r\n\t},\r\n\r\n\t_destroyAnimProxy: function () {\r\n\t\tDomUtil.remove(this._proxy);\r\n\t\tthis.off('load moveend', this._animMoveEnd, this);\r\n\t\tdelete this._proxy;\r\n\t},\r\n\r\n\t_animMoveEnd: function () {\r\n\t\tvar c = this.getCenter(),\r\n\t\t z = this.getZoom();\r\n\t\tDomUtil.setTransform(this._proxy, this.project(c, z), this.getZoomScale(z, 1));\r\n\t},\r\n\r\n\t_catchTransitionEnd: function (e) {\r\n\t\tif (this._animatingZoom && e.propertyName.indexOf('transform') >= 0) {\r\n\t\t\tthis._onZoomTransitionEnd();\r\n\t\t}\r\n\t},\r\n\r\n\t_nothingToAnimate: function () {\r\n\t\treturn !this._container.getElementsByClassName('leaflet-zoom-animated').length;\r\n\t},\r\n\r\n\t_tryAnimatedZoom: function (center, zoom, options) {\r\n\r\n\t\tif (this._animatingZoom) { return true; }\r\n\r\n\t\toptions = options || {};\r\n\r\n\t\t// don't animate if disabled, not supported or zoom difference is too large\r\n\t\tif (!this._zoomAnimated || options.animate === false || this._nothingToAnimate() ||\r\n\t\t Math.abs(zoom - this._zoom) > this.options.zoomAnimationThreshold) { return false; }\r\n\r\n\t\t// offset is the pixel coords of the zoom origin relative to the current center\r\n\t\tvar scale = this.getZoomScale(zoom),\r\n\t\t offset = this._getCenterOffset(center)._divideBy(1 - 1 / scale);\r\n\r\n\t\t// don't animate if the zoom origin isn't within one screen from the current center, unless forced\r\n\t\tif (options.animate !== true && !this.getSize().contains(offset)) { return false; }\r\n\r\n\t\tUtil.requestAnimFrame(function () {\r\n\t\t\tthis\r\n\t\t\t ._moveStart(true, false)\r\n\t\t\t ._animateZoom(center, zoom, true);\r\n\t\t}, this);\r\n\r\n\t\treturn true;\r\n\t},\r\n\r\n\t_animateZoom: function (center, zoom, startAnim, noUpdate) {\r\n\t\tif (!this._mapPane) { return; }\r\n\r\n\t\tif (startAnim) {\r\n\t\t\tthis._animatingZoom = true;\r\n\r\n\t\t\t// remember what center/zoom to set after animation\r\n\t\t\tthis._animateToCenter = center;\r\n\t\t\tthis._animateToZoom = zoom;\r\n\r\n\t\t\tDomUtil.addClass(this._mapPane, 'leaflet-zoom-anim');\r\n\t\t}\r\n\r\n\t\t// @section Other Events\r\n\t\t// @event zoomanim: ZoomAnimEvent\r\n\t\t// Fired at least once per zoom animation. For continuous zoom, like pinch zooming, fired once per frame during zoom.\r\n\t\tthis.fire('zoomanim', {\r\n\t\t\tcenter: center,\r\n\t\t\tzoom: zoom,\r\n\t\t\tnoUpdate: noUpdate\r\n\t\t});\r\n\r\n\t\t// Work around webkit not firing 'transitionend', see https://github.com/Leaflet/Leaflet/issues/3689, 2693\r\n\t\tsetTimeout(Util.bind(this._onZoomTransitionEnd, this), 250);\r\n\t},\r\n\r\n\t_onZoomTransitionEnd: function () {\r\n\t\tif (!this._animatingZoom) { return; }\r\n\r\n\t\tif (this._mapPane) {\r\n\t\t\tDomUtil.removeClass(this._mapPane, 'leaflet-zoom-anim');\r\n\t\t}\r\n\r\n\t\tthis._animatingZoom = false;\r\n\r\n\t\tthis._move(this._animateToCenter, this._animateToZoom);\r\n\r\n\t\t// This anim frame should prevent an obscure iOS webkit tile loading race condition.\r\n\t\tUtil.requestAnimFrame(function () {\r\n\t\t\tthis._moveEnd(true);\r\n\t\t}, this);\r\n\t}\r\n});\r\n\r\n// @section\r\n\r\n// @factory L.map(id: String, options?: Map options)\r\n// Instantiates a map object given the DOM ID of a `
` element\r\n// and optionally an object literal with `Map options`.\r\n//\r\n// @alternative\r\n// @factory L.map(el: HTMLElement, options?: Map options)\r\n// Instantiates a map object given an instance of a `
` HTML element\r\n// and optionally an object literal with `Map options`.\r\nexport function createMap(id, options) {\r\n\treturn new Map(id, options);\r\n}\r\n","\r\nimport {Class} from '../core/Class';\r\nimport {Map} from '../map/Map';\r\nimport * as Util from '../core/Util';\r\nimport * as DomUtil from '../dom/DomUtil';\r\n\r\n/*\r\n * @class Control\r\n * @aka L.Control\r\n * @inherits Class\r\n *\r\n * L.Control is a base class for implementing map controls. Handles positioning.\r\n * All other controls extend from this class.\r\n */\r\n\r\nexport var Control = Class.extend({\r\n\t// @section\r\n\t// @aka Control options\r\n\toptions: {\r\n\t\t// @option position: String = 'topright'\r\n\t\t// The position of the control (one of the map corners). Possible values are `'topleft'`,\r\n\t\t// `'topright'`, `'bottomleft'` or `'bottomright'`\r\n\t\tposition: 'topright'\r\n\t},\r\n\r\n\tinitialize: function (options) {\r\n\t\tUtil.setOptions(this, options);\r\n\t},\r\n\r\n\t/* @section\r\n\t * Classes extending L.Control will inherit the following methods:\r\n\t *\r\n\t * @method getPosition: string\r\n\t * Returns the position of the control.\r\n\t */\r\n\tgetPosition: function () {\r\n\t\treturn this.options.position;\r\n\t},\r\n\r\n\t// @method setPosition(position: string): this\r\n\t// Sets the position of the control.\r\n\tsetPosition: function (position) {\r\n\t\tvar map = this._map;\r\n\r\n\t\tif (map) {\r\n\t\t\tmap.removeControl(this);\r\n\t\t}\r\n\r\n\t\tthis.options.position = position;\r\n\r\n\t\tif (map) {\r\n\t\t\tmap.addControl(this);\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method getContainer: HTMLElement\r\n\t// Returns the HTMLElement that contains the control.\r\n\tgetContainer: function () {\r\n\t\treturn this._container;\r\n\t},\r\n\r\n\t// @method addTo(map: Map): this\r\n\t// Adds the control to the given map.\r\n\taddTo: function (map) {\r\n\t\tthis.remove();\r\n\t\tthis._map = map;\r\n\r\n\t\tvar container = this._container = this.onAdd(map),\r\n\t\t pos = this.getPosition(),\r\n\t\t corner = map._controlCorners[pos];\r\n\r\n\t\tDomUtil.addClass(container, 'leaflet-control');\r\n\r\n\t\tif (pos.indexOf('bottom') !== -1) {\r\n\t\t\tcorner.insertBefore(container, corner.firstChild);\r\n\t\t} else {\r\n\t\t\tcorner.appendChild(container);\r\n\t\t}\r\n\r\n\t\tthis._map.on('unload', this.remove, this);\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method remove: this\r\n\t// Removes the control from the map it is currently active on.\r\n\tremove: function () {\r\n\t\tif (!this._map) {\r\n\t\t\treturn this;\r\n\t\t}\r\n\r\n\t\tDomUtil.remove(this._container);\r\n\r\n\t\tif (this.onRemove) {\r\n\t\t\tthis.onRemove(this._map);\r\n\t\t}\r\n\r\n\t\tthis._map.off('unload', this.remove, this);\r\n\t\tthis._map = null;\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t_refocusOnMap: function (e) {\r\n\t\t// if map exists and event is not a keyboard event\r\n\t\tif (this._map && e && e.screenX > 0 && e.screenY > 0) {\r\n\t\t\tthis._map.getContainer().focus();\r\n\t\t}\r\n\t}\r\n});\r\n\r\nexport var control = function (options) {\r\n\treturn new Control(options);\r\n};\r\n\r\n/* @section Extension methods\r\n * @uninheritable\r\n *\r\n * Every control should extend from `L.Control` and (re-)implement the following methods.\r\n *\r\n * @method onAdd(map: Map): HTMLElement\r\n * Should return the container DOM element for the control and add listeners on relevant map events. Called on [`control.addTo(map)`](#control-addTo).\r\n *\r\n * @method onRemove(map: Map)\r\n * Optional method. Should contain all clean up code that removes the listeners previously added in [`onAdd`](#control-onadd). Called on [`control.remove()`](#control-remove).\r\n */\r\n\r\n/* @namespace Map\r\n * @section Methods for Layers and Controls\r\n */\r\nMap.include({\r\n\t// @method addControl(control: Control): this\r\n\t// Adds the given control to the map\r\n\taddControl: function (control) {\r\n\t\tcontrol.addTo(this);\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method removeControl(control: Control): this\r\n\t// Removes the given control from the map\r\n\tremoveControl: function (control) {\r\n\t\tcontrol.remove();\r\n\t\treturn this;\r\n\t},\r\n\r\n\t_initControlPos: function () {\r\n\t\tvar corners = this._controlCorners = {},\r\n\t\t l = 'leaflet-',\r\n\t\t container = this._controlContainer =\r\n\t\t DomUtil.create('div', l + 'control-container', this._container);\r\n\r\n\t\tfunction createCorner(vSide, hSide) {\r\n\t\t\tvar className = l + vSide + ' ' + l + hSide;\r\n\r\n\t\t\tcorners[vSide + hSide] = DomUtil.create('div', className, container);\r\n\t\t}\r\n\r\n\t\tcreateCorner('top', 'left');\r\n\t\tcreateCorner('top', 'right');\r\n\t\tcreateCorner('bottom', 'left');\r\n\t\tcreateCorner('bottom', 'right');\r\n\t},\r\n\r\n\t_clearControlPos: function () {\r\n\t\tfor (var i in this._controlCorners) {\r\n\t\t\tDomUtil.remove(this._controlCorners[i]);\r\n\t\t}\r\n\t\tDomUtil.remove(this._controlContainer);\r\n\t\tdelete this._controlCorners;\r\n\t\tdelete this._controlContainer;\r\n\t}\r\n});\r\n","\r\nimport {Control} from './Control';\r\nimport * as Util from '../core/Util';\r\nimport * as Browser from '../core/Browser';\r\nimport * as DomEvent from '../dom/DomEvent';\r\nimport * as DomUtil from '../dom/DomUtil';\r\n\r\n/*\r\n * @class Control.Layers\r\n * @aka L.Control.Layers\r\n * @inherits Control\r\n *\r\n * The layers control gives users the ability to switch between different base layers and switch overlays on/off (check out the [detailed example](http://leafletjs.com/examples/layers-control/)). Extends `Control`.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * var baseLayers = {\r\n * \t\"Mapbox\": mapbox,\r\n * \t\"OpenStreetMap\": osm\r\n * };\r\n *\r\n * var overlays = {\r\n * \t\"Marker\": marker,\r\n * \t\"Roads\": roadsLayer\r\n * };\r\n *\r\n * L.control.layers(baseLayers, overlays).addTo(map);\r\n * ```\r\n *\r\n * The `baseLayers` and `overlays` parameters are object literals with layer names as keys and `Layer` objects as values:\r\n *\r\n * ```js\r\n * {\r\n * \"\": layer1,\r\n * \"\": layer2\r\n * }\r\n * ```\r\n *\r\n * The layer names can contain HTML, which allows you to add additional styling to the items:\r\n *\r\n * ```js\r\n * {\" My Layer\": myLayer}\r\n * ```\r\n */\r\n\r\nexport var Layers = Control.extend({\r\n\t// @section\r\n\t// @aka Control.Layers options\r\n\toptions: {\r\n\t\t// @option collapsed: Boolean = true\r\n\t\t// If `true`, the control will be collapsed into an icon and expanded on mouse hover or touch.\r\n\t\tcollapsed: true,\r\n\t\tposition: 'topright',\r\n\r\n\t\t// @option autoZIndex: Boolean = true\r\n\t\t// If `true`, the control will assign zIndexes in increasing order to all of its layers so that the order is preserved when switching them on/off.\r\n\t\tautoZIndex: true,\r\n\r\n\t\t// @option hideSingleBase: Boolean = false\r\n\t\t// If `true`, the base layers in the control will be hidden when there is only one.\r\n\t\thideSingleBase: false,\r\n\r\n\t\t// @option sortLayers: Boolean = false\r\n\t\t// Whether to sort the layers. When `false`, layers will keep the order\r\n\t\t// in which they were added to the control.\r\n\t\tsortLayers: false,\r\n\r\n\t\t// @option sortFunction: Function = *\r\n\t\t// A [compare function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)\r\n\t\t// that will be used for sorting the layers, when `sortLayers` is `true`.\r\n\t\t// The function receives both the `L.Layer` instances and their names, as in\r\n\t\t// `sortFunction(layerA, layerB, nameA, nameB)`.\r\n\t\t// By default, it sorts layers alphabetically by their name.\r\n\t\tsortFunction: function (layerA, layerB, nameA, nameB) {\r\n\t\t\treturn nameA < nameB ? -1 : (nameB < nameA ? 1 : 0);\r\n\t\t}\r\n\t},\r\n\r\n\tinitialize: function (baseLayers, overlays, options) {\r\n\t\tUtil.setOptions(this, options);\r\n\r\n\t\tthis._layerControlInputs = [];\r\n\t\tthis._layers = [];\r\n\t\tthis._lastZIndex = 0;\r\n\t\tthis._handlingClick = false;\r\n\r\n\t\tfor (var i in baseLayers) {\r\n\t\t\tthis._addLayer(baseLayers[i], i);\r\n\t\t}\r\n\r\n\t\tfor (i in overlays) {\r\n\t\t\tthis._addLayer(overlays[i], i, true);\r\n\t\t}\r\n\t},\r\n\r\n\tonAdd: function (map) {\r\n\t\tthis._initLayout();\r\n\t\tthis._update();\r\n\r\n\t\tthis._map = map;\r\n\t\tmap.on('zoomend', this._checkDisabledLayers, this);\r\n\r\n\t\tfor (var i = 0; i < this._layers.length; i++) {\r\n\t\t\tthis._layers[i].layer.on('add remove', this._onLayerChange, this);\r\n\t\t}\r\n\r\n\t\treturn this._container;\r\n\t},\r\n\r\n\taddTo: function (map) {\r\n\t\tControl.prototype.addTo.call(this, map);\r\n\t\t// Trigger expand after Layers Control has been inserted into DOM so that is now has an actual height.\r\n\t\treturn this._expandIfNotCollapsed();\r\n\t},\r\n\r\n\tonRemove: function () {\r\n\t\tthis._map.off('zoomend', this._checkDisabledLayers, this);\r\n\r\n\t\tfor (var i = 0; i < this._layers.length; i++) {\r\n\t\t\tthis._layers[i].layer.off('add remove', this._onLayerChange, this);\r\n\t\t}\r\n\t},\r\n\r\n\t// @method addBaseLayer(layer: Layer, name: String): this\r\n\t// Adds a base layer (radio button entry) with the given name to the control.\r\n\taddBaseLayer: function (layer, name) {\r\n\t\tthis._addLayer(layer, name);\r\n\t\treturn (this._map) ? this._update() : this;\r\n\t},\r\n\r\n\t// @method addOverlay(layer: Layer, name: String): this\r\n\t// Adds an overlay (checkbox entry) with the given name to the control.\r\n\taddOverlay: function (layer, name) {\r\n\t\tthis._addLayer(layer, name, true);\r\n\t\treturn (this._map) ? this._update() : this;\r\n\t},\r\n\r\n\t// @method removeLayer(layer: Layer): this\r\n\t// Remove the given layer from the control.\r\n\tremoveLayer: function (layer) {\r\n\t\tlayer.off('add remove', this._onLayerChange, this);\r\n\r\n\t\tvar obj = this._getLayer(Util.stamp(layer));\r\n\t\tif (obj) {\r\n\t\t\tthis._layers.splice(this._layers.indexOf(obj), 1);\r\n\t\t}\r\n\t\treturn (this._map) ? this._update() : this;\r\n\t},\r\n\r\n\t// @method expand(): this\r\n\t// Expand the control container if collapsed.\r\n\texpand: function () {\r\n\t\tDomUtil.addClass(this._container, 'leaflet-control-layers-expanded');\r\n\t\tthis._section.style.height = null;\r\n\t\tvar acceptableHeight = this._map.getSize().y - (this._container.offsetTop + 50);\r\n\t\tif (acceptableHeight < this._section.clientHeight) {\r\n\t\t\tDomUtil.addClass(this._section, 'leaflet-control-layers-scrollbar');\r\n\t\t\tthis._section.style.height = acceptableHeight + 'px';\r\n\t\t} else {\r\n\t\t\tDomUtil.removeClass(this._section, 'leaflet-control-layers-scrollbar');\r\n\t\t}\r\n\t\tthis._checkDisabledLayers();\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method collapse(): this\r\n\t// Collapse the control container if expanded.\r\n\tcollapse: function () {\r\n\t\tDomUtil.removeClass(this._container, 'leaflet-control-layers-expanded');\r\n\t\treturn this;\r\n\t},\r\n\r\n\t_initLayout: function () {\r\n\t\tvar className = 'leaflet-control-layers',\r\n\t\t container = this._container = DomUtil.create('div', className),\r\n\t\t collapsed = this.options.collapsed;\r\n\r\n\t\t// makes this work on IE touch devices by stopping it from firing a mouseout event when the touch is released\r\n\t\tcontainer.setAttribute('aria-haspopup', true);\r\n\r\n\t\tDomEvent.disableClickPropagation(container);\r\n\t\tDomEvent.disableScrollPropagation(container);\r\n\r\n\t\tvar section = this._section = DomUtil.create('section', className + '-list');\r\n\r\n\t\tif (collapsed) {\r\n\t\t\tthis._map.on('click', this.collapse, this);\r\n\r\n\t\t\tif (!Browser.android) {\r\n\t\t\t\tDomEvent.on(container, {\r\n\t\t\t\t\tmouseenter: this.expand,\r\n\t\t\t\t\tmouseleave: this.collapse\r\n\t\t\t\t}, this);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tvar link = this._layersLink = DomUtil.create('a', className + '-toggle', container);\r\n\t\tlink.href = '#';\r\n\t\tlink.title = 'Layers';\r\n\r\n\t\tif (Browser.touch) {\r\n\t\t\tDomEvent.on(link, 'click', DomEvent.stop);\r\n\t\t\tDomEvent.on(link, 'click', this.expand, this);\r\n\t\t} else {\r\n\t\t\tDomEvent.on(link, 'focus', this.expand, this);\r\n\t\t}\r\n\r\n\t\tif (!collapsed) {\r\n\t\t\tthis.expand();\r\n\t\t}\r\n\r\n\t\tthis._baseLayersList = DomUtil.create('div', className + '-base', section);\r\n\t\tthis._separator = DomUtil.create('div', className + '-separator', section);\r\n\t\tthis._overlaysList = DomUtil.create('div', className + '-overlays', section);\r\n\r\n\t\tcontainer.appendChild(section);\r\n\t},\r\n\r\n\t_getLayer: function (id) {\r\n\t\tfor (var i = 0; i < this._layers.length; i++) {\r\n\r\n\t\t\tif (this._layers[i] && Util.stamp(this._layers[i].layer) === id) {\r\n\t\t\t\treturn this._layers[i];\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\t_addLayer: function (layer, name, overlay) {\r\n\t\tif (this._map) {\r\n\t\t\tlayer.on('add remove', this._onLayerChange, this);\r\n\t\t}\r\n\r\n\t\tthis._layers.push({\r\n\t\t\tlayer: layer,\r\n\t\t\tname: name,\r\n\t\t\toverlay: overlay\r\n\t\t});\r\n\r\n\t\tif (this.options.sortLayers) {\r\n\t\t\tthis._layers.sort(Util.bind(function (a, b) {\r\n\t\t\t\treturn this.options.sortFunction(a.layer, b.layer, a.name, b.name);\r\n\t\t\t}, this));\r\n\t\t}\r\n\r\n\t\tif (this.options.autoZIndex && layer.setZIndex) {\r\n\t\t\tthis._lastZIndex++;\r\n\t\t\tlayer.setZIndex(this._lastZIndex);\r\n\t\t}\r\n\r\n\t\tthis._expandIfNotCollapsed();\r\n\t},\r\n\r\n\t_update: function () {\r\n\t\tif (!this._container) { return this; }\r\n\r\n\t\tDomUtil.empty(this._baseLayersList);\r\n\t\tDomUtil.empty(this._overlaysList);\r\n\r\n\t\tthis._layerControlInputs = [];\r\n\t\tvar baseLayersPresent, overlaysPresent, i, obj, baseLayersCount = 0;\r\n\r\n\t\tfor (i = 0; i < this._layers.length; i++) {\r\n\t\t\tobj = this._layers[i];\r\n\t\t\tthis._addItem(obj);\r\n\t\t\toverlaysPresent = overlaysPresent || obj.overlay;\r\n\t\t\tbaseLayersPresent = baseLayersPresent || !obj.overlay;\r\n\t\t\tbaseLayersCount += !obj.overlay ? 1 : 0;\r\n\t\t}\r\n\r\n\t\t// Hide base layers section if there's only one layer.\r\n\t\tif (this.options.hideSingleBase) {\r\n\t\t\tbaseLayersPresent = baseLayersPresent && baseLayersCount > 1;\r\n\t\t\tthis._baseLayersList.style.display = baseLayersPresent ? '' : 'none';\r\n\t\t}\r\n\r\n\t\tthis._separator.style.display = overlaysPresent && baseLayersPresent ? '' : 'none';\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t_onLayerChange: function (e) {\r\n\t\tif (!this._handlingClick) {\r\n\t\t\tthis._update();\r\n\t\t}\r\n\r\n\t\tvar obj = this._getLayer(Util.stamp(e.target));\r\n\r\n\t\t// @namespace Map\r\n\t\t// @section Layer events\r\n\t\t// @event baselayerchange: LayersControlEvent\r\n\t\t// Fired when the base layer is changed through the [layer control](#control-layers).\r\n\t\t// @event overlayadd: LayersControlEvent\r\n\t\t// Fired when an overlay is selected through the [layer control](#control-layers).\r\n\t\t// @event overlayremove: LayersControlEvent\r\n\t\t// Fired when an overlay is deselected through the [layer control](#control-layers).\r\n\t\t// @namespace Control.Layers\r\n\t\tvar type = obj.overlay ?\r\n\t\t\t(e.type === 'add' ? 'overlayadd' : 'overlayremove') :\r\n\t\t\t(e.type === 'add' ? 'baselayerchange' : null);\r\n\r\n\t\tif (type) {\r\n\t\t\tthis._map.fire(type, obj);\r\n\t\t}\r\n\t},\r\n\r\n\t// IE7 bugs out if you create a radio dynamically, so you have to do it this hacky way (see http://bit.ly/PqYLBe)\r\n\t_createRadioElement: function (name, checked) {\r\n\r\n\t\tvar radioHtml = '';\r\n\r\n\t\tvar radioFragment = document.createElement('div');\r\n\t\tradioFragment.innerHTML = radioHtml;\r\n\r\n\t\treturn radioFragment.firstChild;\r\n\t},\r\n\r\n\t_addItem: function (obj) {\r\n\t\tvar label = document.createElement('label'),\r\n\t\t checked = this._map.hasLayer(obj.layer),\r\n\t\t input;\r\n\r\n\t\tif (obj.overlay) {\r\n\t\t\tinput = document.createElement('input');\r\n\t\t\tinput.type = 'checkbox';\r\n\t\t\tinput.className = 'leaflet-control-layers-selector';\r\n\t\t\tinput.defaultChecked = checked;\r\n\t\t} else {\r\n\t\t\tinput = this._createRadioElement('leaflet-base-layers_' + Util.stamp(this), checked);\r\n\t\t}\r\n\r\n\t\tthis._layerControlInputs.push(input);\r\n\t\tinput.layerId = Util.stamp(obj.layer);\r\n\r\n\t\tDomEvent.on(input, 'click', this._onInputClick, this);\r\n\r\n\t\tvar name = document.createElement('span');\r\n\t\tname.innerHTML = ' ' + obj.name;\r\n\r\n\t\t// Helps from preventing layer control flicker when checkboxes are disabled\r\n\t\t// https://github.com/Leaflet/Leaflet/issues/2771\r\n\t\tvar holder = document.createElement('div');\r\n\r\n\t\tlabel.appendChild(holder);\r\n\t\tholder.appendChild(input);\r\n\t\tholder.appendChild(name);\r\n\r\n\t\tvar container = obj.overlay ? this._overlaysList : this._baseLayersList;\r\n\t\tcontainer.appendChild(label);\r\n\r\n\t\tthis._checkDisabledLayers();\r\n\t\treturn label;\r\n\t},\r\n\r\n\t_onInputClick: function () {\r\n\t\tvar inputs = this._layerControlInputs,\r\n\t\t input, layer;\r\n\t\tvar addedLayers = [],\r\n\t\t removedLayers = [];\r\n\r\n\t\tthis._handlingClick = true;\r\n\r\n\t\tfor (var i = inputs.length - 1; i >= 0; i--) {\r\n\t\t\tinput = inputs[i];\r\n\t\t\tlayer = this._getLayer(input.layerId).layer;\r\n\r\n\t\t\tif (input.checked) {\r\n\t\t\t\taddedLayers.push(layer);\r\n\t\t\t} else if (!input.checked) {\r\n\t\t\t\tremovedLayers.push(layer);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Bugfix issue 2318: Should remove all old layers before readding new ones\r\n\t\tfor (i = 0; i < removedLayers.length; i++) {\r\n\t\t\tif (this._map.hasLayer(removedLayers[i])) {\r\n\t\t\t\tthis._map.removeLayer(removedLayers[i]);\r\n\t\t\t}\r\n\t\t}\r\n\t\tfor (i = 0; i < addedLayers.length; i++) {\r\n\t\t\tif (!this._map.hasLayer(addedLayers[i])) {\r\n\t\t\t\tthis._map.addLayer(addedLayers[i]);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis._handlingClick = false;\r\n\r\n\t\tthis._refocusOnMap();\r\n\t},\r\n\r\n\t_checkDisabledLayers: function () {\r\n\t\tvar inputs = this._layerControlInputs,\r\n\t\t input,\r\n\t\t layer,\r\n\t\t zoom = this._map.getZoom();\r\n\r\n\t\tfor (var i = inputs.length - 1; i >= 0; i--) {\r\n\t\t\tinput = inputs[i];\r\n\t\t\tlayer = this._getLayer(input.layerId).layer;\r\n\t\t\tinput.disabled = (layer.options.minZoom !== undefined && zoom < layer.options.minZoom) ||\r\n\t\t\t (layer.options.maxZoom !== undefined && zoom > layer.options.maxZoom);\r\n\r\n\t\t}\r\n\t},\r\n\r\n\t_expandIfNotCollapsed: function () {\r\n\t\tif (this._map && !this.options.collapsed) {\r\n\t\t\tthis.expand();\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t_expand: function () {\r\n\t\t// Backward compatibility, remove me in 1.1.\r\n\t\treturn this.expand();\r\n\t},\r\n\r\n\t_collapse: function () {\r\n\t\t// Backward compatibility, remove me in 1.1.\r\n\t\treturn this.collapse();\r\n\t}\r\n\r\n});\r\n\r\n\r\n// @factory L.control.layers(baselayers?: Object, overlays?: Object, options?: Control.Layers options)\r\n// Creates a layers control with the given layers. Base layers will be switched with radio buttons, while overlays will be switched with checkboxes. Note that all base layers should be passed in the base layers object, but only one should be added to the map during map instantiation.\r\nexport var layers = function (baseLayers, overlays, options) {\r\n\treturn new Layers(baseLayers, overlays, options);\r\n};\r\n","\r\nimport {Control} from './Control';\r\nimport {Map} from '../map/Map';\r\nimport * as DomUtil from '../dom/DomUtil';\r\nimport * as DomEvent from '../dom/DomEvent';\r\n\r\n/*\r\n * @class Control.Zoom\r\n * @aka L.Control.Zoom\r\n * @inherits Control\r\n *\r\n * A basic zoom control with two buttons (zoom in and zoom out). It is put on the map by default unless you set its [`zoomControl` option](#map-zoomcontrol) to `false`. Extends `Control`.\r\n */\r\n\r\nexport var Zoom = Control.extend({\r\n\t// @section\r\n\t// @aka Control.Zoom options\r\n\toptions: {\r\n\t\tposition: 'topleft',\r\n\r\n\t\t// @option zoomInText: String = '+'\r\n\t\t// The text set on the 'zoom in' button.\r\n\t\tzoomInText: '+',\r\n\r\n\t\t// @option zoomInTitle: String = 'Zoom in'\r\n\t\t// The title set on the 'zoom in' button.\r\n\t\tzoomInTitle: 'Zoom in',\r\n\r\n\t\t// @option zoomOutText: String = '−'\r\n\t\t// The text set on the 'zoom out' button.\r\n\t\tzoomOutText: '−',\r\n\r\n\t\t// @option zoomOutTitle: String = 'Zoom out'\r\n\t\t// The title set on the 'zoom out' button.\r\n\t\tzoomOutTitle: 'Zoom out'\r\n\t},\r\n\r\n\tonAdd: function (map) {\r\n\t\tvar zoomName = 'leaflet-control-zoom',\r\n\t\t container = DomUtil.create('div', zoomName + ' leaflet-bar'),\r\n\t\t options = this.options;\r\n\r\n\t\tthis._zoomInButton = this._createButton(options.zoomInText, options.zoomInTitle,\r\n\t\t zoomName + '-in', container, this._zoomIn);\r\n\t\tthis._zoomOutButton = this._createButton(options.zoomOutText, options.zoomOutTitle,\r\n\t\t zoomName + '-out', container, this._zoomOut);\r\n\r\n\t\tthis._updateDisabled();\r\n\t\tmap.on('zoomend zoomlevelschange', this._updateDisabled, this);\r\n\r\n\t\treturn container;\r\n\t},\r\n\r\n\tonRemove: function (map) {\r\n\t\tmap.off('zoomend zoomlevelschange', this._updateDisabled, this);\r\n\t},\r\n\r\n\tdisable: function () {\r\n\t\tthis._disabled = true;\r\n\t\tthis._updateDisabled();\r\n\t\treturn this;\r\n\t},\r\n\r\n\tenable: function () {\r\n\t\tthis._disabled = false;\r\n\t\tthis._updateDisabled();\r\n\t\treturn this;\r\n\t},\r\n\r\n\t_zoomIn: function (e) {\r\n\t\tif (!this._disabled && this._map._zoom < this._map.getMaxZoom()) {\r\n\t\t\tthis._map.zoomIn(this._map.options.zoomDelta * (e.shiftKey ? 3 : 1));\r\n\t\t}\r\n\t},\r\n\r\n\t_zoomOut: function (e) {\r\n\t\tif (!this._disabled && this._map._zoom > this._map.getMinZoom()) {\r\n\t\t\tthis._map.zoomOut(this._map.options.zoomDelta * (e.shiftKey ? 3 : 1));\r\n\t\t}\r\n\t},\r\n\r\n\t_createButton: function (html, title, className, container, fn) {\r\n\t\tvar link = DomUtil.create('a', className, container);\r\n\t\tlink.innerHTML = html;\r\n\t\tlink.href = '#';\r\n\t\tlink.title = title;\r\n\r\n\t\t/*\r\n\t\t * Will force screen readers like VoiceOver to read this as \"Zoom in - button\"\r\n\t\t */\r\n\t\tlink.setAttribute('role', 'button');\r\n\t\tlink.setAttribute('aria-label', title);\r\n\r\n\t\tDomEvent.disableClickPropagation(link);\r\n\t\tDomEvent.on(link, 'click', DomEvent.stop);\r\n\t\tDomEvent.on(link, 'click', fn, this);\r\n\t\tDomEvent.on(link, 'click', this._refocusOnMap, this);\r\n\r\n\t\treturn link;\r\n\t},\r\n\r\n\t_updateDisabled: function () {\r\n\t\tvar map = this._map,\r\n\t\t className = 'leaflet-disabled';\r\n\r\n\t\tDomUtil.removeClass(this._zoomInButton, className);\r\n\t\tDomUtil.removeClass(this._zoomOutButton, className);\r\n\r\n\t\tif (this._disabled || map._zoom === map.getMinZoom()) {\r\n\t\t\tDomUtil.addClass(this._zoomOutButton, className);\r\n\t\t}\r\n\t\tif (this._disabled || map._zoom === map.getMaxZoom()) {\r\n\t\t\tDomUtil.addClass(this._zoomInButton, className);\r\n\t\t}\r\n\t}\r\n});\r\n\r\n// @namespace Map\r\n// @section Control options\r\n// @option zoomControl: Boolean = true\r\n// Whether a [zoom control](#control-zoom) is added to the map by default.\r\nMap.mergeOptions({\r\n\tzoomControl: true\r\n});\r\n\r\nMap.addInitHook(function () {\r\n\tif (this.options.zoomControl) {\r\n\t\t// @section Controls\r\n\t\t// @property zoomControl: Control.Zoom\r\n\t\t// The default zoom control (only available if the\r\n\t\t// [`zoomControl` option](#map-zoomcontrol) was `true` when creating the map).\r\n\t\tthis.zoomControl = new Zoom();\r\n\t\tthis.addControl(this.zoomControl);\r\n\t}\r\n});\r\n\r\n// @namespace Control.Zoom\r\n// @factory L.control.zoom(options: Control.Zoom options)\r\n// Creates a zoom control\r\nexport var zoom = function (options) {\r\n\treturn new Zoom(options);\r\n};\r\n","\nimport {Control} from './Control';\nimport * as DomUtil from '../dom/DomUtil';\n\n/*\n * @class Control.Scale\n * @aka L.Control.Scale\n * @inherits Control\n *\n * A simple scale control that shows the scale of the current center of screen in metric (m/km) and imperial (mi/ft) systems. Extends `Control`.\n *\n * @example\n *\n * ```js\n * L.control.scale().addTo(map);\n * ```\n */\n\nexport var Scale = Control.extend({\n\t// @section\n\t// @aka Control.Scale options\n\toptions: {\n\t\tposition: 'bottomleft',\n\n\t\t// @option maxWidth: Number = 100\n\t\t// Maximum width of the control in pixels. The width is set dynamically to show round values (e.g. 100, 200, 500).\n\t\tmaxWidth: 100,\n\n\t\t// @option metric: Boolean = True\n\t\t// Whether to show the metric scale line (m/km).\n\t\tmetric: true,\n\n\t\t// @option imperial: Boolean = True\n\t\t// Whether to show the imperial scale line (mi/ft).\n\t\timperial: true\n\n\t\t// @option updateWhenIdle: Boolean = false\n\t\t// If `true`, the control is updated on [`moveend`](#map-moveend), otherwise it's always up-to-date (updated on [`move`](#map-move)).\n\t},\n\n\tonAdd: function (map) {\n\t\tvar className = 'leaflet-control-scale',\n\t\t container = DomUtil.create('div', className),\n\t\t options = this.options;\n\n\t\tthis._addScales(options, className + '-line', container);\n\n\t\tmap.on(options.updateWhenIdle ? 'moveend' : 'move', this._update, this);\n\t\tmap.whenReady(this._update, this);\n\n\t\treturn container;\n\t},\n\n\tonRemove: function (map) {\n\t\tmap.off(this.options.updateWhenIdle ? 'moveend' : 'move', this._update, this);\n\t},\n\n\t_addScales: function (options, className, container) {\n\t\tif (options.metric) {\n\t\t\tthis._mScale = DomUtil.create('div', className, container);\n\t\t}\n\t\tif (options.imperial) {\n\t\t\tthis._iScale = DomUtil.create('div', className, container);\n\t\t}\n\t},\n\n\t_update: function () {\n\t\tvar map = this._map,\n\t\t y = map.getSize().y / 2;\n\n\t\tvar maxMeters = map.distance(\n\t\t\tmap.containerPointToLatLng([0, y]),\n\t\t\tmap.containerPointToLatLng([this.options.maxWidth, y]));\n\n\t\tthis._updateScales(maxMeters);\n\t},\n\n\t_updateScales: function (maxMeters) {\n\t\tif (this.options.metric && maxMeters) {\n\t\t\tthis._updateMetric(maxMeters);\n\t\t}\n\t\tif (this.options.imperial && maxMeters) {\n\t\t\tthis._updateImperial(maxMeters);\n\t\t}\n\t},\n\n\t_updateMetric: function (maxMeters) {\n\t\tvar meters = this._getRoundNum(maxMeters),\n\t\t label = meters < 1000 ? meters + ' m' : (meters / 1000) + ' km';\n\n\t\tthis._updateScale(this._mScale, label, meters / maxMeters);\n\t},\n\n\t_updateImperial: function (maxMeters) {\n\t\tvar maxFeet = maxMeters * 3.2808399,\n\t\t maxMiles, miles, feet;\n\n\t\tif (maxFeet > 5280) {\n\t\t\tmaxMiles = maxFeet / 5280;\n\t\t\tmiles = this._getRoundNum(maxMiles);\n\t\t\tthis._updateScale(this._iScale, miles + ' mi', miles / maxMiles);\n\n\t\t} else {\n\t\t\tfeet = this._getRoundNum(maxFeet);\n\t\t\tthis._updateScale(this._iScale, feet + ' ft', feet / maxFeet);\n\t\t}\n\t},\n\n\t_updateScale: function (scale, text, ratio) {\n\t\tscale.style.width = Math.round(this.options.maxWidth * ratio) + 'px';\n\t\tscale.innerHTML = text;\n\t},\n\n\t_getRoundNum: function (num) {\n\t\tvar pow10 = Math.pow(10, (Math.floor(num) + '').length - 1),\n\t\t d = num / pow10;\n\n\t\td = d >= 10 ? 10 :\n\t\t d >= 5 ? 5 :\n\t\t d >= 3 ? 3 :\n\t\t d >= 2 ? 2 : 1;\n\n\t\treturn pow10 * d;\n\t}\n});\n\n\n// @factory L.control.scale(options?: Control.Scale options)\n// Creates an scale control with the given options.\nexport var scale = function (options) {\n\treturn new Scale(options);\n};\n","\r\nimport {Control} from './Control';\r\nimport {Map} from '../map/Map';\r\nimport * as Util from '../core/Util';\r\nimport * as DomEvent from '../dom/DomEvent';\r\nimport * as DomUtil from '../dom/DomUtil';\r\n\r\n/*\r\n * @class Control.Attribution\r\n * @aka L.Control.Attribution\r\n * @inherits Control\r\n *\r\n * The attribution control allows you to display attribution data in a small text box on a map. It is put on the map by default unless you set its [`attributionControl` option](#map-attributioncontrol) to `false`, and it fetches attribution texts from layers with the [`getAttribution` method](#layer-getattribution) automatically. Extends Control.\r\n */\r\n\r\nexport var Attribution = Control.extend({\r\n\t// @section\r\n\t// @aka Control.Attribution options\r\n\toptions: {\r\n\t\tposition: 'bottomright',\r\n\r\n\t\t// @option prefix: String = 'Leaflet'\r\n\t\t// The HTML text shown before the attributions. Pass `false` to disable.\r\n\t\tprefix: 'Leaflet'\r\n\t},\r\n\r\n\tinitialize: function (options) {\r\n\t\tUtil.setOptions(this, options);\r\n\r\n\t\tthis._attributions = {};\r\n\t},\r\n\r\n\tonAdd: function (map) {\r\n\t\tmap.attributionControl = this;\r\n\t\tthis._container = DomUtil.create('div', 'leaflet-control-attribution');\r\n\t\tDomEvent.disableClickPropagation(this._container);\r\n\r\n\t\t// TODO ugly, refactor\r\n\t\tfor (var i in map._layers) {\r\n\t\t\tif (map._layers[i].getAttribution) {\r\n\t\t\t\tthis.addAttribution(map._layers[i].getAttribution());\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis._update();\r\n\r\n\t\treturn this._container;\r\n\t},\r\n\r\n\t// @method setPrefix(prefix: String): this\r\n\t// Sets the text before the attributions.\r\n\tsetPrefix: function (prefix) {\r\n\t\tthis.options.prefix = prefix;\r\n\t\tthis._update();\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method addAttribution(text: String): this\r\n\t// Adds an attribution text (e.g. `'Vector data © Mapbox'`).\r\n\taddAttribution: function (text) {\r\n\t\tif (!text) { return this; }\r\n\r\n\t\tif (!this._attributions[text]) {\r\n\t\t\tthis._attributions[text] = 0;\r\n\t\t}\r\n\t\tthis._attributions[text]++;\r\n\r\n\t\tthis._update();\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method removeAttribution(text: String): this\r\n\t// Removes an attribution text.\r\n\tremoveAttribution: function (text) {\r\n\t\tif (!text) { return this; }\r\n\r\n\t\tif (this._attributions[text]) {\r\n\t\t\tthis._attributions[text]--;\r\n\t\t\tthis._update();\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t_update: function () {\r\n\t\tif (!this._map) { return; }\r\n\r\n\t\tvar attribs = [];\r\n\r\n\t\tfor (var i in this._attributions) {\r\n\t\t\tif (this._attributions[i]) {\r\n\t\t\t\tattribs.push(i);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tvar prefixAndAttribs = [];\r\n\r\n\t\tif (this.options.prefix) {\r\n\t\t\tprefixAndAttribs.push(this.options.prefix);\r\n\t\t}\r\n\t\tif (attribs.length) {\r\n\t\t\tprefixAndAttribs.push(attribs.join(', '));\r\n\t\t}\r\n\r\n\t\tthis._container.innerHTML = prefixAndAttribs.join(' | ');\r\n\t}\r\n});\r\n\r\n// @namespace Map\r\n// @section Control options\r\n// @option attributionControl: Boolean = true\r\n// Whether a [attribution control](#control-attribution) is added to the map by default.\r\nMap.mergeOptions({\r\n\tattributionControl: true\r\n});\r\n\r\nMap.addInitHook(function () {\r\n\tif (this.options.attributionControl) {\r\n\t\tnew Attribution().addTo(this);\r\n\t}\r\n});\r\n\r\n// @namespace Control.Attribution\r\n// @factory L.control.attribution(options: Control.Attribution options)\r\n// Creates an attribution control.\r\nexport var attribution = function (options) {\r\n\treturn new Attribution(options);\r\n};\r\n","import {Control, control} from './Control';\nimport {Layers, layers} from './Control.Layers';\nimport {Zoom, zoom} from './Control.Zoom';\nimport {Scale, scale} from './Control.Scale';\nimport {Attribution, attribution} from './Control.Attribution';\n\nControl.Layers = Layers;\nControl.Zoom = Zoom;\nControl.Scale = Scale;\nControl.Attribution = Attribution;\n\ncontrol.layers = layers;\ncontrol.zoom = zoom;\ncontrol.scale = scale;\ncontrol.attribution = attribution;\n\nexport {Control, control};\n","import {Class} from './Class';\n\n/*\n\tL.Handler is a base class for handler classes that are used internally to inject\n\tinteraction features like dragging to classes like Map and Marker.\n*/\n\n// @class Handler\n// @aka L.Handler\n// Abstract class for map interaction handlers\n\nexport var Handler = Class.extend({\n\tinitialize: function (map) {\n\t\tthis._map = map;\n\t},\n\n\t// @method enable(): this\n\t// Enables the handler\n\tenable: function () {\n\t\tif (this._enabled) { return this; }\n\n\t\tthis._enabled = true;\n\t\tthis.addHooks();\n\t\treturn this;\n\t},\n\n\t// @method disable(): this\n\t// Disables the handler\n\tdisable: function () {\n\t\tif (!this._enabled) { return this; }\n\n\t\tthis._enabled = false;\n\t\tthis.removeHooks();\n\t\treturn this;\n\t},\n\n\t// @method enabled(): Boolean\n\t// Returns `true` if the handler is enabled\n\tenabled: function () {\n\t\treturn !!this._enabled;\n\t}\n\n\t// @section Extension methods\n\t// Classes inheriting from `Handler` must implement the two following methods:\n\t// @method addHooks()\n\t// Called when the handler is enabled, should add event hooks.\n\t// @method removeHooks()\n\t// Called when the handler is disabled, should remove the event hooks added previously.\n});\n\n// @section There is static function which can be called without instantiating L.Handler:\n// @function addTo(map: Map, name: String): this\n// Adds a new Handler to the given map with the given name.\nHandler.addTo = function (map, name) {\n\tmap.addHandler(name, this);\n\treturn this;\n};\n","import * as Browser from './Browser';\nexport {Browser};\n\nexport {Class} from './Class';\n\nimport {Evented} from './Events';\nimport {Events} from './Events';\nexport {Evented};\nexport var Mixin = {Events: Events};\n\nexport {Handler} from './Handler';\n\nimport * as Util from './Util';\nexport {Util};\nexport {extend, bind, stamp, setOptions} from './Util';\n","import {Evented} from '../core/Events';\r\nimport * as Browser from '../core/Browser';\r\nimport * as DomEvent from './DomEvent';\r\nimport * as DomUtil from './DomUtil';\r\nimport * as Util from '../core/Util';\r\nimport {Point} from '../geometry/Point';\r\n\r\n/*\r\n * @class Draggable\r\n * @aka L.Draggable\r\n * @inherits Evented\r\n *\r\n * A class for making DOM elements draggable (including touch support).\r\n * Used internally for map and marker dragging. Only works for elements\r\n * that were positioned with [`L.DomUtil.setPosition`](#domutil-setposition).\r\n *\r\n * @example\r\n * ```js\r\n * var draggable = new L.Draggable(elementToDrag);\r\n * draggable.enable();\r\n * ```\r\n */\r\n\r\nvar START = Browser.touch ? 'touchstart mousedown' : 'mousedown';\r\nvar END = {\r\n\tmousedown: 'mouseup',\r\n\ttouchstart: 'touchend',\r\n\tpointerdown: 'touchend',\r\n\tMSPointerDown: 'touchend'\r\n};\r\nvar MOVE = {\r\n\tmousedown: 'mousemove',\r\n\ttouchstart: 'touchmove',\r\n\tpointerdown: 'touchmove',\r\n\tMSPointerDown: 'touchmove'\r\n};\r\n\r\n\r\nexport var Draggable = Evented.extend({\r\n\r\n\toptions: {\r\n\t\t// @section\r\n\t\t// @aka Draggable options\r\n\t\t// @option clickTolerance: Number = 3\r\n\t\t// The max number of pixels a user can shift the mouse pointer during a click\r\n\t\t// for it to be considered a valid click (as opposed to a mouse drag).\r\n\t\tclickTolerance: 3\r\n\t},\r\n\r\n\t// @constructor L.Draggable(el: HTMLElement, dragHandle?: HTMLElement, preventOutline?: Boolean, options?: Draggable options)\r\n\t// Creates a `Draggable` object for moving `el` when you start dragging the `dragHandle` element (equals `el` itself by default).\r\n\tinitialize: function (element, dragStartTarget, preventOutline, options) {\r\n\t\tUtil.setOptions(this, options);\r\n\r\n\t\tthis._element = element;\r\n\t\tthis._dragStartTarget = dragStartTarget || element;\r\n\t\tthis._preventOutline = preventOutline;\r\n\t},\r\n\r\n\t// @method enable()\r\n\t// Enables the dragging ability\r\n\tenable: function () {\r\n\t\tif (this._enabled) { return; }\r\n\r\n\t\tDomEvent.on(this._dragStartTarget, START, this._onDown, this);\r\n\r\n\t\tthis._enabled = true;\r\n\t},\r\n\r\n\t// @method disable()\r\n\t// Disables the dragging ability\r\n\tdisable: function () {\r\n\t\tif (!this._enabled) { return; }\r\n\r\n\t\t// If we're currently dragging this draggable,\r\n\t\t// disabling it counts as first ending the drag.\r\n\t\tif (Draggable._dragging === this) {\r\n\t\t\tthis.finishDrag();\r\n\t\t}\r\n\r\n\t\tDomEvent.off(this._dragStartTarget, START, this._onDown, this);\r\n\r\n\t\tthis._enabled = false;\r\n\t\tthis._moved = false;\r\n\t},\r\n\r\n\t_onDown: function (e) {\r\n\t\t// Ignore simulated events, since we handle both touch and\r\n\t\t// mouse explicitly; otherwise we risk getting duplicates of\r\n\t\t// touch events, see #4315.\r\n\t\t// Also ignore the event if disabled; this happens in IE11\r\n\t\t// under some circumstances, see #3666.\r\n\t\tif (e._simulated || !this._enabled) { return; }\r\n\r\n\t\tthis._moved = false;\r\n\r\n\t\tif (DomUtil.hasClass(this._element, 'leaflet-zoom-anim')) { return; }\r\n\r\n\t\tif (Draggable._dragging || e.shiftKey || ((e.which !== 1) && (e.button !== 1) && !e.touches)) { return; }\r\n\t\tDraggable._dragging = this; // Prevent dragging multiple objects at once.\r\n\r\n\t\tif (this._preventOutline) {\r\n\t\t\tDomUtil.preventOutline(this._element);\r\n\t\t}\r\n\r\n\t\tDomUtil.disableImageDrag();\r\n\t\tDomUtil.disableTextSelection();\r\n\r\n\t\tif (this._moving) { return; }\r\n\r\n\t\t// @event down: Event\r\n\t\t// Fired when a drag is about to start.\r\n\t\tthis.fire('down');\r\n\r\n\t\tvar first = e.touches ? e.touches[0] : e,\r\n\t\t sizedParent = DomUtil.getSizedParentNode(this._element);\r\n\r\n\t\tthis._startPoint = new Point(first.clientX, first.clientY);\r\n\r\n\t\t// Cache the scale, so that we can continuously compensate for it during drag (_onMove).\r\n\t\tthis._parentScale = DomUtil.getScale(sizedParent);\r\n\r\n\t\tDomEvent.on(document, MOVE[e.type], this._onMove, this);\r\n\t\tDomEvent.on(document, END[e.type], this._onUp, this);\r\n\t},\r\n\r\n\t_onMove: function (e) {\r\n\t\t// Ignore simulated events, since we handle both touch and\r\n\t\t// mouse explicitly; otherwise we risk getting duplicates of\r\n\t\t// touch events, see #4315.\r\n\t\t// Also ignore the event if disabled; this happens in IE11\r\n\t\t// under some circumstances, see #3666.\r\n\t\tif (e._simulated || !this._enabled) { return; }\r\n\r\n\t\tif (e.touches && e.touches.length > 1) {\r\n\t\t\tthis._moved = true;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tvar first = (e.touches && e.touches.length === 1 ? e.touches[0] : e),\r\n\t\t offset = new Point(first.clientX, first.clientY)._subtract(this._startPoint);\r\n\r\n\t\tif (!offset.x && !offset.y) { return; }\r\n\t\tif (Math.abs(offset.x) + Math.abs(offset.y) < this.options.clickTolerance) { return; }\r\n\r\n\t\t// We assume that the parent container's position, border and scale do not change for the duration of the drag.\r\n\t\t// Therefore there is no need to account for the position and border (they are eliminated by the subtraction)\r\n\t\t// and we can use the cached value for the scale.\r\n\t\toffset.x /= this._parentScale.x;\r\n\t\toffset.y /= this._parentScale.y;\r\n\r\n\t\tDomEvent.preventDefault(e);\r\n\r\n\t\tif (!this._moved) {\r\n\t\t\t// @event dragstart: Event\r\n\t\t\t// Fired when a drag starts\r\n\t\t\tthis.fire('dragstart');\r\n\r\n\t\t\tthis._moved = true;\r\n\t\t\tthis._startPos = DomUtil.getPosition(this._element).subtract(offset);\r\n\r\n\t\t\tDomUtil.addClass(document.body, 'leaflet-dragging');\r\n\r\n\t\t\tthis._lastTarget = e.target || e.srcElement;\r\n\t\t\t// IE and Edge do not give the element, so fetch it\r\n\t\t\t// if necessary\r\n\t\t\tif ((window.SVGElementInstance) && (this._lastTarget instanceof SVGElementInstance)) {\r\n\t\t\t\tthis._lastTarget = this._lastTarget.correspondingUseElement;\r\n\t\t\t}\r\n\t\t\tDomUtil.addClass(this._lastTarget, 'leaflet-drag-target');\r\n\t\t}\r\n\r\n\t\tthis._newPos = this._startPos.add(offset);\r\n\t\tthis._moving = true;\r\n\r\n\t\tUtil.cancelAnimFrame(this._animRequest);\r\n\t\tthis._lastEvent = e;\r\n\t\tthis._animRequest = Util.requestAnimFrame(this._updatePosition, this, true);\r\n\t},\r\n\r\n\t_updatePosition: function () {\r\n\t\tvar e = {originalEvent: this._lastEvent};\r\n\r\n\t\t// @event predrag: Event\r\n\t\t// Fired continuously during dragging *before* each corresponding\r\n\t\t// update of the element's position.\r\n\t\tthis.fire('predrag', e);\r\n\t\tDomUtil.setPosition(this._element, this._newPos);\r\n\r\n\t\t// @event drag: Event\r\n\t\t// Fired continuously during dragging.\r\n\t\tthis.fire('drag', e);\r\n\t},\r\n\r\n\t_onUp: function (e) {\r\n\t\t// Ignore simulated events, since we handle both touch and\r\n\t\t// mouse explicitly; otherwise we risk getting duplicates of\r\n\t\t// touch events, see #4315.\r\n\t\t// Also ignore the event if disabled; this happens in IE11\r\n\t\t// under some circumstances, see #3666.\r\n\t\tif (e._simulated || !this._enabled) { return; }\r\n\t\tthis.finishDrag();\r\n\t},\r\n\r\n\tfinishDrag: function () {\r\n\t\tDomUtil.removeClass(document.body, 'leaflet-dragging');\r\n\r\n\t\tif (this._lastTarget) {\r\n\t\t\tDomUtil.removeClass(this._lastTarget, 'leaflet-drag-target');\r\n\t\t\tthis._lastTarget = null;\r\n\t\t}\r\n\r\n\t\tfor (var i in MOVE) {\r\n\t\t\tDomEvent.off(document, MOVE[i], this._onMove, this);\r\n\t\t\tDomEvent.off(document, END[i], this._onUp, this);\r\n\t\t}\r\n\r\n\t\tDomUtil.enableImageDrag();\r\n\t\tDomUtil.enableTextSelection();\r\n\r\n\t\tif (this._moved && this._moving) {\r\n\t\t\t// ensure drag is not fired after dragend\r\n\t\t\tUtil.cancelAnimFrame(this._animRequest);\r\n\r\n\t\t\t// @event dragend: DragEndEvent\r\n\t\t\t// Fired when the drag ends.\r\n\t\t\tthis.fire('dragend', {\r\n\t\t\t\tdistance: this._newPos.distanceTo(this._startPos)\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tthis._moving = false;\r\n\t\tDraggable._dragging = false;\r\n\t}\r\n\r\n});\r\n","import {Point} from './Point';\r\nimport * as Util from '../core/Util';\r\n\r\n\r\n/*\r\n * @namespace LineUtil\r\n *\r\n * Various utility functions for polyline points processing, used by Leaflet internally to make polylines lightning-fast.\r\n */\r\n\r\n// Simplify polyline with vertex reduction and Douglas-Peucker simplification.\r\n// Improves rendering performance dramatically by lessening the number of points to draw.\r\n\r\n// @function simplify(points: Point[], tolerance: Number): Point[]\r\n// Dramatically reduces the number of points in a polyline while retaining\r\n// its shape and returns a new array of simplified points, using the\r\n// [Douglas-Peucker algorithm](http://en.wikipedia.org/wiki/Douglas-Peucker_algorithm).\r\n// Used for a huge performance boost when processing/displaying Leaflet polylines for\r\n// each zoom level and also reducing visual noise. tolerance affects the amount of\r\n// simplification (lesser value means higher quality but slower and with more points).\r\n// Also released as a separated micro-library [Simplify.js](http://mourner.github.com/simplify-js/).\r\nexport function simplify(points, tolerance) {\r\n\tif (!tolerance || !points.length) {\r\n\t\treturn points.slice();\r\n\t}\r\n\r\n\tvar sqTolerance = tolerance * tolerance;\r\n\r\n\t // stage 1: vertex reduction\r\n\t points = _reducePoints(points, sqTolerance);\r\n\r\n\t // stage 2: Douglas-Peucker simplification\r\n\t points = _simplifyDP(points, sqTolerance);\r\n\r\n\treturn points;\r\n}\r\n\r\n// @function pointToSegmentDistance(p: Point, p1: Point, p2: Point): Number\r\n// Returns the distance between point `p` and segment `p1` to `p2`.\r\nexport function pointToSegmentDistance(p, p1, p2) {\r\n\treturn Math.sqrt(_sqClosestPointOnSegment(p, p1, p2, true));\r\n}\r\n\r\n// @function closestPointOnSegment(p: Point, p1: Point, p2: Point): Number\r\n// Returns the closest point from a point `p` on a segment `p1` to `p2`.\r\nexport function closestPointOnSegment(p, p1, p2) {\r\n\treturn _sqClosestPointOnSegment(p, p1, p2);\r\n}\r\n\r\n// Douglas-Peucker simplification, see http://en.wikipedia.org/wiki/Douglas-Peucker_algorithm\r\nfunction _simplifyDP(points, sqTolerance) {\r\n\r\n\tvar len = points.length,\r\n\t ArrayConstructor = typeof Uint8Array !== undefined + '' ? Uint8Array : Array,\r\n\t markers = new ArrayConstructor(len);\r\n\r\n\t markers[0] = markers[len - 1] = 1;\r\n\r\n\t_simplifyDPStep(points, markers, sqTolerance, 0, len - 1);\r\n\r\n\tvar i,\r\n\t newPoints = [];\r\n\r\n\tfor (i = 0; i < len; i++) {\r\n\t\tif (markers[i]) {\r\n\t\t\tnewPoints.push(points[i]);\r\n\t\t}\r\n\t}\r\n\r\n\treturn newPoints;\r\n}\r\n\r\nfunction _simplifyDPStep(points, markers, sqTolerance, first, last) {\r\n\r\n\tvar maxSqDist = 0,\r\n\tindex, i, sqDist;\r\n\r\n\tfor (i = first + 1; i <= last - 1; i++) {\r\n\t\tsqDist = _sqClosestPointOnSegment(points[i], points[first], points[last], true);\r\n\r\n\t\tif (sqDist > maxSqDist) {\r\n\t\t\tindex = i;\r\n\t\t\tmaxSqDist = sqDist;\r\n\t\t}\r\n\t}\r\n\r\n\tif (maxSqDist > sqTolerance) {\r\n\t\tmarkers[index] = 1;\r\n\r\n\t\t_simplifyDPStep(points, markers, sqTolerance, first, index);\r\n\t\t_simplifyDPStep(points, markers, sqTolerance, index, last);\r\n\t}\r\n}\r\n\r\n// reduce points that are too close to each other to a single point\r\nfunction _reducePoints(points, sqTolerance) {\r\n\tvar reducedPoints = [points[0]];\r\n\r\n\tfor (var i = 1, prev = 0, len = points.length; i < len; i++) {\r\n\t\tif (_sqDist(points[i], points[prev]) > sqTolerance) {\r\n\t\t\treducedPoints.push(points[i]);\r\n\t\t\tprev = i;\r\n\t\t}\r\n\t}\r\n\tif (prev < len - 1) {\r\n\t\treducedPoints.push(points[len - 1]);\r\n\t}\r\n\treturn reducedPoints;\r\n}\r\n\r\nvar _lastCode;\r\n\r\n// @function clipSegment(a: Point, b: Point, bounds: Bounds, useLastCode?: Boolean, round?: Boolean): Point[]|Boolean\r\n// Clips the segment a to b by rectangular bounds with the\r\n// [Cohen-Sutherland algorithm](https://en.wikipedia.org/wiki/Cohen%E2%80%93Sutherland_algorithm)\r\n// (modifying the segment points directly!). Used by Leaflet to only show polyline\r\n// points that are on the screen or near, increasing performance.\r\nexport function clipSegment(a, b, bounds, useLastCode, round) {\r\n\tvar codeA = useLastCode ? _lastCode : _getBitCode(a, bounds),\r\n\t codeB = _getBitCode(b, bounds),\r\n\r\n\t codeOut, p, newCode;\r\n\r\n\t // save 2nd code to avoid calculating it on the next segment\r\n\t _lastCode = codeB;\r\n\r\n\twhile (true) {\r\n\t\t// if a,b is inside the clip window (trivial accept)\r\n\t\tif (!(codeA | codeB)) {\r\n\t\t\treturn [a, b];\r\n\t\t}\r\n\r\n\t\t// if a,b is outside the clip window (trivial reject)\r\n\t\tif (codeA & codeB) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\t// other cases\r\n\t\tcodeOut = codeA || codeB;\r\n\t\tp = _getEdgeIntersection(a, b, codeOut, bounds, round);\r\n\t\tnewCode = _getBitCode(p, bounds);\r\n\r\n\t\tif (codeOut === codeA) {\r\n\t\t\ta = p;\r\n\t\t\tcodeA = newCode;\r\n\t\t} else {\r\n\t\t\tb = p;\r\n\t\t\tcodeB = newCode;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nexport function _getEdgeIntersection(a, b, code, bounds, round) {\r\n\tvar dx = b.x - a.x,\r\n\t dy = b.y - a.y,\r\n\t min = bounds.min,\r\n\t max = bounds.max,\r\n\t x, y;\r\n\r\n\tif (code & 8) { // top\r\n\t\tx = a.x + dx * (max.y - a.y) / dy;\r\n\t\ty = max.y;\r\n\r\n\t} else if (code & 4) { // bottom\r\n\t\tx = a.x + dx * (min.y - a.y) / dy;\r\n\t\ty = min.y;\r\n\r\n\t} else if (code & 2) { // right\r\n\t\tx = max.x;\r\n\t\ty = a.y + dy * (max.x - a.x) / dx;\r\n\r\n\t} else if (code & 1) { // left\r\n\t\tx = min.x;\r\n\t\ty = a.y + dy * (min.x - a.x) / dx;\r\n\t}\r\n\r\n\treturn new Point(x, y, round);\r\n}\r\n\r\nexport function _getBitCode(p, bounds) {\r\n\tvar code = 0;\r\n\r\n\tif (p.x < bounds.min.x) { // left\r\n\t\tcode |= 1;\r\n\t} else if (p.x > bounds.max.x) { // right\r\n\t\tcode |= 2;\r\n\t}\r\n\r\n\tif (p.y < bounds.min.y) { // bottom\r\n\t\tcode |= 4;\r\n\t} else if (p.y > bounds.max.y) { // top\r\n\t\tcode |= 8;\r\n\t}\r\n\r\n\treturn code;\r\n}\r\n\r\n// square distance (to avoid unnecessary Math.sqrt calls)\r\nfunction _sqDist(p1, p2) {\r\n\tvar dx = p2.x - p1.x,\r\n\t dy = p2.y - p1.y;\r\n\treturn dx * dx + dy * dy;\r\n}\r\n\r\n// return closest point on segment or distance to that point\r\nexport function _sqClosestPointOnSegment(p, p1, p2, sqDist) {\r\n\tvar x = p1.x,\r\n\t y = p1.y,\r\n\t dx = p2.x - x,\r\n\t dy = p2.y - y,\r\n\t dot = dx * dx + dy * dy,\r\n\t t;\r\n\r\n\tif (dot > 0) {\r\n\t\tt = ((p.x - x) * dx + (p.y - y) * dy) / dot;\r\n\r\n\t\tif (t > 1) {\r\n\t\t\tx = p2.x;\r\n\t\t\ty = p2.y;\r\n\t\t} else if (t > 0) {\r\n\t\t\tx += dx * t;\r\n\t\t\ty += dy * t;\r\n\t\t}\r\n\t}\r\n\r\n\tdx = p.x - x;\r\n\tdy = p.y - y;\r\n\r\n\treturn sqDist ? dx * dx + dy * dy : new Point(x, y);\r\n}\r\n\r\n\r\n// @function isFlat(latlngs: LatLng[]): Boolean\r\n// Returns true if `latlngs` is a flat array, false is nested.\r\nexport function isFlat(latlngs) {\r\n\treturn !Util.isArray(latlngs[0]) || (typeof latlngs[0][0] !== 'object' && typeof latlngs[0][0] !== 'undefined');\r\n}\r\n\r\nexport function _flat(latlngs) {\r\n\tconsole.warn('Deprecated use of _flat, please use L.LineUtil.isFlat instead.');\r\n\treturn isFlat(latlngs);\r\n}\r\n","import * as LineUtil from './LineUtil';\r\n\r\n/*\r\n * @namespace PolyUtil\r\n * Various utility functions for polygon geometries.\r\n */\r\n\r\n/* @function clipPolygon(points: Point[], bounds: Bounds, round?: Boolean): Point[]\r\n * Clips the polygon geometry defined by the given `points` by the given bounds (using the [Sutherland-Hodgman algorithm](https://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman_algorithm)).\r\n * Used by Leaflet to only show polygon points that are on the screen or near, increasing\r\n * performance. Note that polygon points needs different algorithm for clipping\r\n * than polyline, so there's a separate method for it.\r\n */\r\nexport function clipPolygon(points, bounds, round) {\r\n\tvar clippedPoints,\r\n\t edges = [1, 4, 2, 8],\r\n\t i, j, k,\r\n\t a, b,\r\n\t len, edge, p;\r\n\r\n\tfor (i = 0, len = points.length; i < len; i++) {\r\n\t\tpoints[i]._code = LineUtil._getBitCode(points[i], bounds);\r\n\t}\r\n\r\n\t// for each edge (left, bottom, right, top)\r\n\tfor (k = 0; k < 4; k++) {\r\n\t\tedge = edges[k];\r\n\t\tclippedPoints = [];\r\n\r\n\t\tfor (i = 0, len = points.length, j = len - 1; i < len; j = i++) {\r\n\t\t\ta = points[i];\r\n\t\t\tb = points[j];\r\n\r\n\t\t\t// if a is inside the clip window\r\n\t\t\tif (!(a._code & edge)) {\r\n\t\t\t\t// if b is outside the clip window (a->b goes out of screen)\r\n\t\t\t\tif (b._code & edge) {\r\n\t\t\t\t\tp = LineUtil._getEdgeIntersection(b, a, edge, bounds, round);\r\n\t\t\t\t\tp._code = LineUtil._getBitCode(p, bounds);\r\n\t\t\t\t\tclippedPoints.push(p);\r\n\t\t\t\t}\r\n\t\t\t\tclippedPoints.push(a);\r\n\r\n\t\t\t// else if b is inside the clip window (a->b enters the screen)\r\n\t\t\t} else if (!(b._code & edge)) {\r\n\t\t\t\tp = LineUtil._getEdgeIntersection(b, a, edge, bounds, round);\r\n\t\t\t\tp._code = LineUtil._getBitCode(p, bounds);\r\n\t\t\t\tclippedPoints.push(p);\r\n\t\t\t}\r\n\t\t}\r\n\t\tpoints = clippedPoints;\r\n\t}\r\n\r\n\treturn points;\r\n}\r\n","import {LatLng} from '../LatLng';\r\nimport {Bounds} from '../../geometry/Bounds';\r\nimport {Point} from '../../geometry/Point';\r\n\r\n/*\r\n * @namespace Projection\r\n * @section\r\n * Leaflet comes with a set of already defined Projections out of the box:\r\n *\r\n * @projection L.Projection.LonLat\r\n *\r\n * Equirectangular, or Plate Carree projection — the most simple projection,\r\n * mostly used by GIS enthusiasts. Directly maps `x` as longitude, and `y` as\r\n * latitude. Also suitable for flat worlds, e.g. game maps. Used by the\r\n * `EPSG:4326` and `Simple` CRS.\r\n */\r\n\r\nexport var LonLat = {\r\n\tproject: function (latlng) {\r\n\t\treturn new Point(latlng.lng, latlng.lat);\r\n\t},\r\n\r\n\tunproject: function (point) {\r\n\t\treturn new LatLng(point.y, point.x);\r\n\t},\r\n\r\n\tbounds: new Bounds([-180, -90], [180, 90])\r\n};\r\n","import {LatLng} from '../LatLng';\r\nimport {Bounds} from '../../geometry/Bounds';\r\nimport {Point} from '../../geometry/Point';\r\n\r\n/*\r\n * @namespace Projection\r\n * @projection L.Projection.Mercator\r\n *\r\n * Elliptical Mercator projection — more complex than Spherical Mercator. Assumes that Earth is an ellipsoid. Used by the EPSG:3395 CRS.\r\n */\r\n\r\nexport var Mercator = {\r\n\tR: 6378137,\r\n\tR_MINOR: 6356752.314245179,\r\n\r\n\tbounds: new Bounds([-20037508.34279, -15496570.73972], [20037508.34279, 18764656.23138]),\r\n\r\n\tproject: function (latlng) {\r\n\t\tvar d = Math.PI / 180,\r\n\t\t r = this.R,\r\n\t\t y = latlng.lat * d,\r\n\t\t tmp = this.R_MINOR / r,\r\n\t\t e = Math.sqrt(1 - tmp * tmp),\r\n\t\t con = e * Math.sin(y);\r\n\r\n\t\tvar ts = Math.tan(Math.PI / 4 - y / 2) / Math.pow((1 - con) / (1 + con), e / 2);\r\n\t\ty = -r * Math.log(Math.max(ts, 1E-10));\r\n\r\n\t\treturn new Point(latlng.lng * d * r, y);\r\n\t},\r\n\r\n\tunproject: function (point) {\r\n\t\tvar d = 180 / Math.PI,\r\n\t\t r = this.R,\r\n\t\t tmp = this.R_MINOR / r,\r\n\t\t e = Math.sqrt(1 - tmp * tmp),\r\n\t\t ts = Math.exp(-point.y / r),\r\n\t\t phi = Math.PI / 2 - 2 * Math.atan(ts);\r\n\r\n\t\tfor (var i = 0, dphi = 0.1, con; i < 15 && Math.abs(dphi) > 1e-7; i++) {\r\n\t\t\tcon = e * Math.sin(phi);\r\n\t\t\tcon = Math.pow((1 - con) / (1 + con), e / 2);\r\n\t\t\tdphi = Math.PI / 2 - 2 * Math.atan(ts * con) - phi;\r\n\t\t\tphi += dphi;\r\n\t\t}\r\n\r\n\t\treturn new LatLng(phi * d, point.x * d / r);\r\n\t}\r\n};\r\n","/*\n * @class Projection\n\n * An object with methods for projecting geographical coordinates of the world onto\n * a flat surface (and back). See [Map projection](http://en.wikipedia.org/wiki/Map_projection).\n\n * @property bounds: Bounds\n * The bounds (specified in CRS units) where the projection is valid\n\n * @method project(latlng: LatLng): Point\n * Projects geographical coordinates into a 2D point.\n * Only accepts actual `L.LatLng` instances, not arrays.\n\n * @method unproject(point: Point): LatLng\n * The inverse of `project`. Projects a 2D point into a geographical location.\n * Only accepts actual `L.Point` instances, not arrays.\n\n * Note that the projection instances do not inherit from Leafet's `Class` object,\n * and can't be instantiated. Also, new classes can't inherit from them,\n * and methods can't be added to them with the `include` function.\n\n */\n\nexport {LonLat} from './Projection.LonLat';\nexport {Mercator} from './Projection.Mercator';\nexport {SphericalMercator} from './Projection.SphericalMercator';\n","import {Earth} from './CRS.Earth';\r\nimport {Mercator} from '../projection/Projection.Mercator';\r\nimport {toTransformation} from '../../geometry/Transformation';\r\nimport * as Util from '../../core/Util';\r\n\r\n/*\r\n * @namespace CRS\r\n * @crs L.CRS.EPSG3395\r\n *\r\n * Rarely used by some commercial tile providers. Uses Elliptical Mercator projection.\r\n */\r\nexport var EPSG3395 = Util.extend({}, Earth, {\r\n\tcode: 'EPSG:3395',\r\n\tprojection: Mercator,\r\n\r\n\ttransformation: (function () {\r\n\t\tvar scale = 0.5 / (Math.PI * Mercator.R);\r\n\t\treturn toTransformation(scale, 0.5, -scale, 0.5);\r\n\t}())\r\n});\r\n","import {Earth} from './CRS.Earth';\r\nimport {LonLat} from '../projection/Projection.LonLat';\r\nimport {toTransformation} from '../../geometry/Transformation';\r\nimport * as Util from '../../core/Util';\r\n\r\n/*\r\n * @namespace CRS\r\n * @crs L.CRS.EPSG4326\r\n *\r\n * A common CRS among GIS enthusiasts. Uses simple Equirectangular projection.\r\n *\r\n * Leaflet 1.0.x complies with the [TMS coordinate scheme for EPSG:4326](https://wiki.osgeo.org/wiki/Tile_Map_Service_Specification#global-geodetic),\r\n * which is a breaking change from 0.7.x behaviour. If you are using a `TileLayer`\r\n * with this CRS, ensure that there are two 256x256 pixel tiles covering the\r\n * whole earth at zoom level zero, and that the tile coordinate origin is (-180,+90),\r\n * or (-180,-90) for `TileLayer`s with [the `tms` option](#tilelayer-tms) set.\r\n */\r\n\r\nexport var EPSG4326 = Util.extend({}, Earth, {\r\n\tcode: 'EPSG:4326',\r\n\tprojection: LonLat,\r\n\ttransformation: toTransformation(1 / 180, 1, -1 / 180, 0.5)\r\n});\r\n","import {CRS} from './CRS';\nimport {LonLat} from '../projection/Projection.LonLat';\nimport {toTransformation} from '../../geometry/Transformation';\nimport * as Util from '../../core/Util';\n\n/*\n * @namespace CRS\n * @crs L.CRS.Simple\n *\n * A simple CRS that maps longitude and latitude into `x` and `y` directly.\n * May be used for maps of flat surfaces (e.g. game maps). Note that the `y`\n * axis should still be inverted (going from bottom to top). `distance()` returns\n * simple euclidean distance.\n */\n\nexport var Simple = Util.extend({}, CRS, {\n\tprojection: LonLat,\n\ttransformation: toTransformation(1, 0, -1, 0),\n\n\tscale: function (zoom) {\n\t\treturn Math.pow(2, zoom);\n\t},\n\n\tzoom: function (scale) {\n\t\treturn Math.log(scale) / Math.LN2;\n\t},\n\n\tdistance: function (latlng1, latlng2) {\n\t\tvar dx = latlng2.lng - latlng1.lng,\n\t\t dy = latlng2.lat - latlng1.lat;\n\n\t\treturn Math.sqrt(dx * dx + dy * dy);\n\t},\n\n\tinfinite: true\n});\n","import {CRS} from './CRS';\nimport {Earth} from './CRS.Earth';\nimport {EPSG3395} from './CRS.EPSG3395';\nimport {EPSG3857, EPSG900913} from './CRS.EPSG3857';\nimport {EPSG4326} from './CRS.EPSG4326';\nimport {Simple} from './CRS.Simple';\n\nCRS.Earth = Earth;\nCRS.EPSG3395 = EPSG3395;\nCRS.EPSG3857 = EPSG3857;\nCRS.EPSG900913 = EPSG900913;\nCRS.EPSG4326 = EPSG4326;\nCRS.Simple = Simple;\n\nexport {CRS};\n","import {Evented} from '../core/Events';\nimport {Map} from '../map/Map';\nimport * as Util from '../core/Util';\n\n/*\n * @class Layer\n * @inherits Evented\n * @aka L.Layer\n * @aka ILayer\n *\n * A set of methods from the Layer base class that all Leaflet layers use.\n * Inherits all methods, options and events from `L.Evented`.\n *\n * @example\n *\n * ```js\n * var layer = L.marker(latlng).addTo(map);\n * layer.addTo(map);\n * layer.remove();\n * ```\n *\n * @event add: Event\n * Fired after the layer is added to a map\n *\n * @event remove: Event\n * Fired after the layer is removed from a map\n */\n\n\nexport var Layer = Evented.extend({\n\n\t// Classes extending `L.Layer` will inherit the following options:\n\toptions: {\n\t\t// @option pane: String = 'overlayPane'\n\t\t// By default the layer will be added to the map's [overlay pane](#map-overlaypane). Overriding this option will cause the layer to be placed on another pane by default.\n\t\tpane: 'overlayPane',\n\n\t\t// @option attribution: String = null\n\t\t// String to be shown in the attribution control, e.g. \"© OpenStreetMap contributors\". It describes the layer data and is often a legal obligation towards copyright holders and tile providers.\n\t\tattribution: null,\n\n\t\tbubblingMouseEvents: true\n\t},\n\n\t/* @section\n\t * Classes extending `L.Layer` will inherit the following methods:\n\t *\n\t * @method addTo(map: Map|LayerGroup): this\n\t * Adds the layer to the given map or layer group.\n\t */\n\taddTo: function (map) {\n\t\tmap.addLayer(this);\n\t\treturn this;\n\t},\n\n\t// @method remove: this\n\t// Removes the layer from the map it is currently active on.\n\tremove: function () {\n\t\treturn this.removeFrom(this._map || this._mapToAdd);\n\t},\n\n\t// @method removeFrom(map: Map): this\n\t// Removes the layer from the given map\n\tremoveFrom: function (obj) {\n\t\tif (obj) {\n\t\t\tobj.removeLayer(this);\n\t\t}\n\t\treturn this;\n\t},\n\n\t// @method getPane(name? : String): HTMLElement\n\t// Returns the `HTMLElement` representing the named pane on the map. If `name` is omitted, returns the pane for this layer.\n\tgetPane: function (name) {\n\t\treturn this._map.getPane(name ? (this.options[name] || name) : this.options.pane);\n\t},\n\n\taddInteractiveTarget: function (targetEl) {\n\t\tthis._map._targets[Util.stamp(targetEl)] = this;\n\t\treturn this;\n\t},\n\n\tremoveInteractiveTarget: function (targetEl) {\n\t\tdelete this._map._targets[Util.stamp(targetEl)];\n\t\treturn this;\n\t},\n\n\t// @method getAttribution: String\n\t// Used by the `attribution control`, returns the [attribution option](#gridlayer-attribution).\n\tgetAttribution: function () {\n\t\treturn this.options.attribution;\n\t},\n\n\t_layerAdd: function (e) {\n\t\tvar map = e.target;\n\n\t\t// check in case layer gets added and then removed before the map is ready\n\t\tif (!map.hasLayer(this)) { return; }\n\n\t\tthis._map = map;\n\t\tthis._zoomAnimated = map._zoomAnimated;\n\n\t\tif (this.getEvents) {\n\t\t\tvar events = this.getEvents();\n\t\t\tmap.on(events, this);\n\t\t\tthis.once('remove', function () {\n\t\t\t\tmap.off(events, this);\n\t\t\t}, this);\n\t\t}\n\n\t\tthis.onAdd(map);\n\n\t\tif (this.getAttribution && map.attributionControl) {\n\t\t\tmap.attributionControl.addAttribution(this.getAttribution());\n\t\t}\n\n\t\tthis.fire('add');\n\t\tmap.fire('layeradd', {layer: this});\n\t}\n});\n\n/* @section Extension methods\n * @uninheritable\n *\n * Every layer should extend from `L.Layer` and (re-)implement the following methods.\n *\n * @method onAdd(map: Map): this\n * Should contain code that creates DOM elements for the layer, adds them to `map panes` where they should belong and puts listeners on relevant map events. Called on [`map.addLayer(layer)`](#map-addlayer).\n *\n * @method onRemove(map: Map): this\n * Should contain all clean up code that removes the layer's elements from the DOM and removes listeners previously added in [`onAdd`](#layer-onadd). Called on [`map.removeLayer(layer)`](#map-removelayer).\n *\n * @method getEvents(): Object\n * This optional method should return an object like `{ viewreset: this._reset }` for [`addEventListener`](#evented-addeventlistener). The event handlers in this object will be automatically added and removed from the map with your layer.\n *\n * @method getAttribution(): String\n * This optional method should return a string containing HTML to be shown on the `Attribution control` whenever the layer is visible.\n *\n * @method beforeAdd(map: Map): this\n * Optional method. Called on [`map.addLayer(layer)`](#map-addlayer), before the layer is added to the map, before events are initialized, without waiting until the map is in a usable state. Use for early initialization only.\n */\n\n\n/* @namespace Map\n * @section Layer events\n *\n * @event layeradd: LayerEvent\n * Fired when a new layer is added to the map.\n *\n * @event layerremove: LayerEvent\n * Fired when some layer is removed from the map\n *\n * @section Methods for Layers and Controls\n */\nMap.include({\n\t// @method addLayer(layer: Layer): this\n\t// Adds the given layer to the map\n\taddLayer: function (layer) {\n\t\tif (!layer._layerAdd) {\n\t\t\tthrow new Error('The provided object is not a Layer.');\n\t\t}\n\n\t\tvar id = Util.stamp(layer);\n\t\tif (this._layers[id]) { return this; }\n\t\tthis._layers[id] = layer;\n\n\t\tlayer._mapToAdd = this;\n\n\t\tif (layer.beforeAdd) {\n\t\t\tlayer.beforeAdd(this);\n\t\t}\n\n\t\tthis.whenReady(layer._layerAdd, layer);\n\n\t\treturn this;\n\t},\n\n\t// @method removeLayer(layer: Layer): this\n\t// Removes the given layer from the map.\n\tremoveLayer: function (layer) {\n\t\tvar id = Util.stamp(layer);\n\n\t\tif (!this._layers[id]) { return this; }\n\n\t\tif (this._loaded) {\n\t\t\tlayer.onRemove(this);\n\t\t}\n\n\t\tif (layer.getAttribution && this.attributionControl) {\n\t\t\tthis.attributionControl.removeAttribution(layer.getAttribution());\n\t\t}\n\n\t\tdelete this._layers[id];\n\n\t\tif (this._loaded) {\n\t\t\tthis.fire('layerremove', {layer: layer});\n\t\t\tlayer.fire('remove');\n\t\t}\n\n\t\tlayer._map = layer._mapToAdd = null;\n\n\t\treturn this;\n\t},\n\n\t// @method hasLayer(layer: Layer): Boolean\n\t// Returns `true` if the given layer is currently added to the map\n\thasLayer: function (layer) {\n\t\treturn !!layer && (Util.stamp(layer) in this._layers);\n\t},\n\n\t/* @method eachLayer(fn: Function, context?: Object): this\n\t * Iterates over the layers of the map, optionally specifying context of the iterator function.\n\t * ```\n\t * map.eachLayer(function(layer){\n\t * layer.bindPopup('Hello');\n\t * });\n\t * ```\n\t */\n\teachLayer: function (method, context) {\n\t\tfor (var i in this._layers) {\n\t\t\tmethod.call(context, this._layers[i]);\n\t\t}\n\t\treturn this;\n\t},\n\n\t_addLayers: function (layers) {\n\t\tlayers = layers ? (Util.isArray(layers) ? layers : [layers]) : [];\n\n\t\tfor (var i = 0, len = layers.length; i < len; i++) {\n\t\t\tthis.addLayer(layers[i]);\n\t\t}\n\t},\n\n\t_addZoomLimit: function (layer) {\n\t\tif (isNaN(layer.options.maxZoom) || !isNaN(layer.options.minZoom)) {\n\t\t\tthis._zoomBoundLayers[Util.stamp(layer)] = layer;\n\t\t\tthis._updateZoomLevels();\n\t\t}\n\t},\n\n\t_removeZoomLimit: function (layer) {\n\t\tvar id = Util.stamp(layer);\n\n\t\tif (this._zoomBoundLayers[id]) {\n\t\t\tdelete this._zoomBoundLayers[id];\n\t\t\tthis._updateZoomLevels();\n\t\t}\n\t},\n\n\t_updateZoomLevels: function () {\n\t\tvar minZoom = Infinity,\n\t\t maxZoom = -Infinity,\n\t\t oldZoomSpan = this._getZoomSpan();\n\n\t\tfor (var i in this._zoomBoundLayers) {\n\t\t\tvar options = this._zoomBoundLayers[i].options;\n\n\t\t\tminZoom = options.minZoom === undefined ? minZoom : Math.min(minZoom, options.minZoom);\n\t\t\tmaxZoom = options.maxZoom === undefined ? maxZoom : Math.max(maxZoom, options.maxZoom);\n\t\t}\n\n\t\tthis._layersMaxZoom = maxZoom === -Infinity ? undefined : maxZoom;\n\t\tthis._layersMinZoom = minZoom === Infinity ? undefined : minZoom;\n\n\t\t// @section Map state change events\n\t\t// @event zoomlevelschange: Event\n\t\t// Fired when the number of zoomlevels on the map is changed due\n\t\t// to adding or removing a layer.\n\t\tif (oldZoomSpan !== this._getZoomSpan()) {\n\t\t\tthis.fire('zoomlevelschange');\n\t\t}\n\n\t\tif (this.options.maxZoom === undefined && this._layersMaxZoom && this.getZoom() > this._layersMaxZoom) {\n\t\t\tthis.setZoom(this._layersMaxZoom);\n\t\t}\n\t\tif (this.options.minZoom === undefined && this._layersMinZoom && this.getZoom() < this._layersMinZoom) {\n\t\t\tthis.setZoom(this._layersMinZoom);\n\t\t}\n\t}\n});\n","\r\nimport {Layer} from './Layer';\r\nimport * as Util from '../core/Util';\r\n\r\n/*\r\n * @class LayerGroup\r\n * @aka L.LayerGroup\r\n * @inherits Layer\r\n *\r\n * Used to group several layers and handle them as one. If you add it to the map,\r\n * any layers added or removed from the group will be added/removed on the map as\r\n * well. Extends `Layer`.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * L.layerGroup([marker1, marker2])\r\n * \t.addLayer(polyline)\r\n * \t.addTo(map);\r\n * ```\r\n */\r\n\r\nexport var LayerGroup = Layer.extend({\r\n\r\n\tinitialize: function (layers, options) {\r\n\t\tUtil.setOptions(this, options);\r\n\r\n\t\tthis._layers = {};\r\n\r\n\t\tvar i, len;\r\n\r\n\t\tif (layers) {\r\n\t\t\tfor (i = 0, len = layers.length; i < len; i++) {\r\n\t\t\t\tthis.addLayer(layers[i]);\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\t// @method addLayer(layer: Layer): this\r\n\t// Adds the given layer to the group.\r\n\taddLayer: function (layer) {\r\n\t\tvar id = this.getLayerId(layer);\r\n\r\n\t\tthis._layers[id] = layer;\r\n\r\n\t\tif (this._map) {\r\n\t\t\tthis._map.addLayer(layer);\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method removeLayer(layer: Layer): this\r\n\t// Removes the given layer from the group.\r\n\t// @alternative\r\n\t// @method removeLayer(id: Number): this\r\n\t// Removes the layer with the given internal ID from the group.\r\n\tremoveLayer: function (layer) {\r\n\t\tvar id = layer in this._layers ? layer : this.getLayerId(layer);\r\n\r\n\t\tif (this._map && this._layers[id]) {\r\n\t\t\tthis._map.removeLayer(this._layers[id]);\r\n\t\t}\r\n\r\n\t\tdelete this._layers[id];\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method hasLayer(layer: Layer): Boolean\r\n\t// Returns `true` if the given layer is currently added to the group.\r\n\t// @alternative\r\n\t// @method hasLayer(id: Number): Boolean\r\n\t// Returns `true` if the given internal ID is currently added to the group.\r\n\thasLayer: function (layer) {\r\n\t\treturn !!layer && (layer in this._layers || this.getLayerId(layer) in this._layers);\r\n\t},\r\n\r\n\t// @method clearLayers(): this\r\n\t// Removes all the layers from the group.\r\n\tclearLayers: function () {\r\n\t\treturn this.eachLayer(this.removeLayer, this);\r\n\t},\r\n\r\n\t// @method invoke(methodName: String, …): this\r\n\t// Calls `methodName` on every layer contained in this group, passing any\r\n\t// additional parameters. Has no effect if the layers contained do not\r\n\t// implement `methodName`.\r\n\tinvoke: function (methodName) {\r\n\t\tvar args = Array.prototype.slice.call(arguments, 1),\r\n\t\t i, layer;\r\n\r\n\t\tfor (i in this._layers) {\r\n\t\t\tlayer = this._layers[i];\r\n\r\n\t\t\tif (layer[methodName]) {\r\n\t\t\t\tlayer[methodName].apply(layer, args);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\tonAdd: function (map) {\r\n\t\tthis.eachLayer(map.addLayer, map);\r\n\t},\r\n\r\n\tonRemove: function (map) {\r\n\t\tthis.eachLayer(map.removeLayer, map);\r\n\t},\r\n\r\n\t// @method eachLayer(fn: Function, context?: Object): this\r\n\t// Iterates over the layers of the group, optionally specifying context of the iterator function.\r\n\t// ```js\r\n\t// group.eachLayer(function (layer) {\r\n\t// \tlayer.bindPopup('Hello');\r\n\t// });\r\n\t// ```\r\n\teachLayer: function (method, context) {\r\n\t\tfor (var i in this._layers) {\r\n\t\t\tmethod.call(context, this._layers[i]);\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method getLayer(id: Number): Layer\r\n\t// Returns the layer with the given internal ID.\r\n\tgetLayer: function (id) {\r\n\t\treturn this._layers[id];\r\n\t},\r\n\r\n\t// @method getLayers(): Layer[]\r\n\t// Returns an array of all the layers added to the group.\r\n\tgetLayers: function () {\r\n\t\tvar layers = [];\r\n\t\tthis.eachLayer(layers.push, layers);\r\n\t\treturn layers;\r\n\t},\r\n\r\n\t// @method setZIndex(zIndex: Number): this\r\n\t// Calls `setZIndex` on every layer contained in this group, passing the z-index.\r\n\tsetZIndex: function (zIndex) {\r\n\t\treturn this.invoke('setZIndex', zIndex);\r\n\t},\r\n\r\n\t// @method getLayerId(layer: Layer): Number\r\n\t// Returns the internal ID for a layer\r\n\tgetLayerId: function (layer) {\r\n\t\treturn Util.stamp(layer);\r\n\t}\r\n});\r\n\r\n\r\n// @factory L.layerGroup(layers?: Layer[], options?: Object)\r\n// Create a layer group, optionally given an initial set of layers and an `options` object.\r\nexport var layerGroup = function (layers, options) {\r\n\treturn new LayerGroup(layers, options);\r\n};\r\n","import {LayerGroup} from './LayerGroup';\r\nimport {LatLngBounds} from '../geo/LatLngBounds';\r\n\r\n/*\r\n * @class FeatureGroup\r\n * @aka L.FeatureGroup\r\n * @inherits LayerGroup\r\n *\r\n * Extended `LayerGroup` that makes it easier to do the same thing to all its member layers:\r\n * * [`bindPopup`](#layer-bindpopup) binds a popup to all of the layers at once (likewise with [`bindTooltip`](#layer-bindtooltip))\r\n * * Events are propagated to the `FeatureGroup`, so if the group has an event\r\n * handler, it will handle events from any of the layers. This includes mouse events\r\n * and custom events.\r\n * * Has `layeradd` and `layerremove` events\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * L.featureGroup([marker1, marker2, polyline])\r\n * \t.bindPopup('Hello world!')\r\n * \t.on('click', function() { alert('Clicked on a member of the group!'); })\r\n * \t.addTo(map);\r\n * ```\r\n */\r\n\r\nexport var FeatureGroup = LayerGroup.extend({\r\n\r\n\taddLayer: function (layer) {\r\n\t\tif (this.hasLayer(layer)) {\r\n\t\t\treturn this;\r\n\t\t}\r\n\r\n\t\tlayer.addEventParent(this);\r\n\r\n\t\tLayerGroup.prototype.addLayer.call(this, layer);\r\n\r\n\t\t// @event layeradd: LayerEvent\r\n\t\t// Fired when a layer is added to this `FeatureGroup`\r\n\t\treturn this.fire('layeradd', {layer: layer});\r\n\t},\r\n\r\n\tremoveLayer: function (layer) {\r\n\t\tif (!this.hasLayer(layer)) {\r\n\t\t\treturn this;\r\n\t\t}\r\n\t\tif (layer in this._layers) {\r\n\t\t\tlayer = this._layers[layer];\r\n\t\t}\r\n\r\n\t\tlayer.removeEventParent(this);\r\n\r\n\t\tLayerGroup.prototype.removeLayer.call(this, layer);\r\n\r\n\t\t// @event layerremove: LayerEvent\r\n\t\t// Fired when a layer is removed from this `FeatureGroup`\r\n\t\treturn this.fire('layerremove', {layer: layer});\r\n\t},\r\n\r\n\t// @method setStyle(style: Path options): this\r\n\t// Sets the given path options to each layer of the group that has a `setStyle` method.\r\n\tsetStyle: function (style) {\r\n\t\treturn this.invoke('setStyle', style);\r\n\t},\r\n\r\n\t// @method bringToFront(): this\r\n\t// Brings the layer group to the top of all other layers\r\n\tbringToFront: function () {\r\n\t\treturn this.invoke('bringToFront');\r\n\t},\r\n\r\n\t// @method bringToBack(): this\r\n\t// Brings the layer group to the back of all other layers\r\n\tbringToBack: function () {\r\n\t\treturn this.invoke('bringToBack');\r\n\t},\r\n\r\n\t// @method getBounds(): LatLngBounds\r\n\t// Returns the LatLngBounds of the Feature Group (created from bounds and coordinates of its children).\r\n\tgetBounds: function () {\r\n\t\tvar bounds = new LatLngBounds();\r\n\r\n\t\tfor (var id in this._layers) {\r\n\t\t\tvar layer = this._layers[id];\r\n\t\t\tbounds.extend(layer.getBounds ? layer.getBounds() : layer.getLatLng());\r\n\t\t}\r\n\t\treturn bounds;\r\n\t}\r\n});\r\n\r\n// @factory L.featureGroup(layers: Layer[])\r\n// Create a feature group, optionally given an initial set of layers.\r\nexport var featureGroup = function (layers) {\r\n\treturn new FeatureGroup(layers);\r\n};\r\n","import {Class} from '../../core/Class';\r\nimport {setOptions} from '../../core/Util';\r\nimport {toPoint as point} from '../../geometry/Point';\r\nimport {retina} from '../../core/Browser';\r\n\r\n/*\r\n * @class Icon\r\n * @aka L.Icon\r\n *\r\n * Represents an icon to provide when creating a marker.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * var myIcon = L.icon({\r\n * iconUrl: 'my-icon.png',\r\n * iconRetinaUrl: 'my-icon@2x.png',\r\n * iconSize: [38, 95],\r\n * iconAnchor: [22, 94],\r\n * popupAnchor: [-3, -76],\r\n * shadowUrl: 'my-icon-shadow.png',\r\n * shadowRetinaUrl: 'my-icon-shadow@2x.png',\r\n * shadowSize: [68, 95],\r\n * shadowAnchor: [22, 94]\r\n * });\r\n *\r\n * L.marker([50.505, 30.57], {icon: myIcon}).addTo(map);\r\n * ```\r\n *\r\n * `L.Icon.Default` extends `L.Icon` and is the blue icon Leaflet uses for markers by default.\r\n *\r\n */\r\n\r\nexport var Icon = Class.extend({\r\n\r\n\t/* @section\r\n\t * @aka Icon options\r\n\t *\r\n\t * @option iconUrl: String = null\r\n\t * **(required)** The URL to the icon image (absolute or relative to your script path).\r\n\t *\r\n\t * @option iconRetinaUrl: String = null\r\n\t * The URL to a retina sized version of the icon image (absolute or relative to your\r\n\t * script path). Used for Retina screen devices.\r\n\t *\r\n\t * @option iconSize: Point = null\r\n\t * Size of the icon image in pixels.\r\n\t *\r\n\t * @option iconAnchor: Point = null\r\n\t * The coordinates of the \"tip\" of the icon (relative to its top left corner). The icon\r\n\t * will be aligned so that this point is at the marker's geographical location. Centered\r\n\t * by default if size is specified, also can be set in CSS with negative margins.\r\n\t *\r\n\t * @option popupAnchor: Point = [0, 0]\r\n\t * The coordinates of the point from which popups will \"open\", relative to the icon anchor.\r\n\t *\r\n\t * @option tooltipAnchor: Point = [0, 0]\r\n\t * The coordinates of the point from which tooltips will \"open\", relative to the icon anchor.\r\n\t *\r\n\t * @option shadowUrl: String = null\r\n\t * The URL to the icon shadow image. If not specified, no shadow image will be created.\r\n\t *\r\n\t * @option shadowRetinaUrl: String = null\r\n\t *\r\n\t * @option shadowSize: Point = null\r\n\t * Size of the shadow image in pixels.\r\n\t *\r\n\t * @option shadowAnchor: Point = null\r\n\t * The coordinates of the \"tip\" of the shadow (relative to its top left corner) (the same\r\n\t * as iconAnchor if not specified).\r\n\t *\r\n\t * @option className: String = ''\r\n\t * A custom class name to assign to both icon and shadow images. Empty by default.\r\n\t */\r\n\r\n\toptions: {\r\n\t\tpopupAnchor: [0, 0],\r\n\t\ttooltipAnchor: [0, 0]\r\n\t},\r\n\r\n\tinitialize: function (options) {\r\n\t\tsetOptions(this, options);\r\n\t},\r\n\r\n\t// @method createIcon(oldIcon?: HTMLElement): HTMLElement\r\n\t// Called internally when the icon has to be shown, returns a `` HTML element\r\n\t// styled according to the options.\r\n\tcreateIcon: function (oldIcon) {\r\n\t\treturn this._createIcon('icon', oldIcon);\r\n\t},\r\n\r\n\t// @method createShadow(oldIcon?: HTMLElement): HTMLElement\r\n\t// As `createIcon`, but for the shadow beneath it.\r\n\tcreateShadow: function (oldIcon) {\r\n\t\treturn this._createIcon('shadow', oldIcon);\r\n\t},\r\n\r\n\t_createIcon: function (name, oldIcon) {\r\n\t\tvar src = this._getIconUrl(name);\r\n\r\n\t\tif (!src) {\r\n\t\t\tif (name === 'icon') {\r\n\t\t\t\tthrow new Error('iconUrl not set in Icon options (see the docs).');\r\n\t\t\t}\r\n\t\t\treturn null;\r\n\t\t}\r\n\r\n\t\tvar img = this._createImg(src, oldIcon && oldIcon.tagName === 'IMG' ? oldIcon : null);\r\n\t\tthis._setIconStyles(img, name);\r\n\r\n\t\treturn img;\r\n\t},\r\n\r\n\t_setIconStyles: function (img, name) {\r\n\t\tvar options = this.options;\r\n\t\tvar sizeOption = options[name + 'Size'];\r\n\r\n\t\tif (typeof sizeOption === 'number') {\r\n\t\t\tsizeOption = [sizeOption, sizeOption];\r\n\t\t}\r\n\r\n\t\tvar size = point(sizeOption),\r\n\t\t anchor = point(name === 'shadow' && options.shadowAnchor || options.iconAnchor ||\r\n\t\t size && size.divideBy(2, true));\r\n\r\n\t\timg.className = 'leaflet-marker-' + name + ' ' + (options.className || '');\r\n\r\n\t\tif (anchor) {\r\n\t\t\timg.style.marginLeft = (-anchor.x) + 'px';\r\n\t\t\timg.style.marginTop = (-anchor.y) + 'px';\r\n\t\t}\r\n\r\n\t\tif (size) {\r\n\t\t\timg.style.width = size.x + 'px';\r\n\t\t\timg.style.height = size.y + 'px';\r\n\t\t}\r\n\t},\r\n\r\n\t_createImg: function (src, el) {\r\n\t\tel = el || document.createElement('img');\r\n\t\tel.src = src;\r\n\t\treturn el;\r\n\t},\r\n\r\n\t_getIconUrl: function (name) {\r\n\t\treturn retina && this.options[name + 'RetinaUrl'] || this.options[name + 'Url'];\r\n\t}\r\n});\r\n\r\n\r\n// @factory L.icon(options: Icon options)\r\n// Creates an icon instance with the given options.\r\nexport function icon(options) {\r\n\treturn new Icon(options);\r\n}\r\n","import {Icon} from './Icon';\nimport * as DomUtil from '../../dom/DomUtil';\n\n/*\n * @miniclass Icon.Default (Icon)\n * @aka L.Icon.Default\n * @section\n *\n * A trivial subclass of `Icon`, represents the icon to use in `Marker`s when\n * no icon is specified. Points to the blue marker image distributed with Leaflet\n * releases.\n *\n * In order to customize the default icon, just change the properties of `L.Icon.Default.prototype.options`\n * (which is a set of `Icon options`).\n *\n * If you want to _completely_ replace the default icon, override the\n * `L.Marker.prototype.options.icon` with your own icon instead.\n */\n\nexport var IconDefault = Icon.extend({\n\n\toptions: {\n\t\ticonUrl: 'marker-icon.png',\n\t\ticonRetinaUrl: 'marker-icon-2x.png',\n\t\tshadowUrl: 'marker-shadow.png',\n\t\ticonSize: [25, 41],\n\t\ticonAnchor: [12, 41],\n\t\tpopupAnchor: [1, -34],\n\t\ttooltipAnchor: [16, -28],\n\t\tshadowSize: [41, 41]\n\t},\n\n\t_getIconUrl: function (name) {\n\t\tif (!IconDefault.imagePath) {\t// Deprecated, backwards-compatibility only\n\t\t\tIconDefault.imagePath = this._detectIconPath();\n\t\t}\n\n\t\t// @option imagePath: String\n\t\t// `Icon.Default` will try to auto-detect the location of the\n\t\t// blue icon images. If you are placing these images in a non-standard\n\t\t// way, set this option to point to the right path.\n\t\treturn (this.options.imagePath || IconDefault.imagePath) + Icon.prototype._getIconUrl.call(this, name);\n\t},\n\n\t_detectIconPath: function () {\n\t\tvar el = DomUtil.create('div', 'leaflet-default-icon-path', document.body);\n\t\tvar path = DomUtil.getStyle(el, 'background-image') ||\n\t\t DomUtil.getStyle(el, 'backgroundImage');\t// IE8\n\n\t\tdocument.body.removeChild(el);\n\n\t\tif (path === null || path.indexOf('url') !== 0) {\n\t\t\tpath = '';\n\t\t} else {\n\t\t\tpath = path.replace(/^url\\([\"']?/, '').replace(/marker-icon\\.png[\"']?\\)$/, '');\n\t\t}\n\n\t\treturn path;\n\t}\n});\n","import {Handler} from '../../core/Handler';\nimport * as DomUtil from '../../dom/DomUtil';\nimport {Draggable} from '../../dom/Draggable';\nimport {toBounds} from '../../geometry/Bounds';\nimport {toPoint} from '../../geometry/Point';\nimport {requestAnimFrame, cancelAnimFrame} from '../../core/Util';\n\n/*\n * L.Handler.MarkerDrag is used internally by L.Marker to make the markers draggable.\n */\n\n\n/* @namespace Marker\n * @section Interaction handlers\n *\n * Interaction handlers are properties of a marker instance that allow you to control interaction behavior in runtime, enabling or disabling certain features such as dragging (see `Handler` methods). Example:\n *\n * ```js\n * marker.dragging.disable();\n * ```\n *\n * @property dragging: Handler\n * Marker dragging handler (by both mouse and touch). Only valid when the marker is on the map (Otherwise set [`marker.options.draggable`](#marker-draggable)).\n */\n\nexport var MarkerDrag = Handler.extend({\n\tinitialize: function (marker) {\n\t\tthis._marker = marker;\n\t},\n\n\taddHooks: function () {\n\t\tvar icon = this._marker._icon;\n\n\t\tif (!this._draggable) {\n\t\t\tthis._draggable = new Draggable(icon, icon, true);\n\t\t}\n\n\t\tthis._draggable.on({\n\t\t\tdragstart: this._onDragStart,\n\t\t\tpredrag: this._onPreDrag,\n\t\t\tdrag: this._onDrag,\n\t\t\tdragend: this._onDragEnd\n\t\t}, this).enable();\n\n\t\tDomUtil.addClass(icon, 'leaflet-marker-draggable');\n\t},\n\n\tremoveHooks: function () {\n\t\tthis._draggable.off({\n\t\t\tdragstart: this._onDragStart,\n\t\t\tpredrag: this._onPreDrag,\n\t\t\tdrag: this._onDrag,\n\t\t\tdragend: this._onDragEnd\n\t\t}, this).disable();\n\n\t\tif (this._marker._icon) {\n\t\t\tDomUtil.removeClass(this._marker._icon, 'leaflet-marker-draggable');\n\t\t}\n\t},\n\n\tmoved: function () {\n\t\treturn this._draggable && this._draggable._moved;\n\t},\n\n\t_adjustPan: function (e) {\n\t\tvar marker = this._marker,\n\t\t map = marker._map,\n\t\t speed = this._marker.options.autoPanSpeed,\n\t\t padding = this._marker.options.autoPanPadding,\n\t\t iconPos = DomUtil.getPosition(marker._icon),\n\t\t bounds = map.getPixelBounds(),\n\t\t origin = map.getPixelOrigin();\n\n\t\tvar panBounds = toBounds(\n\t\t\tbounds.min._subtract(origin).add(padding),\n\t\t\tbounds.max._subtract(origin).subtract(padding)\n\t\t);\n\n\t\tif (!panBounds.contains(iconPos)) {\n\t\t\t// Compute incremental movement\n\t\t\tvar movement = toPoint(\n\t\t\t\t(Math.max(panBounds.max.x, iconPos.x) - panBounds.max.x) / (bounds.max.x - panBounds.max.x) -\n\t\t\t\t(Math.min(panBounds.min.x, iconPos.x) - panBounds.min.x) / (bounds.min.x - panBounds.min.x),\n\n\t\t\t\t(Math.max(panBounds.max.y, iconPos.y) - panBounds.max.y) / (bounds.max.y - panBounds.max.y) -\n\t\t\t\t(Math.min(panBounds.min.y, iconPos.y) - panBounds.min.y) / (bounds.min.y - panBounds.min.y)\n\t\t\t).multiplyBy(speed);\n\n\t\t\tmap.panBy(movement, {animate: false});\n\n\t\t\tthis._draggable._newPos._add(movement);\n\t\t\tthis._draggable._startPos._add(movement);\n\n\t\t\tDomUtil.setPosition(marker._icon, this._draggable._newPos);\n\t\t\tthis._onDrag(e);\n\n\t\t\tthis._panRequest = requestAnimFrame(this._adjustPan.bind(this, e));\n\t\t}\n\t},\n\n\t_onDragStart: function () {\n\t\t// @section Dragging events\n\t\t// @event dragstart: Event\n\t\t// Fired when the user starts dragging the marker.\n\n\t\t// @event movestart: Event\n\t\t// Fired when the marker starts moving (because of dragging).\n\n\t\tthis._oldLatLng = this._marker.getLatLng();\n\t\tthis._marker\n\t\t .closePopup()\n\t\t .fire('movestart')\n\t\t .fire('dragstart');\n\t},\n\n\t_onPreDrag: function (e) {\n\t\tif (this._marker.options.autoPan) {\n\t\t\tcancelAnimFrame(this._panRequest);\n\t\t\tthis._panRequest = requestAnimFrame(this._adjustPan.bind(this, e));\n\t\t}\n\t},\n\n\t_onDrag: function (e) {\n\t\tvar marker = this._marker,\n\t\t shadow = marker._shadow,\n\t\t iconPos = DomUtil.getPosition(marker._icon),\n\t\t latlng = marker._map.layerPointToLatLng(iconPos);\n\n\t\t// update shadow position\n\t\tif (shadow) {\n\t\t\tDomUtil.setPosition(shadow, iconPos);\n\t\t}\n\n\t\tmarker._latlng = latlng;\n\t\te.latlng = latlng;\n\t\te.oldLatLng = this._oldLatLng;\n\n\t\t// @event drag: Event\n\t\t// Fired repeatedly while the user drags the marker.\n\t\tmarker\n\t\t .fire('move', e)\n\t\t .fire('drag', e);\n\t},\n\n\t_onDragEnd: function (e) {\n\t\t// @event dragend: DragEndEvent\n\t\t// Fired when the user stops dragging the marker.\n\n\t\t cancelAnimFrame(this._panRequest);\n\n\t\t// @event moveend: Event\n\t\t// Fired when the marker stops moving (because of dragging).\n\t\tdelete this._oldLatLng;\n\t\tthis._marker\n\t\t .fire('moveend')\n\t\t .fire('dragend', e);\n\t}\n});\n","import {Layer} from '../Layer';\r\nimport {IconDefault} from './Icon.Default';\r\nimport * as Util from '../../core/Util';\r\nimport {toLatLng as latLng} from '../../geo/LatLng';\r\nimport * as DomUtil from '../../dom/DomUtil';\r\nimport {MarkerDrag} from './Marker.Drag';\r\n\r\n/*\r\n * @class Marker\r\n * @inherits Interactive layer\r\n * @aka L.Marker\r\n * L.Marker is used to display clickable/draggable icons on the map. Extends `Layer`.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * L.marker([50.5, 30.5]).addTo(map);\r\n * ```\r\n */\r\n\r\nexport var Marker = Layer.extend({\r\n\r\n\t// @section\r\n\t// @aka Marker options\r\n\toptions: {\r\n\t\t// @option icon: Icon = *\r\n\t\t// Icon instance to use for rendering the marker.\r\n\t\t// See [Icon documentation](#L.Icon) for details on how to customize the marker icon.\r\n\t\t// If not specified, a common instance of `L.Icon.Default` is used.\r\n\t\ticon: new IconDefault(),\r\n\r\n\t\t// Option inherited from \"Interactive layer\" abstract class\r\n\t\tinteractive: true,\r\n\r\n\t\t// @option keyboard: Boolean = true\r\n\t\t// Whether the marker can be tabbed to with a keyboard and clicked by pressing enter.\r\n\t\tkeyboard: true,\r\n\r\n\t\t// @option title: String = ''\r\n\t\t// Text for the browser tooltip that appear on marker hover (no tooltip by default).\r\n\t\ttitle: '',\r\n\r\n\t\t// @option alt: String = ''\r\n\t\t// Text for the `alt` attribute of the icon image (useful for accessibility).\r\n\t\talt: '',\r\n\r\n\t\t// @option zIndexOffset: Number = 0\r\n\t\t// By default, marker images zIndex is set automatically based on its latitude. Use this option if you want to put the marker on top of all others (or below), specifying a high value like `1000` (or high negative value, respectively).\r\n\t\tzIndexOffset: 0,\r\n\r\n\t\t// @option opacity: Number = 1.0\r\n\t\t// The opacity of the marker.\r\n\t\topacity: 1,\r\n\r\n\t\t// @option riseOnHover: Boolean = false\r\n\t\t// If `true`, the marker will get on top of others when you hover the mouse over it.\r\n\t\triseOnHover: false,\r\n\r\n\t\t// @option riseOffset: Number = 250\r\n\t\t// The z-index offset used for the `riseOnHover` feature.\r\n\t\triseOffset: 250,\r\n\r\n\t\t// @option pane: String = 'markerPane'\r\n\t\t// `Map pane` where the markers icon will be added.\r\n\t\tpane: 'markerPane',\r\n\r\n\t\t// @option pane: String = 'shadowPane'\r\n\t\t// `Map pane` where the markers shadow will be added.\r\n\t\tshadowPane: 'shadowPane',\r\n\r\n\t\t// @option bubblingMouseEvents: Boolean = false\r\n\t\t// When `true`, a mouse event on this marker will trigger the same event on the map\r\n\t\t// (unless [`L.DomEvent.stopPropagation`](#domevent-stoppropagation) is used).\r\n\t\tbubblingMouseEvents: false,\r\n\r\n\t\t// @section Draggable marker options\r\n\t\t// @option draggable: Boolean = false\r\n\t\t// Whether the marker is draggable with mouse/touch or not.\r\n\t\tdraggable: false,\r\n\r\n\t\t// @option autoPan: Boolean = false\r\n\t\t// Whether to pan the map when dragging this marker near its edge or not.\r\n\t\tautoPan: false,\r\n\r\n\t\t// @option autoPanPadding: Point = Point(50, 50)\r\n\t\t// Distance (in pixels to the left/right and to the top/bottom) of the\r\n\t\t// map edge to start panning the map.\r\n\t\tautoPanPadding: [50, 50],\r\n\r\n\t\t// @option autoPanSpeed: Number = 10\r\n\t\t// Number of pixels the map should pan by.\r\n\t\tautoPanSpeed: 10\r\n\t},\r\n\r\n\t/* @section\r\n\t *\r\n\t * In addition to [shared layer methods](#Layer) like `addTo()` and `remove()` and [popup methods](#Popup) like bindPopup() you can also use the following methods:\r\n\t */\r\n\r\n\tinitialize: function (latlng, options) {\r\n\t\tUtil.setOptions(this, options);\r\n\t\tthis._latlng = latLng(latlng);\r\n\t},\r\n\r\n\tonAdd: function (map) {\r\n\t\tthis._zoomAnimated = this._zoomAnimated && map.options.markerZoomAnimation;\r\n\r\n\t\tif (this._zoomAnimated) {\r\n\t\t\tmap.on('zoomanim', this._animateZoom, this);\r\n\t\t}\r\n\r\n\t\tthis._initIcon();\r\n\t\tthis.update();\r\n\t},\r\n\r\n\tonRemove: function (map) {\r\n\t\tif (this.dragging && this.dragging.enabled()) {\r\n\t\t\tthis.options.draggable = true;\r\n\t\t\tthis.dragging.removeHooks();\r\n\t\t}\r\n\t\tdelete this.dragging;\r\n\r\n\t\tif (this._zoomAnimated) {\r\n\t\t\tmap.off('zoomanim', this._animateZoom, this);\r\n\t\t}\r\n\r\n\t\tthis._removeIcon();\r\n\t\tthis._removeShadow();\r\n\t},\r\n\r\n\tgetEvents: function () {\r\n\t\treturn {\r\n\t\t\tzoom: this.update,\r\n\t\t\tviewreset: this.update\r\n\t\t};\r\n\t},\r\n\r\n\t// @method getLatLng: LatLng\r\n\t// Returns the current geographical position of the marker.\r\n\tgetLatLng: function () {\r\n\t\treturn this._latlng;\r\n\t},\r\n\r\n\t// @method setLatLng(latlng: LatLng): this\r\n\t// Changes the marker position to the given point.\r\n\tsetLatLng: function (latlng) {\r\n\t\tvar oldLatLng = this._latlng;\r\n\t\tthis._latlng = latLng(latlng);\r\n\t\tthis.update();\r\n\r\n\t\t// @event move: Event\r\n\t\t// Fired when the marker is moved via [`setLatLng`](#marker-setlatlng) or by [dragging](#marker-dragging). Old and new coordinates are included in event arguments as `oldLatLng`, `latlng`.\r\n\t\treturn this.fire('move', {oldLatLng: oldLatLng, latlng: this._latlng});\r\n\t},\r\n\r\n\t// @method setZIndexOffset(offset: Number): this\r\n\t// Changes the [zIndex offset](#marker-zindexoffset) of the marker.\r\n\tsetZIndexOffset: function (offset) {\r\n\t\tthis.options.zIndexOffset = offset;\r\n\t\treturn this.update();\r\n\t},\r\n\r\n\t// @method getIcon: Icon\r\n\t// Returns the current icon used by the marker\r\n\tgetIcon: function () {\r\n\t\treturn this.options.icon;\r\n\t},\r\n\r\n\t// @method setIcon(icon: Icon): this\r\n\t// Changes the marker icon.\r\n\tsetIcon: function (icon) {\r\n\r\n\t\tthis.options.icon = icon;\r\n\r\n\t\tif (this._map) {\r\n\t\t\tthis._initIcon();\r\n\t\t\tthis.update();\r\n\t\t}\r\n\r\n\t\tif (this._popup) {\r\n\t\t\tthis.bindPopup(this._popup, this._popup.options);\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\tgetElement: function () {\r\n\t\treturn this._icon;\r\n\t},\r\n\r\n\tupdate: function () {\r\n\r\n\t\tif (this._icon && this._map) {\r\n\t\t\tvar pos = this._map.latLngToLayerPoint(this._latlng).round();\r\n\t\t\tthis._setPos(pos);\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t_initIcon: function () {\r\n\t\tvar options = this.options,\r\n\t\t classToAdd = 'leaflet-zoom-' + (this._zoomAnimated ? 'animated' : 'hide');\r\n\r\n\t\tvar icon = options.icon.createIcon(this._icon),\r\n\t\t addIcon = false;\r\n\r\n\t\t// if we're not reusing the icon, remove the old one and init new one\r\n\t\tif (icon !== this._icon) {\r\n\t\t\tif (this._icon) {\r\n\t\t\t\tthis._removeIcon();\r\n\t\t\t}\r\n\t\t\taddIcon = true;\r\n\r\n\t\t\tif (options.title) {\r\n\t\t\t\ticon.title = options.title;\r\n\t\t\t}\r\n\r\n\t\t\tif (icon.tagName === 'IMG') {\r\n\t\t\t\ticon.alt = options.alt || '';\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tDomUtil.addClass(icon, classToAdd);\r\n\r\n\t\tif (options.keyboard) {\r\n\t\t\ticon.tabIndex = '0';\r\n\t\t}\r\n\r\n\t\tthis._icon = icon;\r\n\r\n\t\tif (options.riseOnHover) {\r\n\t\t\tthis.on({\r\n\t\t\t\tmouseover: this._bringToFront,\r\n\t\t\t\tmouseout: this._resetZIndex\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tvar newShadow = options.icon.createShadow(this._shadow),\r\n\t\t addShadow = false;\r\n\r\n\t\tif (newShadow !== this._shadow) {\r\n\t\t\tthis._removeShadow();\r\n\t\t\taddShadow = true;\r\n\t\t}\r\n\r\n\t\tif (newShadow) {\r\n\t\t\tDomUtil.addClass(newShadow, classToAdd);\r\n\t\t\tnewShadow.alt = '';\r\n\t\t}\r\n\t\tthis._shadow = newShadow;\r\n\r\n\r\n\t\tif (options.opacity < 1) {\r\n\t\t\tthis._updateOpacity();\r\n\t\t}\r\n\r\n\r\n\t\tif (addIcon) {\r\n\t\t\tthis.getPane().appendChild(this._icon);\r\n\t\t}\r\n\t\tthis._initInteraction();\r\n\t\tif (newShadow && addShadow) {\r\n\t\t\tthis.getPane(options.shadowPane).appendChild(this._shadow);\r\n\t\t}\r\n\t},\r\n\r\n\t_removeIcon: function () {\r\n\t\tif (this.options.riseOnHover) {\r\n\t\t\tthis.off({\r\n\t\t\t\tmouseover: this._bringToFront,\r\n\t\t\t\tmouseout: this._resetZIndex\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tDomUtil.remove(this._icon);\r\n\t\tthis.removeInteractiveTarget(this._icon);\r\n\r\n\t\tthis._icon = null;\r\n\t},\r\n\r\n\t_removeShadow: function () {\r\n\t\tif (this._shadow) {\r\n\t\t\tDomUtil.remove(this._shadow);\r\n\t\t}\r\n\t\tthis._shadow = null;\r\n\t},\r\n\r\n\t_setPos: function (pos) {\r\n\r\n\t\tif (this._icon) {\r\n\t\t\tDomUtil.setPosition(this._icon, pos);\r\n\t\t}\r\n\r\n\t\tif (this._shadow) {\r\n\t\t\tDomUtil.setPosition(this._shadow, pos);\r\n\t\t}\r\n\r\n\t\tthis._zIndex = pos.y + this.options.zIndexOffset;\r\n\r\n\t\tthis._resetZIndex();\r\n\t},\r\n\r\n\t_updateZIndex: function (offset) {\r\n\t\tif (this._icon) {\r\n\t\t\tthis._icon.style.zIndex = this._zIndex + offset;\r\n\t\t}\r\n\t},\r\n\r\n\t_animateZoom: function (opt) {\r\n\t\tvar pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center).round();\r\n\r\n\t\tthis._setPos(pos);\r\n\t},\r\n\r\n\t_initInteraction: function () {\r\n\r\n\t\tif (!this.options.interactive) { return; }\r\n\r\n\t\tDomUtil.addClass(this._icon, 'leaflet-interactive');\r\n\r\n\t\tthis.addInteractiveTarget(this._icon);\r\n\r\n\t\tif (MarkerDrag) {\r\n\t\t\tvar draggable = this.options.draggable;\r\n\t\t\tif (this.dragging) {\r\n\t\t\t\tdraggable = this.dragging.enabled();\r\n\t\t\t\tthis.dragging.disable();\r\n\t\t\t}\r\n\r\n\t\t\tthis.dragging = new MarkerDrag(this);\r\n\r\n\t\t\tif (draggable) {\r\n\t\t\t\tthis.dragging.enable();\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\t// @method setOpacity(opacity: Number): this\r\n\t// Changes the opacity of the marker.\r\n\tsetOpacity: function (opacity) {\r\n\t\tthis.options.opacity = opacity;\r\n\t\tif (this._map) {\r\n\t\t\tthis._updateOpacity();\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t_updateOpacity: function () {\r\n\t\tvar opacity = this.options.opacity;\r\n\r\n\t\tif (this._icon) {\r\n\t\t\tDomUtil.setOpacity(this._icon, opacity);\r\n\t\t}\r\n\r\n\t\tif (this._shadow) {\r\n\t\t\tDomUtil.setOpacity(this._shadow, opacity);\r\n\t\t}\r\n\t},\r\n\r\n\t_bringToFront: function () {\r\n\t\tthis._updateZIndex(this.options.riseOffset);\r\n\t},\r\n\r\n\t_resetZIndex: function () {\r\n\t\tthis._updateZIndex(0);\r\n\t},\r\n\r\n\t_getPopupAnchor: function () {\r\n\t\treturn this.options.icon.options.popupAnchor;\r\n\t},\r\n\r\n\t_getTooltipAnchor: function () {\r\n\t\treturn this.options.icon.options.tooltipAnchor;\r\n\t}\r\n});\r\n\r\n\r\n// factory L.marker(latlng: LatLng, options? : Marker options)\r\n\r\n// @factory L.marker(latlng: LatLng, options? : Marker options)\r\n// Instantiates a Marker object given a geographical point and optionally an options object.\r\nexport function marker(latlng, options) {\r\n\treturn new Marker(latlng, options);\r\n}\r\n","import {Layer} from '../Layer';\nimport * as Util from '../../core/Util';\n\n/*\n * @class Path\n * @aka L.Path\n * @inherits Interactive layer\n *\n * An abstract class that contains options and constants shared between vector\n * overlays (Polygon, Polyline, Circle). Do not use it directly. Extends `Layer`.\n */\n\nexport var Path = Layer.extend({\n\n\t// @section\n\t// @aka Path options\n\toptions: {\n\t\t// @option stroke: Boolean = true\n\t\t// Whether to draw stroke along the path. Set it to `false` to disable borders on polygons or circles.\n\t\tstroke: true,\n\n\t\t// @option color: String = '#3388ff'\n\t\t// Stroke color\n\t\tcolor: '#3388ff',\n\n\t\t// @option weight: Number = 3\n\t\t// Stroke width in pixels\n\t\tweight: 3,\n\n\t\t// @option opacity: Number = 1.0\n\t\t// Stroke opacity\n\t\topacity: 1,\n\n\t\t// @option lineCap: String= 'round'\n\t\t// A string that defines [shape to be used at the end](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-linecap) of the stroke.\n\t\tlineCap: 'round',\n\n\t\t// @option lineJoin: String = 'round'\n\t\t// A string that defines [shape to be used at the corners](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-linejoin) of the stroke.\n\t\tlineJoin: 'round',\n\n\t\t// @option dashArray: String = null\n\t\t// A string that defines the stroke [dash pattern](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-dasharray). Doesn't work on `Canvas`-powered layers in [some old browsers](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/setLineDash#Browser_compatibility).\n\t\tdashArray: null,\n\n\t\t// @option dashOffset: String = null\n\t\t// A string that defines the [distance into the dash pattern to start the dash](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-dashoffset). Doesn't work on `Canvas`-powered layers in [some old browsers](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/setLineDash#Browser_compatibility).\n\t\tdashOffset: null,\n\n\t\t// @option fill: Boolean = depends\n\t\t// Whether to fill the path with color. Set it to `false` to disable filling on polygons or circles.\n\t\tfill: false,\n\n\t\t// @option fillColor: String = *\n\t\t// Fill color. Defaults to the value of the [`color`](#path-color) option\n\t\tfillColor: null,\n\n\t\t// @option fillOpacity: Number = 0.2\n\t\t// Fill opacity.\n\t\tfillOpacity: 0.2,\n\n\t\t// @option fillRule: String = 'evenodd'\n\t\t// A string that defines [how the inside of a shape](https://developer.mozilla.org/docs/Web/SVG/Attribute/fill-rule) is determined.\n\t\tfillRule: 'evenodd',\n\n\t\t// className: '',\n\n\t\t// Option inherited from \"Interactive layer\" abstract class\n\t\tinteractive: true,\n\n\t\t// @option bubblingMouseEvents: Boolean = true\n\t\t// When `true`, a mouse event on this path will trigger the same event on the map\n\t\t// (unless [`L.DomEvent.stopPropagation`](#domevent-stoppropagation) is used).\n\t\tbubblingMouseEvents: true\n\t},\n\n\tbeforeAdd: function (map) {\n\t\t// Renderer is set here because we need to call renderer.getEvents\n\t\t// before this.getEvents.\n\t\tthis._renderer = map.getRenderer(this);\n\t},\n\n\tonAdd: function () {\n\t\tthis._renderer._initPath(this);\n\t\tthis._reset();\n\t\tthis._renderer._addPath(this);\n\t},\n\n\tonRemove: function () {\n\t\tthis._renderer._removePath(this);\n\t},\n\n\t// @method redraw(): this\n\t// Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.\n\tredraw: function () {\n\t\tif (this._map) {\n\t\t\tthis._renderer._updatePath(this);\n\t\t}\n\t\treturn this;\n\t},\n\n\t// @method setStyle(style: Path options): this\n\t// Changes the appearance of a Path based on the options in the `Path options` object.\n\tsetStyle: function (style) {\n\t\tUtil.setOptions(this, style);\n\t\tif (this._renderer) {\n\t\t\tthis._renderer._updateStyle(this);\n\t\t\tif (this.options.stroke && style && style.hasOwnProperty('weight')) {\n\t\t\t\tthis._updateBounds();\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t},\n\n\t// @method bringToFront(): this\n\t// Brings the layer to the top of all path layers.\n\tbringToFront: function () {\n\t\tif (this._renderer) {\n\t\t\tthis._renderer._bringToFront(this);\n\t\t}\n\t\treturn this;\n\t},\n\n\t// @method bringToBack(): this\n\t// Brings the layer to the bottom of all path layers.\n\tbringToBack: function () {\n\t\tif (this._renderer) {\n\t\t\tthis._renderer._bringToBack(this);\n\t\t}\n\t\treturn this;\n\t},\n\n\tgetElement: function () {\n\t\treturn this._path;\n\t},\n\n\t_reset: function () {\n\t\t// defined in child classes\n\t\tthis._project();\n\t\tthis._update();\n\t},\n\n\t_clickTolerance: function () {\n\t\t// used when doing hit detection for Canvas layers\n\t\treturn (this.options.stroke ? this.options.weight / 2 : 0) + this._renderer.options.tolerance;\n\t}\n});\n","import {Path} from './Path';\nimport * as Util from '../../core/Util';\nimport {toLatLng} from '../../geo/LatLng';\nimport {Bounds} from '../../geometry/Bounds';\n\n\n/*\n * @class CircleMarker\n * @aka L.CircleMarker\n * @inherits Path\n *\n * A circle of a fixed size with radius specified in pixels. Extends `Path`.\n */\n\nexport var CircleMarker = Path.extend({\n\n\t// @section\n\t// @aka CircleMarker options\n\toptions: {\n\t\tfill: true,\n\n\t\t// @option radius: Number = 10\n\t\t// Radius of the circle marker, in pixels\n\t\tradius: 10\n\t},\n\n\tinitialize: function (latlng, options) {\n\t\tUtil.setOptions(this, options);\n\t\tthis._latlng = toLatLng(latlng);\n\t\tthis._radius = this.options.radius;\n\t},\n\n\t// @method setLatLng(latLng: LatLng): this\n\t// Sets the position of a circle marker to a new location.\n\tsetLatLng: function (latlng) {\n\t\tvar oldLatLng = this._latlng;\n\t\tthis._latlng = toLatLng(latlng);\n\t\tthis.redraw();\n\n\t\t// @event move: Event\n\t\t// Fired when the marker is moved via [`setLatLng`](#circlemarker-setlatlng). Old and new coordinates are included in event arguments as `oldLatLng`, `latlng`.\n\t\treturn this.fire('move', {oldLatLng: oldLatLng, latlng: this._latlng});\n\t},\n\n\t// @method getLatLng(): LatLng\n\t// Returns the current geographical position of the circle marker\n\tgetLatLng: function () {\n\t\treturn this._latlng;\n\t},\n\n\t// @method setRadius(radius: Number): this\n\t// Sets the radius of a circle marker. Units are in pixels.\n\tsetRadius: function (radius) {\n\t\tthis.options.radius = this._radius = radius;\n\t\treturn this.redraw();\n\t},\n\n\t// @method getRadius(): Number\n\t// Returns the current radius of the circle\n\tgetRadius: function () {\n\t\treturn this._radius;\n\t},\n\n\tsetStyle : function (options) {\n\t\tvar radius = options && options.radius || this._radius;\n\t\tPath.prototype.setStyle.call(this, options);\n\t\tthis.setRadius(radius);\n\t\treturn this;\n\t},\n\n\t_project: function () {\n\t\tthis._point = this._map.latLngToLayerPoint(this._latlng);\n\t\tthis._updateBounds();\n\t},\n\n\t_updateBounds: function () {\n\t\tvar r = this._radius,\n\t\t r2 = this._radiusY || r,\n\t\t w = this._clickTolerance(),\n\t\t p = [r + w, r2 + w];\n\t\tthis._pxBounds = new Bounds(this._point.subtract(p), this._point.add(p));\n\t},\n\n\t_update: function () {\n\t\tif (this._map) {\n\t\t\tthis._updatePath();\n\t\t}\n\t},\n\n\t_updatePath: function () {\n\t\tthis._renderer._updateCircle(this);\n\t},\n\n\t_empty: function () {\n\t\treturn this._radius && !this._renderer._bounds.intersects(this._pxBounds);\n\t},\n\n\t// Needed by the `Canvas` renderer for interactivity\n\t_containsPoint: function (p) {\n\t\treturn p.distanceTo(this._point) <= this._radius + this._clickTolerance();\n\t}\n});\n\n\n// @factory L.circleMarker(latlng: LatLng, options?: CircleMarker options)\n// Instantiates a circle marker object given a geographical point, and an optional options object.\nexport function circleMarker(latlng, options) {\n\treturn new CircleMarker(latlng, options);\n}\n","import {CircleMarker} from './CircleMarker';\nimport {Path} from './Path';\nimport * as Util from '../../core/Util';\nimport {toLatLng} from '../../geo/LatLng';\nimport {LatLngBounds} from '../../geo/LatLngBounds';\nimport {Earth} from '../../geo/crs/CRS.Earth';\n\n\n/*\n * @class Circle\n * @aka L.Circle\n * @inherits CircleMarker\n *\n * A class for drawing circle overlays on a map. Extends `CircleMarker`.\n *\n * It's an approximation and starts to diverge from a real circle closer to poles (due to projection distortion).\n *\n * @example\n *\n * ```js\n * L.circle([50.5, 30.5], {radius: 200}).addTo(map);\n * ```\n */\n\nexport var Circle = CircleMarker.extend({\n\n\tinitialize: function (latlng, options, legacyOptions) {\n\t\tif (typeof options === 'number') {\n\t\t\t// Backwards compatibility with 0.7.x factory (latlng, radius, options?)\n\t\t\toptions = Util.extend({}, legacyOptions, {radius: options});\n\t\t}\n\t\tUtil.setOptions(this, options);\n\t\tthis._latlng = toLatLng(latlng);\n\n\t\tif (isNaN(this.options.radius)) { throw new Error('Circle radius cannot be NaN'); }\n\n\t\t// @section\n\t\t// @aka Circle options\n\t\t// @option radius: Number; Radius of the circle, in meters.\n\t\tthis._mRadius = this.options.radius;\n\t},\n\n\t// @method setRadius(radius: Number): this\n\t// Sets the radius of a circle. Units are in meters.\n\tsetRadius: function (radius) {\n\t\tthis._mRadius = radius;\n\t\treturn this.redraw();\n\t},\n\n\t// @method getRadius(): Number\n\t// Returns the current radius of a circle. Units are in meters.\n\tgetRadius: function () {\n\t\treturn this._mRadius;\n\t},\n\n\t// @method getBounds(): LatLngBounds\n\t// Returns the `LatLngBounds` of the path.\n\tgetBounds: function () {\n\t\tvar half = [this._radius, this._radiusY || this._radius];\n\n\t\treturn new LatLngBounds(\n\t\t\tthis._map.layerPointToLatLng(this._point.subtract(half)),\n\t\t\tthis._map.layerPointToLatLng(this._point.add(half)));\n\t},\n\n\tsetStyle: Path.prototype.setStyle,\n\n\t_project: function () {\n\n\t\tvar lng = this._latlng.lng,\n\t\t lat = this._latlng.lat,\n\t\t map = this._map,\n\t\t crs = map.options.crs;\n\n\t\tif (crs.distance === Earth.distance) {\n\t\t\tvar d = Math.PI / 180,\n\t\t\t latR = (this._mRadius / Earth.R) / d,\n\t\t\t top = map.project([lat + latR, lng]),\n\t\t\t bottom = map.project([lat - latR, lng]),\n\t\t\t p = top.add(bottom).divideBy(2),\n\t\t\t lat2 = map.unproject(p).lat,\n\t\t\t lngR = Math.acos((Math.cos(latR * d) - Math.sin(lat * d) * Math.sin(lat2 * d)) /\n\t\t\t (Math.cos(lat * d) * Math.cos(lat2 * d))) / d;\n\n\t\t\tif (isNaN(lngR) || lngR === 0) {\n\t\t\t\tlngR = latR / Math.cos(Math.PI / 180 * lat); // Fallback for edge case, #2425\n\t\t\t}\n\n\t\t\tthis._point = p.subtract(map.getPixelOrigin());\n\t\t\tthis._radius = isNaN(lngR) ? 0 : p.x - map.project([lat2, lng - lngR]).x;\n\t\t\tthis._radiusY = p.y - top.y;\n\n\t\t} else {\n\t\t\tvar latlng2 = crs.unproject(crs.project(this._latlng).subtract([this._mRadius, 0]));\n\n\t\t\tthis._point = map.latLngToLayerPoint(this._latlng);\n\t\t\tthis._radius = this._point.x - map.latLngToLayerPoint(latlng2).x;\n\t\t}\n\n\t\tthis._updateBounds();\n\t}\n});\n\n// @factory L.circle(latlng: LatLng, options?: Circle options)\n// Instantiates a circle object given a geographical point, and an options object\n// which contains the circle radius.\n// @alternative\n// @factory L.circle(latlng: LatLng, radius: Number, options?: Circle options)\n// Obsolete way of instantiating a circle, for compatibility with 0.7.x code.\n// Do not use in new applications or plugins.\nexport function circle(latlng, options, legacyOptions) {\n\treturn new Circle(latlng, options, legacyOptions);\n}\n","import {Path} from './Path';\nimport * as Util from '../../core/Util';\nimport * as LineUtil from '../../geometry/LineUtil';\nimport {LatLng, toLatLng} from '../../geo/LatLng';\nimport {LatLngBounds} from '../../geo/LatLngBounds';\nimport {Bounds} from '../../geometry/Bounds';\nimport {Point} from '../../geometry/Point';\n\n/*\n * @class Polyline\n * @aka L.Polyline\n * @inherits Path\n *\n * A class for drawing polyline overlays on a map. Extends `Path`.\n *\n * @example\n *\n * ```js\n * // create a red polyline from an array of LatLng points\n * var latlngs = [\n * \t[45.51, -122.68],\n * \t[37.77, -122.43],\n * \t[34.04, -118.2]\n * ];\n *\n * var polyline = L.polyline(latlngs, {color: 'red'}).addTo(map);\n *\n * // zoom the map to the polyline\n * map.fitBounds(polyline.getBounds());\n * ```\n *\n * You can also pass a multi-dimensional array to represent a `MultiPolyline` shape:\n *\n * ```js\n * // create a red polyline from an array of arrays of LatLng points\n * var latlngs = [\n * \t[[45.51, -122.68],\n * \t [37.77, -122.43],\n * \t [34.04, -118.2]],\n * \t[[40.78, -73.91],\n * \t [41.83, -87.62],\n * \t [32.76, -96.72]]\n * ];\n * ```\n */\n\n\nexport var Polyline = Path.extend({\n\n\t// @section\n\t// @aka Polyline options\n\toptions: {\n\t\t// @option smoothFactor: Number = 1.0\n\t\t// How much to simplify the polyline on each zoom level. More means\n\t\t// better performance and smoother look, and less means more accurate representation.\n\t\tsmoothFactor: 1.0,\n\n\t\t// @option noClip: Boolean = false\n\t\t// Disable polyline clipping.\n\t\tnoClip: false\n\t},\n\n\tinitialize: function (latlngs, options) {\n\t\tUtil.setOptions(this, options);\n\t\tthis._setLatLngs(latlngs);\n\t},\n\n\t// @method getLatLngs(): LatLng[]\n\t// Returns an array of the points in the path, or nested arrays of points in case of multi-polyline.\n\tgetLatLngs: function () {\n\t\treturn this._latlngs;\n\t},\n\n\t// @method setLatLngs(latlngs: LatLng[]): this\n\t// Replaces all the points in the polyline with the given array of geographical points.\n\tsetLatLngs: function (latlngs) {\n\t\tthis._setLatLngs(latlngs);\n\t\treturn this.redraw();\n\t},\n\n\t// @method isEmpty(): Boolean\n\t// Returns `true` if the Polyline has no LatLngs.\n\tisEmpty: function () {\n\t\treturn !this._latlngs.length;\n\t},\n\n\t// @method closestLayerPoint(p: Point): Point\n\t// Returns the point closest to `p` on the Polyline.\n\tclosestLayerPoint: function (p) {\n\t\tvar minDistance = Infinity,\n\t\t minPoint = null,\n\t\t closest = LineUtil._sqClosestPointOnSegment,\n\t\t p1, p2;\n\n\t\tfor (var j = 0, jLen = this._parts.length; j < jLen; j++) {\n\t\t\tvar points = this._parts[j];\n\n\t\t\tfor (var i = 1, len = points.length; i < len; i++) {\n\t\t\t\tp1 = points[i - 1];\n\t\t\t\tp2 = points[i];\n\n\t\t\t\tvar sqDist = closest(p, p1, p2, true);\n\n\t\t\t\tif (sqDist < minDistance) {\n\t\t\t\t\tminDistance = sqDist;\n\t\t\t\t\tminPoint = closest(p, p1, p2);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (minPoint) {\n\t\t\tminPoint.distance = Math.sqrt(minDistance);\n\t\t}\n\t\treturn minPoint;\n\t},\n\n\t// @method getCenter(): LatLng\n\t// Returns the center ([centroid](http://en.wikipedia.org/wiki/Centroid)) of the polyline.\n\tgetCenter: function () {\n\t\t// throws error when not yet added to map as this center calculation requires projected coordinates\n\t\tif (!this._map) {\n\t\t\tthrow new Error('Must add layer to map before using getCenter()');\n\t\t}\n\n\t\tvar i, halfDist, segDist, dist, p1, p2, ratio,\n\t\t points = this._rings[0],\n\t\t len = points.length;\n\n\t\tif (!len) { return null; }\n\n\t\t// polyline centroid algorithm; only uses the first ring if there are multiple\n\n\t\tfor (i = 0, halfDist = 0; i < len - 1; i++) {\n\t\t\thalfDist += points[i].distanceTo(points[i + 1]) / 2;\n\t\t}\n\n\t\t// The line is so small in the current view that all points are on the same pixel.\n\t\tif (halfDist === 0) {\n\t\t\treturn this._map.layerPointToLatLng(points[0]);\n\t\t}\n\n\t\tfor (i = 0, dist = 0; i < len - 1; i++) {\n\t\t\tp1 = points[i];\n\t\t\tp2 = points[i + 1];\n\t\t\tsegDist = p1.distanceTo(p2);\n\t\t\tdist += segDist;\n\n\t\t\tif (dist > halfDist) {\n\t\t\t\tratio = (dist - halfDist) / segDist;\n\t\t\t\treturn this._map.layerPointToLatLng([\n\t\t\t\t\tp2.x - ratio * (p2.x - p1.x),\n\t\t\t\t\tp2.y - ratio * (p2.y - p1.y)\n\t\t\t\t]);\n\t\t\t}\n\t\t}\n\t},\n\n\t// @method getBounds(): LatLngBounds\n\t// Returns the `LatLngBounds` of the path.\n\tgetBounds: function () {\n\t\treturn this._bounds;\n\t},\n\n\t// @method addLatLng(latlng: LatLng, latlngs? LatLng[]): this\n\t// Adds a given point to the polyline. By default, adds to the first ring of\n\t// the polyline in case of a multi-polyline, but can be overridden by passing\n\t// a specific ring as a LatLng array (that you can earlier access with [`getLatLngs`](#polyline-getlatlngs)).\n\taddLatLng: function (latlng, latlngs) {\n\t\tlatlngs = latlngs || this._defaultShape();\n\t\tlatlng = toLatLng(latlng);\n\t\tlatlngs.push(latlng);\n\t\tthis._bounds.extend(latlng);\n\t\treturn this.redraw();\n\t},\n\n\t_setLatLngs: function (latlngs) {\n\t\tthis._bounds = new LatLngBounds();\n\t\tthis._latlngs = this._convertLatLngs(latlngs);\n\t},\n\n\t_defaultShape: function () {\n\t\treturn LineUtil.isFlat(this._latlngs) ? this._latlngs : this._latlngs[0];\n\t},\n\n\t// recursively convert latlngs input into actual LatLng instances; calculate bounds along the way\n\t_convertLatLngs: function (latlngs) {\n\t\tvar result = [],\n\t\t flat = LineUtil.isFlat(latlngs);\n\n\t\tfor (var i = 0, len = latlngs.length; i < len; i++) {\n\t\t\tif (flat) {\n\t\t\t\tresult[i] = toLatLng(latlngs[i]);\n\t\t\t\tthis._bounds.extend(result[i]);\n\t\t\t} else {\n\t\t\t\tresult[i] = this._convertLatLngs(latlngs[i]);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t},\n\n\t_project: function () {\n\t\tvar pxBounds = new Bounds();\n\t\tthis._rings = [];\n\t\tthis._projectLatlngs(this._latlngs, this._rings, pxBounds);\n\n\t\tif (this._bounds.isValid() && pxBounds.isValid()) {\n\t\t\tthis._rawPxBounds = pxBounds;\n\t\t\tthis._updateBounds();\n\t\t}\n\t},\n\n\t_updateBounds: function () {\n\t\tvar w = this._clickTolerance(),\n\t\t p = new Point(w, w);\n\t\tthis._pxBounds = new Bounds([\n\t\t\tthis._rawPxBounds.min.subtract(p),\n\t\t\tthis._rawPxBounds.max.add(p)\n\t\t]);\n\t},\n\n\t// recursively turns latlngs into a set of rings with projected coordinates\n\t_projectLatlngs: function (latlngs, result, projectedBounds) {\n\t\tvar flat = latlngs[0] instanceof LatLng,\n\t\t len = latlngs.length,\n\t\t i, ring;\n\n\t\tif (flat) {\n\t\t\tring = [];\n\t\t\tfor (i = 0; i < len; i++) {\n\t\t\t\tring[i] = this._map.latLngToLayerPoint(latlngs[i]);\n\t\t\t\tprojectedBounds.extend(ring[i]);\n\t\t\t}\n\t\t\tresult.push(ring);\n\t\t} else {\n\t\t\tfor (i = 0; i < len; i++) {\n\t\t\t\tthis._projectLatlngs(latlngs[i], result, projectedBounds);\n\t\t\t}\n\t\t}\n\t},\n\n\t// clip polyline by renderer bounds so that we have less to render for performance\n\t_clipPoints: function () {\n\t\tvar bounds = this._renderer._bounds;\n\n\t\tthis._parts = [];\n\t\tif (!this._pxBounds || !this._pxBounds.intersects(bounds)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.options.noClip) {\n\t\t\tthis._parts = this._rings;\n\t\t\treturn;\n\t\t}\n\n\t\tvar parts = this._parts,\n\t\t i, j, k, len, len2, segment, points;\n\n\t\tfor (i = 0, k = 0, len = this._rings.length; i < len; i++) {\n\t\t\tpoints = this._rings[i];\n\n\t\t\tfor (j = 0, len2 = points.length; j < len2 - 1; j++) {\n\t\t\t\tsegment = LineUtil.clipSegment(points[j], points[j + 1], bounds, j, true);\n\n\t\t\t\tif (!segment) { continue; }\n\n\t\t\t\tparts[k] = parts[k] || [];\n\t\t\t\tparts[k].push(segment[0]);\n\n\t\t\t\t// if segment goes out of screen, or it's the last one, it's the end of the line part\n\t\t\t\tif ((segment[1] !== points[j + 1]) || (j === len2 - 2)) {\n\t\t\t\t\tparts[k].push(segment[1]);\n\t\t\t\t\tk++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// simplify each clipped part of the polyline for performance\n\t_simplifyPoints: function () {\n\t\tvar parts = this._parts,\n\t\t tolerance = this.options.smoothFactor;\n\n\t\tfor (var i = 0, len = parts.length; i < len; i++) {\n\t\t\tparts[i] = LineUtil.simplify(parts[i], tolerance);\n\t\t}\n\t},\n\n\t_update: function () {\n\t\tif (!this._map) { return; }\n\n\t\tthis._clipPoints();\n\t\tthis._simplifyPoints();\n\t\tthis._updatePath();\n\t},\n\n\t_updatePath: function () {\n\t\tthis._renderer._updatePoly(this);\n\t},\n\n\t// Needed by the `Canvas` renderer for interactivity\n\t_containsPoint: function (p, closed) {\n\t\tvar i, j, k, len, len2, part,\n\t\t w = this._clickTolerance();\n\n\t\tif (!this._pxBounds || !this._pxBounds.contains(p)) { return false; }\n\n\t\t// hit detection for polylines\n\t\tfor (i = 0, len = this._parts.length; i < len; i++) {\n\t\t\tpart = this._parts[i];\n\n\t\t\tfor (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) {\n\t\t\t\tif (!closed && (j === 0)) { continue; }\n\n\t\t\t\tif (LineUtil.pointToSegmentDistance(p, part[k], part[j]) <= w) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n});\n\n// @factory L.polyline(latlngs: LatLng[], options?: Polyline options)\n// Instantiates a polyline object given an array of geographical points and\n// optionally an options object. You can create a `Polyline` object with\n// multiple separate lines (`MultiPolyline`) by passing an array of arrays\n// of geographic points.\nexport function polyline(latlngs, options) {\n\treturn new Polyline(latlngs, options);\n}\n\n// Retrocompat. Allow plugins to support Leaflet versions before and after 1.1.\nPolyline._flat = LineUtil._flat;\n","import {Polyline} from './Polyline';\nimport {LatLng} from '../../geo/LatLng';\nimport * as LineUtil from '../../geometry/LineUtil';\nimport {Point} from '../../geometry/Point';\nimport {Bounds} from '../../geometry/Bounds';\nimport * as PolyUtil from '../../geometry/PolyUtil';\n\n/*\n * @class Polygon\n * @aka L.Polygon\n * @inherits Polyline\n *\n * A class for drawing polygon overlays on a map. Extends `Polyline`.\n *\n * Note that points you pass when creating a polygon shouldn't have an additional last point equal to the first one — it's better to filter out such points.\n *\n *\n * @example\n *\n * ```js\n * // create a red polygon from an array of LatLng points\n * var latlngs = [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]];\n *\n * var polygon = L.polygon(latlngs, {color: 'red'}).addTo(map);\n *\n * // zoom the map to the polygon\n * map.fitBounds(polygon.getBounds());\n * ```\n *\n * You can also pass an array of arrays of latlngs, with the first array representing the outer shape and the other arrays representing holes in the outer shape:\n *\n * ```js\n * var latlngs = [\n * [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring\n * [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole\n * ];\n * ```\n *\n * Additionally, you can pass a multi-dimensional array to represent a MultiPolygon shape.\n *\n * ```js\n * var latlngs = [\n * [ // first polygon\n * [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring\n * [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole\n * ],\n * [ // second polygon\n * [[41, -111.03],[45, -111.04],[45, -104.05],[41, -104.05]]\n * ]\n * ];\n * ```\n */\n\nexport var Polygon = Polyline.extend({\n\n\toptions: {\n\t\tfill: true\n\t},\n\n\tisEmpty: function () {\n\t\treturn !this._latlngs.length || !this._latlngs[0].length;\n\t},\n\n\tgetCenter: function () {\n\t\t// throws error when not yet added to map as this center calculation requires projected coordinates\n\t\tif (!this._map) {\n\t\t\tthrow new Error('Must add layer to map before using getCenter()');\n\t\t}\n\n\t\tvar i, j, p1, p2, f, area, x, y, center,\n\t\t points = this._rings[0],\n\t\t len = points.length;\n\n\t\tif (!len) { return null; }\n\n\t\t// polygon centroid algorithm; only uses the first ring if there are multiple\n\n\t\tarea = x = y = 0;\n\n\t\tfor (i = 0, j = len - 1; i < len; j = i++) {\n\t\t\tp1 = points[i];\n\t\t\tp2 = points[j];\n\n\t\t\tf = p1.y * p2.x - p2.y * p1.x;\n\t\t\tx += (p1.x + p2.x) * f;\n\t\t\ty += (p1.y + p2.y) * f;\n\t\t\tarea += f * 3;\n\t\t}\n\n\t\tif (area === 0) {\n\t\t\t// Polygon is so small that all points are on same pixel.\n\t\t\tcenter = points[0];\n\t\t} else {\n\t\t\tcenter = [x / area, y / area];\n\t\t}\n\t\treturn this._map.layerPointToLatLng(center);\n\t},\n\n\t_convertLatLngs: function (latlngs) {\n\t\tvar result = Polyline.prototype._convertLatLngs.call(this, latlngs),\n\t\t len = result.length;\n\n\t\t// remove last point if it equals first one\n\t\tif (len >= 2 && result[0] instanceof LatLng && result[0].equals(result[len - 1])) {\n\t\t\tresult.pop();\n\t\t}\n\t\treturn result;\n\t},\n\n\t_setLatLngs: function (latlngs) {\n\t\tPolyline.prototype._setLatLngs.call(this, latlngs);\n\t\tif (LineUtil.isFlat(this._latlngs)) {\n\t\t\tthis._latlngs = [this._latlngs];\n\t\t}\n\t},\n\n\t_defaultShape: function () {\n\t\treturn LineUtil.isFlat(this._latlngs[0]) ? this._latlngs[0] : this._latlngs[0][0];\n\t},\n\n\t_clipPoints: function () {\n\t\t// polygons need a different clipping algorithm so we redefine that\n\n\t\tvar bounds = this._renderer._bounds,\n\t\t w = this.options.weight,\n\t\t p = new Point(w, w);\n\n\t\t// increase clip padding by stroke width to avoid stroke on clip edges\n\t\tbounds = new Bounds(bounds.min.subtract(p), bounds.max.add(p));\n\n\t\tthis._parts = [];\n\t\tif (!this._pxBounds || !this._pxBounds.intersects(bounds)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.options.noClip) {\n\t\t\tthis._parts = this._rings;\n\t\t\treturn;\n\t\t}\n\n\t\tfor (var i = 0, len = this._rings.length, clipped; i < len; i++) {\n\t\t\tclipped = PolyUtil.clipPolygon(this._rings[i], bounds, true);\n\t\t\tif (clipped.length) {\n\t\t\t\tthis._parts.push(clipped);\n\t\t\t}\n\t\t}\n\t},\n\n\t_updatePath: function () {\n\t\tthis._renderer._updatePoly(this, true);\n\t},\n\n\t// Needed by the `Canvas` renderer for interactivity\n\t_containsPoint: function (p) {\n\t\tvar inside = false,\n\t\t part, p1, p2, i, j, k, len, len2;\n\n\t\tif (!this._pxBounds || !this._pxBounds.contains(p)) { return false; }\n\n\t\t// ray casting algorithm for detecting if point is in polygon\n\t\tfor (i = 0, len = this._parts.length; i < len; i++) {\n\t\t\tpart = this._parts[i];\n\n\t\t\tfor (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) {\n\t\t\t\tp1 = part[j];\n\t\t\t\tp2 = part[k];\n\n\t\t\t\tif (((p1.y > p.y) !== (p2.y > p.y)) && (p.x < (p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x)) {\n\t\t\t\t\tinside = !inside;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// also check if it's on polygon stroke\n\t\treturn inside || Polyline.prototype._containsPoint.call(this, p, true);\n\t}\n\n});\n\n\n// @factory L.polygon(latlngs: LatLng[], options?: Polyline options)\nexport function polygon(latlngs, options) {\n\treturn new Polygon(latlngs, options);\n}\n","import {LayerGroup} from './LayerGroup';\r\nimport {FeatureGroup} from './FeatureGroup';\r\nimport * as Util from '../core/Util';\r\nimport {Marker} from './marker/Marker';\r\nimport {Circle} from './vector/Circle';\r\nimport {CircleMarker} from './vector/CircleMarker';\r\nimport {Polyline} from './vector/Polyline';\r\nimport {Polygon} from './vector/Polygon';\r\nimport {LatLng} from '../geo/LatLng';\r\nimport * as LineUtil from '../geometry/LineUtil';\r\n\r\n\r\n/*\r\n * @class GeoJSON\r\n * @aka L.GeoJSON\r\n * @inherits FeatureGroup\r\n *\r\n * Represents a GeoJSON object or an array of GeoJSON objects. Allows you to parse\r\n * GeoJSON data and display it on the map. Extends `FeatureGroup`.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * L.geoJSON(data, {\r\n * \tstyle: function (feature) {\r\n * \t\treturn {color: feature.properties.color};\r\n * \t}\r\n * }).bindPopup(function (layer) {\r\n * \treturn layer.feature.properties.description;\r\n * }).addTo(map);\r\n * ```\r\n */\r\n\r\nexport var GeoJSON = FeatureGroup.extend({\r\n\r\n\t/* @section\r\n\t * @aka GeoJSON options\r\n\t *\r\n\t * @option pointToLayer: Function = *\r\n\t * A `Function` defining how GeoJSON points spawn Leaflet layers. It is internally\r\n\t * called when data is added, passing the GeoJSON point feature and its `LatLng`.\r\n\t * The default is to spawn a default `Marker`:\r\n\t * ```js\r\n\t * function(geoJsonPoint, latlng) {\r\n\t * \treturn L.marker(latlng);\r\n\t * }\r\n\t * ```\r\n\t *\r\n\t * @option style: Function = *\r\n\t * A `Function` defining the `Path options` for styling GeoJSON lines and polygons,\r\n\t * called internally when data is added.\r\n\t * The default value is to not override any defaults:\r\n\t * ```js\r\n\t * function (geoJsonFeature) {\r\n\t * \treturn {}\r\n\t * }\r\n\t * ```\r\n\t *\r\n\t * @option onEachFeature: Function = *\r\n\t * A `Function` that will be called once for each created `Feature`, after it has\r\n\t * been created and styled. Useful for attaching events and popups to features.\r\n\t * The default is to do nothing with the newly created layers:\r\n\t * ```js\r\n\t * function (feature, layer) {}\r\n\t * ```\r\n\t *\r\n\t * @option filter: Function = *\r\n\t * A `Function` that will be used to decide whether to include a feature or not.\r\n\t * The default is to include all features:\r\n\t * ```js\r\n\t * function (geoJsonFeature) {\r\n\t * \treturn true;\r\n\t * }\r\n\t * ```\r\n\t * Note: dynamically changing the `filter` option will have effect only on newly\r\n\t * added data. It will _not_ re-evaluate already included features.\r\n\t *\r\n\t * @option coordsToLatLng: Function = *\r\n\t * A `Function` that will be used for converting GeoJSON coordinates to `LatLng`s.\r\n\t * The default is the `coordsToLatLng` static method.\r\n\t *\r\n\t * @option markersInheritOptions: Boolean = false\r\n\t * Whether default Markers for \"Point\" type Features inherit from group options.\r\n\t */\r\n\r\n\tinitialize: function (geojson, options) {\r\n\t\tUtil.setOptions(this, options);\r\n\r\n\t\tthis._layers = {};\r\n\r\n\t\tif (geojson) {\r\n\t\t\tthis.addData(geojson);\r\n\t\t}\r\n\t},\r\n\r\n\t// @method addData( data ): this\r\n\t// Adds a GeoJSON object to the layer.\r\n\taddData: function (geojson) {\r\n\t\tvar features = Util.isArray(geojson) ? geojson : geojson.features,\r\n\t\t i, len, feature;\r\n\r\n\t\tif (features) {\r\n\t\t\tfor (i = 0, len = features.length; i < len; i++) {\r\n\t\t\t\t// only add this if geometry or geometries are set and not null\r\n\t\t\t\tfeature = features[i];\r\n\t\t\t\tif (feature.geometries || feature.geometry || feature.features || feature.coordinates) {\r\n\t\t\t\t\tthis.addData(feature);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn this;\r\n\t\t}\r\n\r\n\t\tvar options = this.options;\r\n\r\n\t\tif (options.filter && !options.filter(geojson)) { return this; }\r\n\r\n\t\tvar layer = geometryToLayer(geojson, options);\r\n\t\tif (!layer) {\r\n\t\t\treturn this;\r\n\t\t}\r\n\t\tlayer.feature = asFeature(geojson);\r\n\r\n\t\tlayer.defaultOptions = layer.options;\r\n\t\tthis.resetStyle(layer);\r\n\r\n\t\tif (options.onEachFeature) {\r\n\t\t\toptions.onEachFeature(geojson, layer);\r\n\t\t}\r\n\r\n\t\treturn this.addLayer(layer);\r\n\t},\r\n\r\n\t// @method resetStyle( layer? ): this\r\n\t// Resets the given vector layer's style to the original GeoJSON style, useful for resetting style after hover events.\r\n\t// If `layer` is omitted, the style of all features in the current layer is reset.\r\n\tresetStyle: function (layer) {\r\n\t\tif (layer === undefined) {\r\n\t\t\treturn this.eachLayer(this.resetStyle, this);\r\n\t\t}\r\n\t\t// reset any custom styles\r\n\t\tlayer.options = Util.extend({}, layer.defaultOptions);\r\n\t\tthis._setLayerStyle(layer, this.options.style);\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method setStyle( style ): this\r\n\t// Changes styles of GeoJSON vector layers with the given style function.\r\n\tsetStyle: function (style) {\r\n\t\treturn this.eachLayer(function (layer) {\r\n\t\t\tthis._setLayerStyle(layer, style);\r\n\t\t}, this);\r\n\t},\r\n\r\n\t_setLayerStyle: function (layer, style) {\r\n\t\tif (layer.setStyle) {\r\n\t\t\tif (typeof style === 'function') {\r\n\t\t\t\tstyle = style(layer.feature);\r\n\t\t\t}\r\n\t\t\tlayer.setStyle(style);\r\n\t\t}\r\n\t}\r\n});\r\n\r\n// @section\r\n// There are several static functions which can be called without instantiating L.GeoJSON:\r\n\r\n// @function geometryToLayer(featureData: Object, options?: GeoJSON options): Layer\r\n// Creates a `Layer` from a given GeoJSON feature. Can use a custom\r\n// [`pointToLayer`](#geojson-pointtolayer) and/or [`coordsToLatLng`](#geojson-coordstolatlng)\r\n// functions if provided as options.\r\nexport function geometryToLayer(geojson, options) {\r\n\r\n\tvar geometry = geojson.type === 'Feature' ? geojson.geometry : geojson,\r\n\t coords = geometry ? geometry.coordinates : null,\r\n\t layers = [],\r\n\t pointToLayer = options && options.pointToLayer,\r\n\t _coordsToLatLng = options && options.coordsToLatLng || coordsToLatLng,\r\n\t latlng, latlngs, i, len;\r\n\r\n\tif (!coords && !geometry) {\r\n\t\treturn null;\r\n\t}\r\n\r\n\tswitch (geometry.type) {\r\n\tcase 'Point':\r\n\t\tlatlng = _coordsToLatLng(coords);\r\n\t\treturn _pointToLayer(pointToLayer, geojson, latlng, options);\r\n\r\n\tcase 'MultiPoint':\r\n\t\tfor (i = 0, len = coords.length; i < len; i++) {\r\n\t\t\tlatlng = _coordsToLatLng(coords[i]);\r\n\t\t\tlayers.push(_pointToLayer(pointToLayer, geojson, latlng, options));\r\n\t\t}\r\n\t\treturn new FeatureGroup(layers);\r\n\r\n\tcase 'LineString':\r\n\tcase 'MultiLineString':\r\n\t\tlatlngs = coordsToLatLngs(coords, geometry.type === 'LineString' ? 0 : 1, _coordsToLatLng);\r\n\t\treturn new Polyline(latlngs, options);\r\n\r\n\tcase 'Polygon':\r\n\tcase 'MultiPolygon':\r\n\t\tlatlngs = coordsToLatLngs(coords, geometry.type === 'Polygon' ? 1 : 2, _coordsToLatLng);\r\n\t\treturn new Polygon(latlngs, options);\r\n\r\n\tcase 'GeometryCollection':\r\n\t\tfor (i = 0, len = geometry.geometries.length; i < len; i++) {\r\n\t\t\tvar layer = geometryToLayer({\r\n\t\t\t\tgeometry: geometry.geometries[i],\r\n\t\t\t\ttype: 'Feature',\r\n\t\t\t\tproperties: geojson.properties\r\n\t\t\t}, options);\r\n\r\n\t\t\tif (layer) {\r\n\t\t\t\tlayers.push(layer);\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn new FeatureGroup(layers);\r\n\r\n\tdefault:\r\n\t\tthrow new Error('Invalid GeoJSON object.');\r\n\t}\r\n}\r\n\r\nfunction _pointToLayer(pointToLayerFn, geojson, latlng, options) {\r\n\treturn pointToLayerFn ?\r\n\t\tpointToLayerFn(geojson, latlng) :\r\n\t\tnew Marker(latlng, options && options.markersInheritOptions && options);\r\n}\r\n\r\n// @function coordsToLatLng(coords: Array): LatLng\r\n// Creates a `LatLng` object from an array of 2 numbers (longitude, latitude)\r\n// or 3 numbers (longitude, latitude, altitude) used in GeoJSON for points.\r\nexport function coordsToLatLng(coords) {\r\n\treturn new LatLng(coords[1], coords[0], coords[2]);\r\n}\r\n\r\n// @function coordsToLatLngs(coords: Array, levelsDeep?: Number, coordsToLatLng?: Function): Array\r\n// Creates a multidimensional array of `LatLng`s from a GeoJSON coordinates array.\r\n// `levelsDeep` specifies the nesting level (0 is for an array of points, 1 for an array of arrays of points, etc., 0 by default).\r\n// Can use a custom [`coordsToLatLng`](#geojson-coordstolatlng) function.\r\nexport function coordsToLatLngs(coords, levelsDeep, _coordsToLatLng) {\r\n\tvar latlngs = [];\r\n\r\n\tfor (var i = 0, len = coords.length, latlng; i < len; i++) {\r\n\t\tlatlng = levelsDeep ?\r\n\t\t\tcoordsToLatLngs(coords[i], levelsDeep - 1, _coordsToLatLng) :\r\n\t\t\t(_coordsToLatLng || coordsToLatLng)(coords[i]);\r\n\r\n\t\tlatlngs.push(latlng);\r\n\t}\r\n\r\n\treturn latlngs;\r\n}\r\n\r\n// @function latLngToCoords(latlng: LatLng, precision?: Number): Array\r\n// Reverse of [`coordsToLatLng`](#geojson-coordstolatlng)\r\nexport function latLngToCoords(latlng, precision) {\r\n\tprecision = typeof precision === 'number' ? precision : 6;\r\n\treturn latlng.alt !== undefined ?\r\n\t\t[Util.formatNum(latlng.lng, precision), Util.formatNum(latlng.lat, precision), Util.formatNum(latlng.alt, precision)] :\r\n\t\t[Util.formatNum(latlng.lng, precision), Util.formatNum(latlng.lat, precision)];\r\n}\r\n\r\n// @function latLngsToCoords(latlngs: Array, levelsDeep?: Number, closed?: Boolean): Array\r\n// Reverse of [`coordsToLatLngs`](#geojson-coordstolatlngs)\r\n// `closed` determines whether the first point should be appended to the end of the array to close the feature, only used when `levelsDeep` is 0. False by default.\r\nexport function latLngsToCoords(latlngs, levelsDeep, closed, precision) {\r\n\tvar coords = [];\r\n\r\n\tfor (var i = 0, len = latlngs.length; i < len; i++) {\r\n\t\tcoords.push(levelsDeep ?\r\n\t\t\tlatLngsToCoords(latlngs[i], levelsDeep - 1, closed, precision) :\r\n\t\t\tlatLngToCoords(latlngs[i], precision));\r\n\t}\r\n\r\n\tif (!levelsDeep && closed) {\r\n\t\tcoords.push(coords[0]);\r\n\t}\r\n\r\n\treturn coords;\r\n}\r\n\r\nexport function getFeature(layer, newGeometry) {\r\n\treturn layer.feature ?\r\n\t\tUtil.extend({}, layer.feature, {geometry: newGeometry}) :\r\n\t\tasFeature(newGeometry);\r\n}\r\n\r\n// @function asFeature(geojson: Object): Object\r\n// Normalize GeoJSON geometries/features into GeoJSON features.\r\nexport function asFeature(geojson) {\r\n\tif (geojson.type === 'Feature' || geojson.type === 'FeatureCollection') {\r\n\t\treturn geojson;\r\n\t}\r\n\r\n\treturn {\r\n\t\ttype: 'Feature',\r\n\t\tproperties: {},\r\n\t\tgeometry: geojson\r\n\t};\r\n}\r\n\r\nvar PointToGeoJSON = {\r\n\ttoGeoJSON: function (precision) {\r\n\t\treturn getFeature(this, {\r\n\t\t\ttype: 'Point',\r\n\t\t\tcoordinates: latLngToCoords(this.getLatLng(), precision)\r\n\t\t});\r\n\t}\r\n};\r\n\r\n// @namespace Marker\r\n// @section Other methods\r\n// @method toGeoJSON(precision?: Number): Object\r\n// `precision` is the number of decimal places for coordinates.\r\n// The default value is 6 places.\r\n// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the marker (as a GeoJSON `Point` Feature).\r\nMarker.include(PointToGeoJSON);\r\n\r\n// @namespace CircleMarker\r\n// @method toGeoJSON(precision?: Number): Object\r\n// `precision` is the number of decimal places for coordinates.\r\n// The default value is 6 places.\r\n// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the circle marker (as a GeoJSON `Point` Feature).\r\nCircle.include(PointToGeoJSON);\r\nCircleMarker.include(PointToGeoJSON);\r\n\r\n\r\n// @namespace Polyline\r\n// @method toGeoJSON(precision?: Number): Object\r\n// `precision` is the number of decimal places for coordinates.\r\n// The default value is 6 places.\r\n// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the polyline (as a GeoJSON `LineString` or `MultiLineString` Feature).\r\nPolyline.include({\r\n\ttoGeoJSON: function (precision) {\r\n\t\tvar multi = !LineUtil.isFlat(this._latlngs);\r\n\r\n\t\tvar coords = latLngsToCoords(this._latlngs, multi ? 1 : 0, false, precision);\r\n\r\n\t\treturn getFeature(this, {\r\n\t\t\ttype: (multi ? 'Multi' : '') + 'LineString',\r\n\t\t\tcoordinates: coords\r\n\t\t});\r\n\t}\r\n});\r\n\r\n// @namespace Polygon\r\n// @method toGeoJSON(precision?: Number): Object\r\n// `precision` is the number of decimal places for coordinates.\r\n// The default value is 6 places.\r\n// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the polygon (as a GeoJSON `Polygon` or `MultiPolygon` Feature).\r\nPolygon.include({\r\n\ttoGeoJSON: function (precision) {\r\n\t\tvar holes = !LineUtil.isFlat(this._latlngs),\r\n\t\t multi = holes && !LineUtil.isFlat(this._latlngs[0]);\r\n\r\n\t\tvar coords = latLngsToCoords(this._latlngs, multi ? 2 : holes ? 1 : 0, true, precision);\r\n\r\n\t\tif (!holes) {\r\n\t\t\tcoords = [coords];\r\n\t\t}\r\n\r\n\t\treturn getFeature(this, {\r\n\t\t\ttype: (multi ? 'Multi' : '') + 'Polygon',\r\n\t\t\tcoordinates: coords\r\n\t\t});\r\n\t}\r\n});\r\n\r\n\r\n// @namespace LayerGroup\r\nLayerGroup.include({\r\n\ttoMultiPoint: function (precision) {\r\n\t\tvar coords = [];\r\n\r\n\t\tthis.eachLayer(function (layer) {\r\n\t\t\tcoords.push(layer.toGeoJSON(precision).geometry.coordinates);\r\n\t\t});\r\n\r\n\t\treturn getFeature(this, {\r\n\t\t\ttype: 'MultiPoint',\r\n\t\t\tcoordinates: coords\r\n\t\t});\r\n\t},\r\n\r\n\t// @method toGeoJSON(precision?: Number): Object\r\n\t// `precision` is the number of decimal places for coordinates.\r\n\t// The default value is 6 places.\r\n\t// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the layer group (as a GeoJSON `FeatureCollection`, `GeometryCollection`, or `MultiPoint`).\r\n\ttoGeoJSON: function (precision) {\r\n\r\n\t\tvar type = this.feature && this.feature.geometry && this.feature.geometry.type;\r\n\r\n\t\tif (type === 'MultiPoint') {\r\n\t\t\treturn this.toMultiPoint(precision);\r\n\t\t}\r\n\r\n\t\tvar isGeometryCollection = type === 'GeometryCollection',\r\n\t\t jsons = [];\r\n\r\n\t\tthis.eachLayer(function (layer) {\r\n\t\t\tif (layer.toGeoJSON) {\r\n\t\t\t\tvar json = layer.toGeoJSON(precision);\r\n\t\t\t\tif (isGeometryCollection) {\r\n\t\t\t\t\tjsons.push(json.geometry);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tvar feature = asFeature(json);\r\n\t\t\t\t\t// Squash nested feature collections\r\n\t\t\t\t\tif (feature.type === 'FeatureCollection') {\r\n\t\t\t\t\t\tjsons.push.apply(jsons, feature.features);\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tjsons.push(feature);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tif (isGeometryCollection) {\r\n\t\t\treturn getFeature(this, {\r\n\t\t\t\tgeometries: jsons,\r\n\t\t\t\ttype: 'GeometryCollection'\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\treturn {\r\n\t\t\ttype: 'FeatureCollection',\r\n\t\t\tfeatures: jsons\r\n\t\t};\r\n\t}\r\n});\r\n\r\n// @namespace GeoJSON\r\n// @factory L.geoJSON(geojson?: Object, options?: GeoJSON options)\r\n// Creates a GeoJSON layer. Optionally accepts an object in\r\n// [GeoJSON format](https://tools.ietf.org/html/rfc7946) to display on the map\r\n// (you can alternatively add it later with `addData` method) and an `options` object.\r\nexport function geoJSON(geojson, options) {\r\n\treturn new GeoJSON(geojson, options);\r\n}\r\n\r\n// Backward compatibility.\r\nexport var geoJson = geoJSON;\r\n","import {Layer} from './Layer';\r\nimport * as Util from '../core/Util';\r\nimport {toLatLngBounds} from '../geo/LatLngBounds';\r\nimport {Bounds} from '../geometry/Bounds';\r\nimport * as DomUtil from '../dom/DomUtil';\r\n\r\n/*\r\n * @class ImageOverlay\r\n * @aka L.ImageOverlay\r\n * @inherits Interactive layer\r\n *\r\n * Used to load and display a single image over specific bounds of the map. Extends `Layer`.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * var imageUrl = 'http://www.lib.utexas.edu/maps/historical/newark_nj_1922.jpg',\r\n * \timageBounds = [[40.712216, -74.22655], [40.773941, -74.12544]];\r\n * L.imageOverlay(imageUrl, imageBounds).addTo(map);\r\n * ```\r\n */\r\n\r\nexport var ImageOverlay = Layer.extend({\r\n\r\n\t// @section\r\n\t// @aka ImageOverlay options\r\n\toptions: {\r\n\t\t// @option opacity: Number = 1.0\r\n\t\t// The opacity of the image overlay.\r\n\t\topacity: 1,\r\n\r\n\t\t// @option alt: String = ''\r\n\t\t// Text for the `alt` attribute of the image (useful for accessibility).\r\n\t\talt: '',\r\n\r\n\t\t// @option interactive: Boolean = false\r\n\t\t// If `true`, the image overlay will emit [mouse events](#interactive-layer) when clicked or hovered.\r\n\t\tinteractive: false,\r\n\r\n\t\t// @option crossOrigin: Boolean|String = false\r\n\t\t// Whether the crossOrigin attribute will be added to the image.\r\n\t\t// If a String is provided, the image will have its crossOrigin attribute set to the String provided. This is needed if you want to access image pixel data.\r\n\t\t// Refer to [CORS Settings](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) for valid String values.\r\n\t\tcrossOrigin: false,\r\n\r\n\t\t// @option errorOverlayUrl: String = ''\r\n\t\t// URL to the overlay image to show in place of the overlay that failed to load.\r\n\t\terrorOverlayUrl: '',\r\n\r\n\t\t// @option zIndex: Number = 1\r\n\t\t// The explicit [zIndex](https://developer.mozilla.org/docs/Web/CSS/CSS_Positioning/Understanding_z_index) of the overlay layer.\r\n\t\tzIndex: 1,\r\n\r\n\t\t// @option className: String = ''\r\n\t\t// A custom class name to assign to the image. Empty by default.\r\n\t\tclassName: ''\r\n\t},\r\n\r\n\tinitialize: function (url, bounds, options) { // (String, LatLngBounds, Object)\r\n\t\tthis._url = url;\r\n\t\tthis._bounds = toLatLngBounds(bounds);\r\n\r\n\t\tUtil.setOptions(this, options);\r\n\t},\r\n\r\n\tonAdd: function () {\r\n\t\tif (!this._image) {\r\n\t\t\tthis._initImage();\r\n\r\n\t\t\tif (this.options.opacity < 1) {\r\n\t\t\t\tthis._updateOpacity();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (this.options.interactive) {\r\n\t\t\tDomUtil.addClass(this._image, 'leaflet-interactive');\r\n\t\t\tthis.addInteractiveTarget(this._image);\r\n\t\t}\r\n\r\n\t\tthis.getPane().appendChild(this._image);\r\n\t\tthis._reset();\r\n\t},\r\n\r\n\tonRemove: function () {\r\n\t\tDomUtil.remove(this._image);\r\n\t\tif (this.options.interactive) {\r\n\t\t\tthis.removeInteractiveTarget(this._image);\r\n\t\t}\r\n\t},\r\n\r\n\t// @method setOpacity(opacity: Number): this\r\n\t// Sets the opacity of the overlay.\r\n\tsetOpacity: function (opacity) {\r\n\t\tthis.options.opacity = opacity;\r\n\r\n\t\tif (this._image) {\r\n\t\t\tthis._updateOpacity();\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\tsetStyle: function (styleOpts) {\r\n\t\tif (styleOpts.opacity) {\r\n\t\t\tthis.setOpacity(styleOpts.opacity);\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method bringToFront(): this\r\n\t// Brings the layer to the top of all overlays.\r\n\tbringToFront: function () {\r\n\t\tif (this._map) {\r\n\t\t\tDomUtil.toFront(this._image);\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method bringToBack(): this\r\n\t// Brings the layer to the bottom of all overlays.\r\n\tbringToBack: function () {\r\n\t\tif (this._map) {\r\n\t\t\tDomUtil.toBack(this._image);\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method setUrl(url: String): this\r\n\t// Changes the URL of the image.\r\n\tsetUrl: function (url) {\r\n\t\tthis._url = url;\r\n\r\n\t\tif (this._image) {\r\n\t\t\tthis._image.src = url;\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method setBounds(bounds: LatLngBounds): this\r\n\t// Update the bounds that this ImageOverlay covers\r\n\tsetBounds: function (bounds) {\r\n\t\tthis._bounds = toLatLngBounds(bounds);\r\n\r\n\t\tif (this._map) {\r\n\t\t\tthis._reset();\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\tgetEvents: function () {\r\n\t\tvar events = {\r\n\t\t\tzoom: this._reset,\r\n\t\t\tviewreset: this._reset\r\n\t\t};\r\n\r\n\t\tif (this._zoomAnimated) {\r\n\t\t\tevents.zoomanim = this._animateZoom;\r\n\t\t}\r\n\r\n\t\treturn events;\r\n\t},\r\n\r\n\t// @method setZIndex(value: Number): this\r\n\t// Changes the [zIndex](#imageoverlay-zindex) of the image overlay.\r\n\tsetZIndex: function (value) {\r\n\t\tthis.options.zIndex = value;\r\n\t\tthis._updateZIndex();\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method getBounds(): LatLngBounds\r\n\t// Get the bounds that this ImageOverlay covers\r\n\tgetBounds: function () {\r\n\t\treturn this._bounds;\r\n\t},\r\n\r\n\t// @method getElement(): HTMLElement\r\n\t// Returns the instance of [`HTMLImageElement`](https://developer.mozilla.org/docs/Web/API/HTMLImageElement)\r\n\t// used by this overlay.\r\n\tgetElement: function () {\r\n\t\treturn this._image;\r\n\t},\r\n\r\n\t_initImage: function () {\r\n\t\tvar wasElementSupplied = this._url.tagName === 'IMG';\r\n\t\tvar img = this._image = wasElementSupplied ? this._url : DomUtil.create('img');\r\n\r\n\t\tDomUtil.addClass(img, 'leaflet-image-layer');\r\n\t\tif (this._zoomAnimated) { DomUtil.addClass(img, 'leaflet-zoom-animated'); }\r\n\t\tif (this.options.className) { DomUtil.addClass(img, this.options.className); }\r\n\r\n\t\timg.onselectstart = Util.falseFn;\r\n\t\timg.onmousemove = Util.falseFn;\r\n\r\n\t\t// @event load: Event\r\n\t\t// Fired when the ImageOverlay layer has loaded its image\r\n\t\timg.onload = Util.bind(this.fire, this, 'load');\r\n\t\timg.onerror = Util.bind(this._overlayOnError, this, 'error');\r\n\r\n\t\tif (this.options.crossOrigin || this.options.crossOrigin === '') {\r\n\t\t\timg.crossOrigin = this.options.crossOrigin === true ? '' : this.options.crossOrigin;\r\n\t\t}\r\n\r\n\t\tif (this.options.zIndex) {\r\n\t\t\tthis._updateZIndex();\r\n\t\t}\r\n\r\n\t\tif (wasElementSupplied) {\r\n\t\t\tthis._url = img.src;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\timg.src = this._url;\r\n\t\timg.alt = this.options.alt;\r\n\t},\r\n\r\n\t_animateZoom: function (e) {\r\n\t\tvar scale = this._map.getZoomScale(e.zoom),\r\n\t\t offset = this._map._latLngBoundsToNewLayerBounds(this._bounds, e.zoom, e.center).min;\r\n\r\n\t\tDomUtil.setTransform(this._image, offset, scale);\r\n\t},\r\n\r\n\t_reset: function () {\r\n\t\tvar image = this._image,\r\n\t\t bounds = new Bounds(\r\n\t\t this._map.latLngToLayerPoint(this._bounds.getNorthWest()),\r\n\t\t this._map.latLngToLayerPoint(this._bounds.getSouthEast())),\r\n\t\t size = bounds.getSize();\r\n\r\n\t\tDomUtil.setPosition(image, bounds.min);\r\n\r\n\t\timage.style.width = size.x + 'px';\r\n\t\timage.style.height = size.y + 'px';\r\n\t},\r\n\r\n\t_updateOpacity: function () {\r\n\t\tDomUtil.setOpacity(this._image, this.options.opacity);\r\n\t},\r\n\r\n\t_updateZIndex: function () {\r\n\t\tif (this._image && this.options.zIndex !== undefined && this.options.zIndex !== null) {\r\n\t\t\tthis._image.style.zIndex = this.options.zIndex;\r\n\t\t}\r\n\t},\r\n\r\n\t_overlayOnError: function () {\r\n\t\t// @event error: Event\r\n\t\t// Fired when the ImageOverlay layer fails to load its image\r\n\t\tthis.fire('error');\r\n\r\n\t\tvar errorUrl = this.options.errorOverlayUrl;\r\n\t\tif (errorUrl && this._url !== errorUrl) {\r\n\t\t\tthis._url = errorUrl;\r\n\t\t\tthis._image.src = errorUrl;\r\n\t\t}\r\n\t}\r\n});\r\n\r\n// @factory L.imageOverlay(imageUrl: String, bounds: LatLngBounds, options?: ImageOverlay options)\r\n// Instantiates an image overlay object given the URL of the image and the\r\n// geographical bounds it is tied to.\r\nexport var imageOverlay = function (url, bounds, options) {\r\n\treturn new ImageOverlay(url, bounds, options);\r\n};\r\n","import {ImageOverlay} from './ImageOverlay';\r\nimport * as DomUtil from '../dom/DomUtil';\r\nimport * as Util from '../core/Util';\r\n\r\n/*\r\n * @class VideoOverlay\r\n * @aka L.VideoOverlay\r\n * @inherits ImageOverlay\r\n *\r\n * Used to load and display a video player over specific bounds of the map. Extends `ImageOverlay`.\r\n *\r\n * A video overlay uses the [`