diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000..a3a47a2 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,32 @@ +name: Docker +on: [push] + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + Docker: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Log in to the Container registry + uses: docker/login-action@v2 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v4 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + + - name: Build and push Docker image + uses: docker/build-push-action@v3 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..76e3cbe --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/config/* +/tools_config/* +.DS_Store \ No newline at end of file diff --git a/.htaccess.example b/.htaccess.example new file mode 100644 index 0000000..88ed2f2 --- /dev/null +++ b/.htaccess.example @@ -0,0 +1,5 @@ +Options -Indexes +AuthType Basic +AuthName "Restricted content" +AuthUserFile /var/www/html/config/.htpasswd +Require valid-user \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c71ca55 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +FROM php:7.2.2-apache + +# Remove folders from the html-folder (in case of an update) +WORKDIR /var/www/html/ +RUN rm -rf /var/www/html/* + +# Copy all files over to the working directory +COPY ./css/* /var/www/html/css/ +COPY ./other/* /var/www/html/other/ +COPY ./index.php /var/www/html/ + +# Copy config-files over to the working directory +# Uncomment the lines if you have set up a password +COPY ./config/config.env.php /var/www/html/config/config.php +#COPY ./config/.htpasswd /var/www/html/config/.htpasswd +#COPY ./.htaccess.example /var/www/html/.htaccess + +# Run the application +RUN docker-php-ext-install pdo pdo_mysql diff --git a/README.md b/README.md index 69136b7..e78be82 100644 --- a/README.md +++ b/README.md @@ -1,101 +1,34 @@ -![RealDeviceMap-tools](assets/map-header.png?raw=true) # RealDeviceMap-tools Tools for managing RealDeviceMap data +![RealDeviceMap-tools](assets/map-header.png?raw=true) -## rdm-tools.php -### Changes -* Now you can report on all nests at once! -* You don't have to have spawns/stops visible on map to perform reporting anymore. -* Revised optimization function - same super simple algorithm, might be better performing though -* Changes to data storage, functions no longer loop through map objects, coordinates for gyms/stops/spawns are stored separately. Should help with performance - -### Features -* View/hide known gyms, stops, and spawnpoints -* Optionally show only unknown gyms/stops -* Nest polygon import from OSM data, set to last datetime of Niantic OSM sync - * [date:"2018-04-09T01:32:00Z"] - * way["leisure"="park"] - * way["leisure"="recreation_ground"] - * way["landuse"="recreation_ground"] -* CSV and GeoJSON polygon import -* GeoJSON polygon export -* Coordinate generation - blanket fill polygons with route points -* Coordinate optimization - fill polygons with route points optimized for existing known gyms/stops/spawnpoints -* Instance import - view your RDM instances and add/remove route points, then reexport and upload to RDM - -### Installation -Simply upload rdm-tools.php to your favorite webserver, point the database variables to your RDM DB's IP, and configure your username/password. - -### Usage -The map has a variety of control buttons for performing different functions: - -#### ![Map Settings](assets/map-settings.png?raw=true) Settings -* Nest Migration Date - select the last nest migration. -* Optimization Attempts - number of passes to attempt to optimize coordinates during optimization. -* Circle Size - View distance radius (in meters) to route for. -* Generate all nests - Get a report of spawns for all nests in current map bounds. _See below_. - -#### Map mode -* ![Map Mode - Routing](assets/map-routing.png?raw=true) Enables full functionality including polygon and routing functions. -* ![Map Mode - Viewing](assets/map-viewing.png?raw=true) For viewing points of interest and spawnpoints only. Enables the option to filter unknown points of interest. - -#### View mode -* ![View Mode - Gyms](assets/map-view-gyms.png?raw=true) Enables/disables viewing gyms as red dots on the map. -* ![View Mode - Pokestops](assets/map-view-stops.png?raw=true) Enables/disables viewing pokestops as green dots on the map. -* ![View Mode - Spawnpoints](assets/map-view-spawns.png?raw=true) Enables/disables viewing spawnpoints as blue dots on the map. - -#### Routing and Drawing -* ![Draw Polygon](assets/map-draw-polygon.png?raw=true) Enables drawing of polygons on the map. -* ![Manual route placement](assets/map-place-circle.png?raw=true) Enables/disables manual placement of route points. Click on the map to drop a route point in the routing layer based on view radius setting. -* ![Import Nests](assets/map-import-nests.png?raw=true) Pulls nest data from OSM and places polygons in the current map bounds covering all parks. -* ![Import Polygon](assets/map-import-polygon.png?raw=true) Import CSV or GeoJSON polygon data. GeoJSON can contain multiple polygons, each one will be placed individually. -* ![Import Instance](assets/map-import-instance.png?raw=true) Imports an instance from your RDM DB and places the route points in the routing layer based on view radius setting. -* ![Clear Routing Layer](assets/map-clear-routing-layer.png?raw=true) Clears the current route from the map, leaving polygons behind -* ![Clear All Layers](assets/map-clear-all-layers.png?raw=true) Clears all route points and polygons from map. -* ![Generate Route](assets/map-generate-route.png?raw=true) Generates a blanket route over all polygons on the map. -* ![Optimize Route](assets/map-optimize-route.png?raw=true) Takes all visible points - gyms, stops, and spawns - and optimizes a route between them based on view radius (circle size). -* ![Get Output](assets/map-get-output.png?raw=true) Opens a textbox to generate lat,lon points for all routing layer coordinates, to be saved as an instance in RDM. - -#### Polygon options -![Polygon Options](assets/polygon-options.png?raw=true) - -Clicking on any polygon will allow you to generate a spawn report, remove it from the map, or export as GeoJSON. - -To generate a spawn report, keep in mind the Nest Migration Date setting. The query generated for your database will only grab spawn data from that point forward. If you are just looking to get data for your area and not specifically reporting on a nest, set the date accordingly before generating your report. Once generated, a modal window will open showing a table of all the spawn counts for that polygon. - -![Example spawn report](assets/example-spawn-report.png?raw=true) - -Example spawn report for a local nest. - -#### New feature - generate a spawn report for all nests -In the settings menu, a new button is available to create a report for all nests in your current map bounds. Make sure you import nest polygons first! - -![Example spawn report](assets/example-all-nests-report.png?raw=true) - -Example multi-nest report - -#### Route options -![Route Options](assets/route-point-options.png?raw=true) - -After a route is generated, you can click on any point of the route to remove it from the map. - -## Example outputs -![Example spawn route](assets/example-blanket-route-spawn.png?raw=true) - -Example route showing a blanket route of 75m circles covering a town for finding new spawn points. - -![Example gym route](assets/example-blanket-route-gym.png?raw=true) - -Example route showing the same polygon covered with 500m circles for finding new raids and stops. - -![Example optimized gym route](assets/example-optimized-route-gyms.png?raw=true) - -Example optimization covering gyms in a polygon - -![Example nest route](assets/example-blanket-route-nest.png?raw=true) - -Example optimization covering all nests in map bounds, for finding new spawnpoints in nests - -![Example optimized nest route](assets/example-optimized-route-nests.png?raw=true) - -Example optimization covering known spawnpoints in multiple nests. Note that you can remove overlapping circles by clicking on them and choosing delete - the optimization routine still needs some work. +## Changes +* Added more details to the import of administrative boundaries +* Distance between points on routes is colored +* Option to show routes for instances, generate new routes for instances or drawn circles and visualize it directly +* Added Dockerfile to generate a local image +* Autogeneration of the correct circle size for raid instances depending on the specific latitude, option in settings to choose between iv-, raid- or own radius +* Color Picker built in for instance- and polygon-import + +## Installation +1. `git clone https://github.com/PickleRickVE/RealDeviceMap-tools` +2. Enter the new folder `cd RealDeviceMap-tools` and go to the config folder `cd config` +2. Edit `nano config.env.php` and add your credentials for the RDM and/or Nest database. +3. Edit `nano .htpasswd` to set a username and password. The default user is **admin** with password **admin**, you can generate one [here](https://www.web2generators.com/apache-tools/htpasswd-generator). + +### Optional: when running Docker +1. Paste the contents from docker-compose.example.yml in the files where RDM & it's database is located and edit where needed +2. Check Dockerfile and uncomment the line with .htaccess if you want to use a password +3. Run `docker-compose up -d --build rdm_tools` + +## Updates +1. Use git pull in the folder +2. When using Docker, re-run `docker-compose up -d --build rdm_tools` + +## Usage +For more info please use the [wiki](https://github.com/PickleRickVE/RealDeviceMap-tools/wiki). + +## Thanks +* Credit to [abakedapplepie](https://github.com/abakedapplepie) and his creditors for the base +* Credit to [lovasoa](https://github.com/lovasoa) for the traveling salesman script +* Credit to [leevo](https://github.com/xxleevo) for various ideas diff --git a/assets/README.md b/assets/README.md deleted file mode 100644 index 818d7dd..0000000 --- a/assets/README.md +++ /dev/null @@ -1 +0,0 @@ -# README Assets diff --git a/assets/example-all-nests-report.png b/assets/example-all-nests-report.png deleted file mode 100644 index 190fbc3..0000000 Binary files a/assets/example-all-nests-report.png and /dev/null differ diff --git a/assets/example-blanket-route-gym.png b/assets/example-blanket-route-gym.png deleted file mode 100644 index 8f9ac20..0000000 Binary files a/assets/example-blanket-route-gym.png and /dev/null differ diff --git a/assets/example-blanket-route-nest.png b/assets/example-blanket-route-nest.png deleted file mode 100644 index 242805b..0000000 Binary files a/assets/example-blanket-route-nest.png and /dev/null differ diff --git a/assets/example-blanket-route-spawn.png b/assets/example-blanket-route-spawn.png deleted file mode 100644 index 3de4102..0000000 Binary files a/assets/example-blanket-route-spawn.png and /dev/null differ diff --git a/assets/example-optimized-route-gyms.png b/assets/example-optimized-route-gyms.png deleted file mode 100644 index 95c9eb5..0000000 Binary files a/assets/example-optimized-route-gyms.png and /dev/null differ diff --git a/assets/example-optimized-route-nests.png b/assets/example-optimized-route-nests.png deleted file mode 100644 index 9b2c912..0000000 Binary files a/assets/example-optimized-route-nests.png and /dev/null differ diff --git a/assets/example-spawn-report.png b/assets/example-spawn-report.png deleted file mode 100644 index 207c47e..0000000 Binary files a/assets/example-spawn-report.png and /dev/null differ diff --git a/assets/map-clear-all-layers.png b/assets/map-clear-all-layers.png deleted file mode 100644 index afdaf44..0000000 Binary files a/assets/map-clear-all-layers.png and /dev/null differ diff --git a/assets/map-clear-routing-layer.png b/assets/map-clear-routing-layer.png deleted file mode 100644 index 17c85d4..0000000 Binary files a/assets/map-clear-routing-layer.png and /dev/null differ diff --git a/assets/map-draw-polygon.png b/assets/map-draw-polygon.png deleted file mode 100644 index 1976139..0000000 Binary files a/assets/map-draw-polygon.png and /dev/null differ diff --git a/assets/map-generate-route.png b/assets/map-generate-route.png deleted file mode 100644 index ffc7534..0000000 Binary files a/assets/map-generate-route.png and /dev/null differ diff --git a/assets/map-get-output.png b/assets/map-get-output.png deleted file mode 100644 index c7d5605..0000000 Binary files a/assets/map-get-output.png and /dev/null differ diff --git a/assets/map-header.png b/assets/map-header.png index 9618705..d95d1df 100644 Binary files a/assets/map-header.png and b/assets/map-header.png differ diff --git a/assets/map-import-instance.png b/assets/map-import-instance.png deleted file mode 100644 index a6cde15..0000000 Binary files a/assets/map-import-instance.png and /dev/null differ diff --git a/assets/map-import-nests.png b/assets/map-import-nests.png deleted file mode 100644 index 69c4cfa..0000000 Binary files a/assets/map-import-nests.png and /dev/null differ diff --git a/assets/map-import-polygon.png b/assets/map-import-polygon.png deleted file mode 100644 index 589473d..0000000 Binary files a/assets/map-import-polygon.png and /dev/null differ diff --git a/assets/map-optimize-route.png b/assets/map-optimize-route.png deleted file mode 100644 index fe767ec..0000000 Binary files a/assets/map-optimize-route.png and /dev/null differ diff --git a/assets/map-place-circle.png b/assets/map-place-circle.png deleted file mode 100644 index 6e049d1..0000000 Binary files a/assets/map-place-circle.png and /dev/null differ diff --git a/assets/map-routing.png b/assets/map-routing.png deleted file mode 100644 index ef157eb..0000000 Binary files a/assets/map-routing.png and /dev/null differ diff --git a/assets/map-settings.png b/assets/map-settings.png deleted file mode 100644 index ee89a70..0000000 Binary files a/assets/map-settings.png and /dev/null differ diff --git a/assets/map-view-gyms.png b/assets/map-view-gyms.png deleted file mode 100644 index a21dc98..0000000 Binary files a/assets/map-view-gyms.png and /dev/null differ diff --git a/assets/map-view-spawns.png b/assets/map-view-spawns.png deleted file mode 100644 index 841ceee..0000000 Binary files a/assets/map-view-spawns.png and /dev/null differ diff --git a/assets/map-view-stops.png b/assets/map-view-stops.png deleted file mode 100644 index 58b2e1b..0000000 Binary files a/assets/map-view-stops.png and /dev/null differ diff --git a/assets/map-viewing.png b/assets/map-viewing.png deleted file mode 100644 index 17de06f..0000000 Binary files a/assets/map-viewing.png and /dev/null differ diff --git a/assets/polygon-options.png b/assets/polygon-options.png deleted file mode 100644 index f8ceea0..0000000 Binary files a/assets/polygon-options.png and /dev/null differ diff --git a/assets/route-point-options.png b/assets/route-point-options.png deleted file mode 100644 index dc21b68..0000000 Binary files a/assets/route-point-options.png and /dev/null differ diff --git a/assets/settings-button.png b/assets/settings-button.png new file mode 100644 index 0000000..1ee6e60 Binary files /dev/null and b/assets/settings-button.png differ diff --git a/assets/settings.png b/assets/settings.png new file mode 100644 index 0000000..d910b42 Binary files /dev/null and b/assets/settings.png differ diff --git a/config/.htpasswd b/config/.htpasswd new file mode 100644 index 0000000..29351a9 --- /dev/null +++ b/config/.htpasswd @@ -0,0 +1 @@ +admin:$apr1$1edgsm5o$xGC./.P3PARUp1x56wEIx/ \ No newline at end of file diff --git a/config/config.env.php b/config/config.env.php new file mode 100644 index 0000000..0713fef --- /dev/null +++ b/config/config.env.php @@ -0,0 +1,21 @@ + diff --git a/css/leaflet-search.css b/css/leaflet-search.css new file mode 100644 index 0000000..7747d6d --- /dev/null +++ b/css/leaflet-search.css @@ -0,0 +1,134 @@ +/* + * Leaflet Control Search v2.9.7 - 2019-01-14 + * + * Copyright 2019 Stefano Cudini + * stefano.cudini@gmail.com + * http://labs.easyblog.it/ + * + * Licensed under the MIT license. + * + * Demo: + * http://labs.easyblog.it/maps/leaflet-search/ + * + * Source: + * git@github.com:stefanocudini/leaflet-search.git + * + */ + +.leaflet-container .leaflet-control-search { + position:relative; + float:left; + background:#fff; + color:#1978cf; + border: 2px solid rgba(0,0,0,0.2); + background-clip: padding-box; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + background-color: rgba(255, 255, 255, 0.8); + z-index:1000; + margin-left: 10px; + margin-top: 10px; +} +.leaflet-control-search.search-exp {/*expanded*/ + background: #fff; + border: 2px solid rgba(0,0,0,0.2); + background-clip: padding-box; +} +.leaflet-control-search .search-input { + display:block; + float:left; + background: #fff; + border:1px solid #666; + border-radius:2px; + height:22px; + padding:0 20px 0 2px; + margin:4px 0 4px 4px; +} +.leaflet-control-search.search-load .search-input { + background: url('../other/loader.gif') no-repeat center right #fff; +} +.leaflet-control-search.search-load .search-cancel { + visibility:hidden; +} +.leaflet-control-search .search-cancel { + display:block; + width:22px; + height:22px; + position:absolute; + right:28px; + margin:6px 0; + background: url('../other/search-icon.png') no-repeat 0 -46px; + text-decoration:none; + filter: alpha(opacity=80); + opacity: 0.8; +} +.leaflet-control-search .search-cancel:hover { + filter: alpha(opacity=100); + opacity: 1; +} +.leaflet-control-search .search-cancel span { + display:none;/* comment for cancel button imageless */ + font-size:18px; + line-height:20px; + color:#ccc; + font-weight:bold; +} +.leaflet-control-search .search-cancel:hover span { + color:#aaa; +} +.leaflet-control-search .search-button { + display:block; + float:left; + width:30px; + height:30px; + background: url('../other/search-icon.png') no-repeat 4px 4px #fff; + border-radius:4px; +} +.leaflet-control-search .search-button:hover { + background: url('../other/search-icon.png') no-repeat 4px -20px #fafafa; +} +.leaflet-control-search .search-tooltip { + position:absolute; + top:100%; + left:0; + float:left; + list-style: none; + padding-left: 0; + min-width:120px; + max-height:122px; + box-shadow: 1px 1px 6px rgba(0,0,0,0.4); + background-color: rgba(0, 0, 0, 0.25); + z-index:1010; + overflow-y:auto; + overflow-x:hidden; + cursor: pointer; +} +.leaflet-control-search .search-tip { + margin:2px; + padding:2px 4px; + display:block; + color:black; + background: #eee; + border-radius:.25em; + text-decoration:none; + white-space:nowrap; + vertical-align:center; +} +.leaflet-control-search .search-button:hover { + background-color: #f4f4f4; +} +.leaflet-control-search .search-tip-select, +.leaflet-control-search .search-tip:hover { + background-color: #fff; +} +.leaflet-control-search .search-alert { + cursor:pointer; + clear:both; + font-size:.75em; + margin-bottom:5px; + padding:0 .25em; + color:#e00; + font-weight:bold; + border-radius:.25em; +} \ No newline at end of file diff --git a/css/multi.select.css b/css/multi.select.css new file mode 100644 index 0000000..161b15a --- /dev/null +++ b/css/multi.select.css @@ -0,0 +1,9 @@ +.wrapper{float:left;width:100%;margin:20px 0} +.fill{color:#fff!important} +.button-blue.fill{background-color:#367fa9} +.button-green.fill{background-color:#5F9323} +.button-aqua.fill{background-color:#00acd6}.button-red.fill{background-color:#d73925} +.button-yellow.fill{background-color:#e08e0b}.button-maroon.fill{background-color:#b20e48} +.button-purple.fill{background-color:#555299}.button-grey.fill{background-color:#5d636e} +.multi-button, +.button{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:600;line-height:1.42857143;text-align:left;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:1px;background-color:#fff}.multi-button::after{background-color:transparent;border-left:none;box-sizing:border-box;color:#fff;content:"\2207";display:inline-block;font-family:"FontAwesome";height:100%;margin-left:-17px;padding:4px 4px 0 3px;pointer-events:none;position:absolute;right:0;text-align:center;top:0;vertical-align:middle;width:23px;z-index:2;transition:transform .25s linear;-webkit-transition:-webkit-transform .25s linear}.multi-button.open::after{font-weight:700;-webkit-transform:rotate(180deg);transform:rotate(180deg);padding:6px 4px 0 3px}.test-values{border-radius:4px;margin-left:10px}.button-xsmall{padding:1px 5px;font-size:12px;line-height:1.5;color:#333}.button-small{padding:5px 10px;font-size:12px;line-height:1.5;color:#333}.button-big{padding:10px 16px;font-size:18px;line-height:1.5;color:#333}.multi-button.button-file{position:relative;overflow:hidden}.button-blue{border-color:#367fa9}.button-blue:hover,.button-blue:active{border-color:#367fa9}.button-green{border-color:#5F9323}.button-green:hover,.button-green:active{border-color:#5F9323}.button-aqua{border-color:#00acd6}.button-aqua:hover,.button-aqua:active{border-color:#00acd6}.button-red{border-color:#d73925}.button-red:hover,.button-red:active{border-color:#d73925}.button-yellow{border-color:#e08e0b}.button-yellow:hover,.button-yellow:active{border-color:#e08e0b}.button-maroon{border-color:#b20e48}.button-maroon:hover,.button-maroon:active{border-color:#b20e48}.button-purple{border-color:#555299}.button-purple:hover,.button-purple:active{border-color:#302c85}.button-grey{border-color:#5d636e}.button-grey:hover,.button-grey:active{border-color:#5d636e}.button-file input[type=file]{position:absolute;top:0;right:0;min-width:100%;min-height:100%;font-size:100px;text-align:right;filter:alpha(opacity=0);opacity:0;outline:none;background:white;cursor:inherit;display:block}.multi-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:0 0 1px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175);width:100%}.open>.multi-menu{display:block}.multi-menu li{position:relative;padding:5px 10px;margin-top:1px}.multi-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.multi-menu li a span.text{display:inline-block;position:relative}.multi-menu li a span.check-mark{display:none}.multi-menu li.selected a span.check-mark{position:absolute;display:inline-block;right:15px;margin-top:0}.multi-menu li .searchbox{padding:4px 8px}.multi-menu li .searchbox .search-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;margin-bottom:0;width:100%;float:none}.multi-menu li.control,.multi-menu li.control:hover{background-color:#fff!important}.multi-menu li.control a.select-all-none{color:#000!important}.multi-menu li.control:hover a.select-all-none{color:#444!important}.multi-button .multi-menu li:hover{background-color:#efefef}.button-blue .multi-menu li.selected,.button-blue .multi-menu li.selected:hover,.button-blue .multi-menu li.controls{background-color:#3c8dbc}.button-blue .multi-menu li.selected a{color:#fff}.button-green .multi-menu li.selected,.button-green .multi-menu li.selected:hover,.button-green .multi-menu li.controls{background-color:#67a028}.button-green .multi-menu li.selected a{color:#fff}.button-aqua .multi-menu li.selected,.button-aqua .multi-menu li.selected:hover,.button-aqua .multi-menu li.controls{background-color:#00c0ef}.button-aqua .multi-menu li.selected a{color:#fff}.button-red .multi-menu li.selected,.button-red .multi-menu li.selected:hover,.button-red .multi-menu li.controls{background-color:#dd4b39}.button-red .multi-menu li.selected a{color:#fff}.button-yellow .multi-menu li.selected,.button-yellow .multi-menu li.selected:hover,.button-yellow .multi-menu li.controls{background-color:#f39c12}.button-yellow .multi-menu li.selected a{color:#fff}.button-maroon .multi-menu li.selected,.button-maroon .multi-menu li.selected:hover,.button-maroon .multi-menu li.controls{background-color:#B7174F}.button-maroon .multi-menu li.selected a{color:#fff}.button-purple .multi-menu li.selected,.button-purple .multi-menu li.selected:hover,.button-purple .multi-menu li.controls{background-color:#555299}.button-purple .multi-menu li.selected a{color:#fff}.button-grey .multi-menu li.selected,.button-grey .multi-menu li.selected:hover,.button-grey .multi-menu li.controls{background-color:#80848c}.button-grey .multi-menu li.selected a{color:#fff}.multi-button .button-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:94%;display:inline-block;vertical-align:bottom}ol,ul{margin-top:10px;margin-bottom:10px}.list-wrapper{padding-left:0;margin-bottom:20px}.list-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-item .file-name{max-width:90%;width:auto;white-space:nowrap;overflow:hidden!important;text-overflow:ellipsis;display:inline-block}.overflow-list{max-height:302px;overflow-y:auto;overflow-x:hidden;width:20%}.float-left{float:left!important}.float-right{float:right!important}.icon-upload{background-attachment:scroll;background-repeat:no-repeat;background-image:url(../images/icons/upload-up-white.svg);background-position:0 0;background-size:100% auto;margin:0;padding:0;display:inline-block;min-height:15px;min-width:16px}.icon-upload-o{background-attachment:scroll;background-repeat:no-repeat;background-image:url(../images/icons/upload-button.svg);background-position:0 0;background-size:100% auto;margin:0;padding:0;display:inline-block;min-height:14px;min-width:16px}.remove-file{font-weight:700}.remove-icon{position:absolute;bottom:-9px;right:-9px;font-weight:700}.data-display{display:block;float:left;list-style:none}.data-display li{border:1px solid #ccc;margin-left:-1px;float:left;padding:5px 10px;margin-top:-1px;min-width:30px;text-align:center} diff --git a/css/pick-a-color-1.2.3.min.css b/css/pick-a-color-1.2.3.min.css new file mode 100644 index 0000000..341cce6 --- /dev/null +++ b/css/pick-a-color-1.2.3.min.css @@ -0,0 +1,86 @@ + +.pick-a-color-markup *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box} +.pick-a-color-markup .hex-pound{padding-left:8px;padding-right:8px}@media screen and (max-width:991px){.pick-a-color-markup .hex-pound{padding:3px 5px 0px 5px;min-height:30px}} +.pick-a-color-markup .pick-a-color{padding:5px}@media screen and (max-width:991px){.pick-a-color-markup .pick-a-color{width:100%;font-size:18px;padding:9px;min-width:222px;height:47px}} +.pick-a-color-markup .input-group-btn .color-dropdown{padding:6px 5px}.pick-a-color-markup .input-group-btn .color-dropdown.no-hex{border-bottom-left-radius:4px;border-top-left-radius:4px} +.pick-a-color-markup .input-group-btn .color-dropdown:focus{background-color:#fff} +@media screen and (max-width:991px){.pick-a-color-markup .input-group-btn .color-dropdown{height:47px}} +.pick-a-color-markup .color-preview{border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 0 2px 2px rgba(0,0,0,0.075);box-shadow:inset 0 0 2px 2px rgba(0,0,0,0.075);height:1.429em;width:1.429em;display:inline-block;cursor:pointer;margin-right:5px}.pick-a-color-markup .color-preview.current-color{margin-bottom:-5px} +@media screen and (max-width:991px){.pick-a-color-markup .color-preview{height:1.875em;width:1.875em}} +.pick-a-color-markup .color-menu{text-align:left;padding:5px 0px;width:330px;font-size:14px;left:auto;}.pick-a-color-markup .color-menu.color-menu--inline{left:-285px}@media screen and (max-width:991px){.pick-a-color-markup .color-menu.color-menu--inline{left:-242px}} +@media screen and (max-width:991px){.pick-a-color-markup .color-menu{left:-242px;width:293px}}.pick-a-color-markup .color-menu.small{width:100px}@media screen and (max-width:991px){.pick-a-color-markup .color-menu.small{left:-105px}} +.pick-a-color-markup .color-menu.no-hex{left:0px} +.pick-a-color-markup .color-menu ul{padding:0px;margin:0px} +.pick-a-color-markup .color-menu li{list-style-type:none;padding:5px 0px;margin:0px} +.pick-a-color-markup .color-menu .color-preview{vertical-align:middle;margin:0px}@media screen and (max-width:991px){.pick-a-color-markup .color-menu .color-preview{height:35px;width:35px}}.pick-a-color-markup .color-menu .color-preview.current-color,.pick-a-color-markup .color-menu .color-preview.white{background-color:#fff} +.pick-a-color-markup .color-menu .color-preview.red{background-color:#f00} +.pick-a-color-markup .color-menu .color-preview.orange{background-color:#f60} +.pick-a-color-markup .color-menu .color-preview.yellow{background-color:#ff0} +.pick-a-color-markup .color-menu .color-preview.green{background-color:#008000} +.pick-a-color-markup .color-menu .color-preview.blue{background-color:#00f} +.pick-a-color-markup .color-menu .color-preview.indigo{background-color:#4a0080} +.pick-a-color-markup .color-menu .color-preview.violet{background-color:#ee81ee} +.pick-a-color-markup .color-menu .color-preview.purple{background-color:#80007f} +.pick-a-color-markup .color-menu .color-preview.black{background-color:#000} +.pick-a-color-markup .color-menu .basicColors-content li>a,.pick-a-color-markup .color-menu .savedColors-content li>a{padding:5px 15px 3px 15px;cursor:default;min-height:25px;color:#333}.pick-a-color-markup .color-menu .basicColors-content li>a:hover,.pick-a-color-markup .color-menu .savedColors-content li>a:hover{background-color:#fff} +@media screen and (max-width:991px){.pick-a-color-markup .color-menu .basicColors-content li>a,.pick-a-color-markup .color-menu .savedColors-content li>a{min-height:40px}} +.pick-a-color-markup .color-menu .basicColors-content li:hover a,.pick-a-color-markup .color-menu .savedColors-content li:hover a{color:#333;background-image:none;filter:none;text-decoration:none;font-weight:bold}@media screen and (max-width:991px){.pick-a-color-markup .color-menu .basicColors-content li:hover a,.pick-a-color-markup .color-menu .savedColors-content li:hover a{background-color:#fff;font-weight:normal}} +.pick-a-color-markup .color-menu .btn.color-select{margin:0px 5px;height:20px;padding:0px 5px;margin-top:0px;line-height:1.5px;border-radius:4px}@media screen and (max-width:991px){.pick-a-color-markup .color-menu .btn.color-select{height:35px}} +.pick-a-color-markup .caret{margin-bottom:3px} +.pick-a-color-markup .color-menu-instructions,.pick-a-color-markup .advanced-instructions{text-align:center;padding:0px 6px;margin:0px;font-size:14px;font-weight:normal}@media screen and (min-width:992px){.pick-a-color-markup .color-menu-instructions,.pick-a-color-markup .advanced-instructions{display:none}} +.pick-a-color-markup .color-label{vertical-align:middle;margin:0px;margin-left:10px;cursor:pointer}@media screen and (max-width:991px){.pick-a-color-markup .color-label{margin-left:8px}} +.pick-a-color-markup .color-box{height:20px;width:200px;position:absolute;left:115px;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 0 2px 2px rgba(0,0,0,0.075);box-shadow:inset 0 0 2px 2px rgba(0,0,0,0.075);cursor:pointer}@media screen and (max-width:991px){.pick-a-color-markup .color-box{width:160px;height:35px}} +.pick-a-color-markup .black .highlight-band-stripe{background-color:#fff} +.pick-a-color-markup .spectrum-white{background-image:-webkit-gradient(linear, 0 top, 100% top, from(#fff), to(#808080));background-image:-webkit-linear-gradient(left, color-stop(#fff 0), color-stop(#808080 100%));background-image:-moz-linear-gradient(left, #fff 0, #808080 100%);background-image:linear-gradient(to right, #fff 0, #808080 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ff808080', GradientType=1)}.pick-a-color-markup .spectrum-white .highlight-band{left:0px} +.pick-a-color-markup .spectrum-red{background-image:-webkit-gradient(linear, left top, right top, color-stop(0, #fff), color-stop(.5, #f00), color-stop(1, #000));background-image:-moz-linear-gradient(left center, #fff 0, #f00 50%, #000 100%);background-image:-webkit-linear-gradient(left, #fff 0, #f00 50%, #000 100%);background-image:-o-linear-gradient(left, #fff 0, #f00 50%, #000 100%);background-image:linear-gradient(to right, #fff 0, #f00 50%, #000 100%);background-repeat:repeat-x} +.pick-a-color-markup .spectrum-orange{background-image:-webkit-gradient(linear, left top, right top, color-stop(0, #fff), color-stop(.5, #f60), color-stop(1, #000));background-image:-moz-linear-gradient(left center, #fff 0, #f60 50%, #000 100%);background-image:-webkit-linear-gradient(left, #fff 0, #f60 50%, #000 100%);background-image:-o-linear-gradient(left, #fff 0, #f60 50%, #000 100%);background-image:linear-gradient(to right, #fff 0, #f60 50%, #000 100%);background-repeat:repeat-x} +.pick-a-color-markup .spectrum-yellow{background-image:-webkit-gradient(linear, left top, right top, color-stop(0, #fff), color-stop(.5, #ff0), color-stop(1, #000));background-image:-moz-linear-gradient(left center, #fff 0, #ff0 50%, #000 100%);background-image:-webkit-linear-gradient(left, #fff 0, #ff0 50%, #000 100%);background-image:-o-linear-gradient(left, #fff 0, #ff0 50%, #000 100%);background-image:linear-gradient(to right, #fff 0, #ff0 50%, #000 100%);background-repeat:repeat-x} +.pick-a-color-markup .spectrum-green{background-image:-webkit-gradient(linear, left top, right top, color-stop(0, #80ff80), color-stop(.5, #008000), color-stop(1, #000));background-image:-moz-linear-gradient(left center, #80ff80 0, #008000 50%, #000 100%);background-image:-webkit-linear-gradient(left, #80ff80 0, #008000 50%, #000 100%);background-image:-o-linear-gradient(left, #80ff80 0, #008000 50%, #000 100%);background-image:linear-gradient(to right, #80ff80 0, #008000 50%, #000 100%);background-repeat:repeat-x} +.pick-a-color-markup .spectrum-blue{background-image:-webkit-gradient(linear, left top, right top, color-stop(0, #fff), color-stop(.5, #00f), color-stop(1, #000));background-image:-moz-linear-gradient(left center, #fff 0, #00f 50%, #000 100%);background-image:-webkit-linear-gradient(left, #fff 0, #00f 50%, #000 100%);background-image:-o-linear-gradient(left, #fff 0, #00f 50%, #000 100%);background-image:linear-gradient(to right, #fff 0, #00f 50%, #000 100%);background-repeat:repeat-x} +.pick-a-color-markup .spectrum-purple{background-image:-webkit-gradient(linear, left top, right top, color-stop(0, #ff80ff), color-stop(.5, #80007f), color-stop(1, #000));background-image:-moz-linear-gradient(left center, #ff80ff 0, #80007f 50%, #000 100%);background-image:-webkit-linear-gradient(left, #ff80ff 0, #80007f 50%, #000 100%);background-image:-o-linear-gradient(left, #ff80ff 0, #80007f 50%, #000 100%);background-image:linear-gradient(to right, #ff80ff 0, #80007f 50%, #000 100%);background-repeat:repeat-x} +.pick-a-color-markup .spectrum-black{background-image:-webkit-gradient(linear, 0 top, 100% top, from(#000), to(#808080));background-image:-webkit-linear-gradient(left, color-stop(#000 0), color-stop(#808080 100%));background-image:-moz-linear-gradient(left, #000 0, #808080 100%);background-image:linear-gradient(to right, #000 0, #808080 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff000000', endColorstr='#ff808080', GradientType=1)}.pick-a-color-markup .spectrum-black .highlight-band{left:0px;border:1px solid #808080} +.pick-a-color-markup .ie-spectrum{height:20px;width:100px;display:inline-block;top:-1}.pick-a-color-markup .ie-spectrum.hue{width:50.5px}@media screen and (max-width:991px){.pick-a-color-markup .ie-spectrum.hue{width:45.5px}} +@media screen and (max-width:991px){.pick-a-color-markup .ie-spectrum{width:80px;height:35px}} +.pick-a-color-markup .red-spectrum-0,.pick-a-color-markup .lightness-spectrum-0{background-image:-webkit-gradient(linear, 0 top, 100% top, from(#fff), to(#f00));background-image:-webkit-linear-gradient(left, color-stop(#fff 0), color-stop(#f00 100%));background-image:-moz-linear-gradient(left, #fff 0, #f00 100%);background-image:linear-gradient(to right, #fff 0, #f00 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffff0000', GradientType=1);border-bottom-left-radius:4px;border-top-left-radius:4px} +.pick-a-color-markup .red-spectrum-1,.pick-a-color-markup .lightness-spectrum-1{background-image:-webkit-gradient(linear, 0 top, 100% top, from(#f00), to(#000));background-image:-webkit-linear-gradient(left, color-stop(#f00 0), color-stop(#000 100%));background-image:-moz-linear-gradient(left, #f00 0, #000 100%);background-image:linear-gradient(to right, #f00 0, #000 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff0000', endColorstr='#ff000000', GradientType=1);border-bottom-right-radius:4px;border-top-right-radius:4px} +.pick-a-color-markup .lightness-spectrum-0,.pick-a-color-markup .lightness-spectrum-1{width:150px}@media screen and (max-width:991px){.pick-a-color-markup .lightness-spectrum-0,.pick-a-color-markup .lightness-spectrum-1{width:135px}} +.pick-a-color-markup .orange-spectrum-0{background-image:-webkit-gradient(linear, 0 top, 100% top, from(#fff), to(#f60));background-image:-webkit-linear-gradient(left, color-stop(#fff 0), color-stop(#f60 100%));background-image:-moz-linear-gradient(left, #fff 0, #f60 100%);background-image:linear-gradient(to right, #fff 0, #f60 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffff6600', GradientType=1);border-bottom-left-radius:4px;border-top-left-radius:4px} +.pick-a-color-markup .orange-spectrum-1{background-image:-webkit-gradient(linear, 0 top, 100% top, from(#f60), to(#000));background-image:-webkit-linear-gradient(left, color-stop(#f60 0), color-stop(#000 100%));background-image:-moz-linear-gradient(left, #f60 0, #000 100%);background-image:linear-gradient(to right, #f60 0, #000 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff6600', endColorstr='#ff000000', GradientType=1);border-bottom-right-radius:4px;border-top-right-radius:4px} +.pick-a-color-markup .yellow-spectrum-0{background-image:-webkit-gradient(linear, 0 top, 100% top, from(#fff), to(#ff0));background-image:-webkit-linear-gradient(left, color-stop(#fff 0), color-stop(#ff0 100%));background-image:-moz-linear-gradient(left, #fff 0, #ff0 100%);background-image:linear-gradient(to right, #fff 0, #ff0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffffff00', GradientType=1);border-bottom-left-radius:4px;border-top-left-radius:4px} +.pick-a-color-markup .yellow-spectrum-1{background-image:-webkit-gradient(linear, 0 top, 100% top, from(#ff0), to(#000));background-image:-webkit-linear-gradient(left, color-stop(#ff0 0), color-stop(#000 100%));background-image:-moz-linear-gradient(left, #ff0 0, #000 100%);background-image:linear-gradient(to right, #ff0 0, #000 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff00', endColorstr='#ff000000', GradientType=1);border-bottom-right-radius:4px;border-top-right-radius:4px} +.pick-a-color-markup .green-spectrum-0{background-image:-webkit-gradient(linear, 0 top, 100% top, from(#80ff80), to(#008000));background-image:-webkit-linear-gradient(left, color-stop(#80ff80 0), color-stop(#008000 100%));background-image:-moz-linear-gradient(left, #80ff80 0, #008000 100%);background-image:linear-gradient(to right, #80ff80 0, #008000 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff80ff80', endColorstr='#ff008000', GradientType=1);border-bottom-left-radius:4px;border-top-left-radius:4px} +.pick-a-color-markup .green-spectrum-1{background-image:-webkit-gradient(linear, 0 top, 100% top, from(#008000), to(#000));background-image:-webkit-linear-gradient(left, color-stop(#008000 0), color-stop(#000 100%));background-image:-moz-linear-gradient(left, #008000 0, #000 100%);background-image:linear-gradient(to right, #008000 0, #000 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff008000', endColorstr='#ff000000', GradientType=1);border-bottom-right-radius:4px;border-top-right-radius:4px} +.pick-a-color-markup .blue-spectrum-0{background-image:-webkit-gradient(linear, 0 top, 100% top, from(#fff), to(#00f));background-image:-webkit-linear-gradient(left, color-stop(#fff 0), color-stop(#00f 100%));background-image:-moz-linear-gradient(left, #fff 0, #00f 100%);background-image:linear-gradient(to right, #fff 0, #00f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ff0000ff', GradientType=1);border-bottom-left-radius:4px;border-top-left-radius:4px} +.pick-a-color-markup .blue-spectrum-1{background-image:-webkit-gradient(linear, 0 top, 100% top, from(#00f), to(#000));background-image:-webkit-linear-gradient(left, color-stop(#00f 0), color-stop(#000 100%));background-image:-moz-linear-gradient(left, #00f 0, #000 100%);background-image:linear-gradient(to right, #00f 0, #000 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0000ff', endColorstr='#ff000000', GradientType=1);border-bottom-right-radius:4px;border-top-right-radius:4px} +.pick-a-color-markup .purple-spectrum-0{background-image:-webkit-gradient(linear, 0 top, 100% top, from(#ff80ff), to(#80007f));background-image:-webkit-linear-gradient(left, color-stop(#ff80ff 0), color-stop(#80007f 100%));background-image:-moz-linear-gradient(left, #ff80ff 0, #80007f 100%);background-image:linear-gradient(to right, #ff80ff 0, #80007f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff80ff', endColorstr='#ff80007f', GradientType=1);border-bottom-left-radius:4px;border-top-left-radius:4px} +.pick-a-color-markup .purple-spectrum-1{background-image:-webkit-gradient(linear, 0 top, 100% top, from(#80007f), to(#000));background-image:-webkit-linear-gradient(left, color-stop(#80007f 0), color-stop(#000 100%));background-image:-moz-linear-gradient(left, #80007f 0, #000 100%);background-image:linear-gradient(to right, #80007f 0, #000 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff80007f', endColorstr='#ff000000', GradientType=1);border-bottom-right-radius:4px;border-top-right-radius:4px} +.pick-a-color-markup .saturation-spectrum-0{background-image:-webkit-gradient(linear, 0 top, 100% top, from(#808080), to(#bf4040));background-image:-webkit-linear-gradient(left, color-stop(#808080 0), color-stop(#bf4040 100%));background-image:-moz-linear-gradient(left, #808080 0, #bf4040 100%);background-image:linear-gradient(to right, #808080 0, #bf4040 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff808080', endColorstr='#ffbf4040', GradientType=1);border-bottom-left-radius:4px;border-top-left-radius:4px;width:150px}@media screen and (max-width:991px){.pick-a-color-markup .saturation-spectrum-0{width:135px}} +.pick-a-color-markup .saturation-spectrum-1{background-image:-webkit-gradient(linear, 0 top, 100% top, from(#bf4040), to(#f00));background-image:-webkit-linear-gradient(left, color-stop(#bf4040 0), color-stop(#f00 100%));background-image:-moz-linear-gradient(left, #bf4040 0, #f00 100%);background-image:linear-gradient(to right, #bf4040 0, #f00 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffbf4040', endColorstr='#ffff0000', GradientType=1);border-bottom-right-radius:4px;border-top-right-radius:4px;width:150px}@media screen and (max-width:991px){.pick-a-color-markup .saturation-spectrum-1{width:135px}} +.pick-a-color-markup .hue-spectrum-0{background-image:-webkit-gradient(linear, 0 top, 100% top, from(#f00), to(#ff0));background-image:-webkit-linear-gradient(left, color-stop(#f00 0), color-stop(#ff0 100%));background-image:-moz-linear-gradient(left, #f00 0, #ff0 100%);background-image:linear-gradient(to right, #f00 0, #ff0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff0000', endColorstr='#ffffff00', GradientType=1)} +.pick-a-color-markup .hue-spectrum-1{background-image:-webkit-gradient(linear, 0 top, 100% top, from(#ff0), to(#0f0));background-image:-webkit-linear-gradient(left, color-stop(#ff0 0), color-stop(#0f0 100%));background-image:-moz-linear-gradient(left, #ff0 0, #0f0 100%);background-image:linear-gradient(to right, #ff0 0, #0f0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff00', endColorstr='#ff00ff00', GradientType=1)} +.pick-a-color-markup .hue-spectrum-2{background-image:-webkit-gradient(linear, 0 top, 100% top, from(#0f0), to(#0ff));background-image:-webkit-linear-gradient(left, color-stop(#0f0 0), color-stop(#0ff 100%));background-image:-moz-linear-gradient(left, #0f0 0, #0ff 100%);background-image:linear-gradient(to right, #0f0 0, #0ff 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff00ff00', endColorstr='#ff00ffff', GradientType=1);left:-1px;position:relative} +.pick-a-color-markup .hue-spectrum-3{background-image:-webkit-gradient(linear, 0 top, 100% top, from(#0ff), to(#00f));background-image:-webkit-linear-gradient(left, color-stop(#0ff 0), color-stop(#00f 100%));background-image:-moz-linear-gradient(left, #0ff 0, #00f 100%);background-image:linear-gradient(to right, #0ff 0, #00f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff00ffff', endColorstr='#ff0000ff', GradientType=1);left:-1px;position:relative} +.pick-a-color-markup .hue-spectrum-4{background-image:-webkit-gradient(linear, 0 top, 100% top, from(#00f), to(#f0f));background-image:-webkit-linear-gradient(left, color-stop(#00f 0), color-stop(#f0f 100%));background-image:-moz-linear-gradient(left, #00f 0, #f0f 100%);background-image:linear-gradient(to right, #00f 0, #f0f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0000ff', endColorstr='#ffff00ff', GradientType=1);left:-1px;position:relative} +.pick-a-color-markup .hue-spectrum-5{background-image:-webkit-gradient(linear, 0 top, 100% top, from(#f0f), to(#f00));background-image:-webkit-linear-gradient(left, color-stop(#f0f 0), color-stop(#f00 100%));background-image:-moz-linear-gradient(left, #f0f 0, #f00 100%);background-image:linear-gradient(to right, #f0f 0, #f00 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff00ff', endColorstr='#ffff0000', GradientType=1);left:-2px;position:relative} +.pick-a-color-markup .highlight-band{border:1px solid #222;border-radius:2px;-webkit-box-shadow:1px 1px 1px #333;box-shadow:1px 1px 1px #333;height:19px;width:11px;display:inline-block;cursor:pointer;cursor:-webkit-grab;cursor:-moz-grab;position:absolute;top:-1px;left:94.5px;text-align:center}@media screen and (max-width:991px){.pick-a-color-markup .highlight-band{width:21px;left:69.5px;height:34px}} +.pick-a-color-markup .highlight-band-stripe{min-height:80%;min-width:1px;background-color:#000;opacity:0.40;margin:2px 1px;display:inline-block;-webkit-box-shadow:1px 0 2px 0 #fff;box-shadow:1px 0 2px 0 #fff}@media screen and (max-width:991px){.pick-a-color-markup .highlight-band-stripe{margin:4px 2px}} +.pick-a-color-markup .color-menu-tabs{padding:5px 3px 3px 10px;font-size:12px;color:#333;border-bottom:1px solid #ccc;margin-bottom:5px}.pick-a-color-markup .color-menu-tabs .tab{padding:4px 5px;margin:5px;border-left:1px solid #fff;border-right:1px solid #fff;cursor:pointer;background-color:#fff}.pick-a-color-markup .color-menu-tabs .tab:hover{padding-bottom:6px;border-top:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc;border-top-right-radius:4px;border-top-left-radius:4px} +.pick-a-color-markup .color-menu-tabs a{color:#333;text-decoration:none} +.pick-a-color-markup .color-menu-tabs .tab-active{border-bottom:3px solid #fff;padding-bottom:5px;border-top:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc;border-top-right-radius:4px;border-top-left-radius:4px} +.pick-a-color-markup .active-content{display:block} +.pick-a-color-markup .inactive-content{display:none} +.pick-a-color-markup .savedColors-content{padding:5px 15px;white-space:normal}.pick-a-color-markup .savedColors-content li.color-item>a{margin-left:7px;padding-left:8px;border-radius:4px} +.pick-a-color-markup .saved-color-col{position:relative;left:-15px;float:left;width:149px}@media screen and (max-width:991px){.pick-a-color-markup .saved-color-col{width:130px}} +.pick-a-color-markup .advanced-content ul{margin-top:10px} +.pick-a-color-markup .advanced-content li{padding:5px 15px 3px 15px;cursor:default;min-height:25px;height:50px;position:relative}@media screen and (max-width:991px){.pick-a-color-markup .advanced-content li{min-height:70px}} +.pick-a-color-markup .advanced-content .color-preview{height:50px;width:300px;float:left;margin:0px 0px 10px 0px;background-color:#f00;text-align:center}.pick-a-color-markup .advanced-content .color-preview .color-select.btn.advanced{margin-top:15px;display:none}@media screen and (max-width:991px){.pick-a-color-markup .advanced-content .color-preview .color-select.btn.advanced{display:inline;margin-top:7px}} +.pick-a-color-markup .advanced-content .color-preview:hover .color-select.btn.advanced{display:inline} +@media screen and (max-width:991px){.pick-a-color-markup .advanced-content .color-preview{width:270px;margin-left:-10px}} +.pick-a-color-markup .advanced-content .spectrum-hue{background-image:-webkit-gradient(linear, left top, right top, color-stop(0, #f00), color-stop(17%, #ff0), color-stop(34%, #0f0), color-stop(51%, #0ff), color-stop(68%, #00f), color-stop(85%, #f0f), color-stop(100%, #f00));background-image:-moz-linear-gradient(left center, #f00 0, #ff0 17%, #0f0 24%, #0ff 51%, #00f 68%, #f0f 85%, #f00 100%);background-image:-webkit-linear-gradient(left, #f00 0, #ff0 17%, #0f0 24%, #0ff 51%, #00f 68%, #f0f 85%, #f00 100%);background-image:-o-linear-gradient(left, #f00 0, #ff0 17%, #0f0 24%, #0ff 51%, #00f 68%, #f0f 85%, #f00 100%);background-image:linear-gradient(to right, #f00 0, #ff0 17%, #0f0 24%, #0ff 51%, #00f 68%, #f0f 85%, #f00 100%);background-repeat:repeat-x}.pick-a-color-markup .advanced-content .spectrum-hue .highlight-band{left:0px} +.pick-a-color-markup .advanced-content .spectrum-lightness{background-image:-webkit-gradient(linear, left top, right top, color-stop(0, #fff), color-stop(.5, #f00), color-stop(1, #000));background-image:-moz-linear-gradient(left center, #fff 0, #f00 50%, #000 100%);background-image:-webkit-linear-gradient(left, #fff 0, #f00 50%, #000 100%);background-image:-o-linear-gradient(left, #fff 0, #f00 50%, #000 100%);background-image:linear-gradient(to right, #fff 0, #f00 50%, #000 100%);background-repeat:repeat-x} +.pick-a-color-markup .advanced-content .spectrum-saturation{background-image:-webkit-gradient(linear, left top, right top, color-stop(0, #808080), color-stop(.5, #f00), color-stop(1, #f00));background-image:-moz-linear-gradient(left center, #808080 0, #f00 50%, #f00 100%);background-image:-webkit-linear-gradient(left, #808080 0, #f00 50%, #f00 100%);background-image:-o-linear-gradient(left, #808080 0, #f00 50%, #f00 100%);background-image:linear-gradient(to right, #808080 0, #f00 50%, #f00 100%);background-repeat:repeat-x}.pick-a-color-markup .advanced-content .spectrum-saturation .highlight-band{left:287px}@media screen and (max-width:991px){.pick-a-color-markup .advanced-content .spectrum-saturation .highlight-band{left:247px}} +.pick-a-color-markup .advanced-content .spectrum-lightness .highlight-band{left:143.5px}@media screen and (max-width:991px){.pick-a-color-markup .advanced-content .spectrum-lightness .highlight-band{left:123.5px}} +.pick-a-color-markup .advanced-content .lightness-text,.pick-a-color-markup .advanced-content .hue-text,.pick-a-color-markup .advanced-content .saturation-text,.pick-a-color-markup .advanced-content .preview-text{vertical-align:middle;text-align:center;display:block} +.pick-a-color-markup .advanced-content .color-box{left:15px;top:25px;width:300px}@media screen and (max-width:991px){.pick-a-color-markup .advanced-content .color-box{width:270px;left:10px}} +.pick-a-color-markup .advanced-content .preview-item{height:80px} +@-moz-document url-prefix(){@media screen and (max-width:991px){div.pick-a-color-markup .color-menu{left:0px}}} diff --git a/deprecated/circle_generator.html b/deprecated/circle_generator.html deleted file mode 100644 index 095a15a..0000000 --- a/deprecated/circle_generator.html +++ /dev/null @@ -1,232 +0,0 @@ - - - - - Circle Generator - - - - - - - - - - - - - - - - - - -
- - - -
- - - - - - diff --git a/deprecated/unknown_helper.php b/deprecated/unknown_helper.php deleted file mode 100644 index 69e708c..0000000 --- a/deprecated/unknown_helper.php +++ /dev/null @@ -1,94 +0,0 @@ -connect_error != '') { - exit("Failed to connect to MySQL server!"); -} -$db->set_charset('utf8'); - -$sql = "SELECT id, lat, lon FROM gym WHERE name IS null"; -$result = $db->query($sql); -while ($point = $result->fetch_array()) { - $gyms[] = array( - 'id' => $point['id'], - 'lat' => $point['lat'], - 'lon' => $point['lon'] - ); -} -$gymjson = json_encode($gyms); - -$sql = "SELECT id, lat, lon FROM pokestop WHERE name IS null"; -$result = $db->query($sql); -while ($point = $result->fetch_array()) { - $stops[] = array( - 'id' => $point['id'], - 'lat' => $point['lat'], - 'lon' => $point['lon'] - ); -} -$stopjson = json_encode($stops); -?> - - - Unknown Finder - - - - - - - - - - - - -
- - - - diff --git a/docker-compose.example.yml b/docker-compose.example.yml new file mode 100644 index 0000000..50d621a --- /dev/null +++ b/docker-compose.example.yml @@ -0,0 +1,38 @@ +version: '3.1' +services: + rdm_tools: + image: ghcr.io/picklerickve/realdevicemap-tools:master + # You can remove this option if you are not using Traefik as reverse proxy + labels: + - traefik.enable=true + # Change yourdomain to your own domain + - traefik.http.routers.rdmtools.rule=Host(`rdm-tools.yourdomain.com`) + # Change your-network to your specified network below + - traefik.http.routers.rdmtools.entrypoints=your-network + container_name: rdm_tools + depends_on: + - rdm_db + volumes: + # Uncomment this if you want to use a password on your RDM Tools frontend + # - ./RealDeviceMap-tools/.htpasswd:/var/www/html/config/.htpasswd + # - ./RealDeviceMap-tools/.htaccess.example:/var/www/html/.htaccess + - /etc/localtime:/etc/localtime:ro + environment: + DB_HOST: rdm-db + DB_NAME: rdmdb + DB_PORT: 3306 + DB_USER: root + DB_PSWD: password + # MDB_ACTIVE: false + # MDB_HOST: 127.0.0.1 + # MDB_NAME: manualdb + # MDB_PORT: 3306 + # MDB_USER: mdbuser + # MDB_PSWD: password + # OWN_TS: https://IP:PORT/tile/STYLE/{z}/{x}/{y}/1/png + ports: + #Change according to your own port-mapping + - 9006:80 + networks: + # Change to your own network + - your-network diff --git a/index.php b/index.php new file mode 100644 index 0000000..61ff35c --- /dev/null +++ b/index.php @@ -0,0 +1,5395 @@ + + + + RDM-Tools + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + PDO::ERRMODE_EXCEPTION, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + PDO::ATTR_EMULATE_PREPARES => true, + ]; + return new PDO($dsn, $DB_USER, $DB_PSWD, $options); +} +function initMDB($MDB_HOST, $MDB_USER, $MDB_PSWD, $MDB_NAME, $MDB_PORT) { + $dsn = "mysql:host=$MDB_HOST;dbname=$MDB_NAME;port=$MDB_PORT;charset=utf8mb4"; + $options = [ + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + PDO::ATTR_EMULATE_PREPARES => true, + ]; + return new PDO($dsn, $MDB_USER, $MDB_PSWD, $options); +} +function map_helper_init() { + global $db; + $db = initDB(DB_HOST, DB_USER, DB_PSWD, DB_NAME, DB_PORT); + if (MDB_ACTIVE === true) { + global $mdb; + $mdb = initMDB(MDB_HOST, MDB_USER, MDB_PSWD, MDB_NAME, MDB_PORT); + } + $args = json_decode($_POST['data']); + if (isset($args->get_spawndata)) { + if ($args->get_spawndata === true) { getSpawnData($args); } + } + if (isset($args->get_data)) { + if ($args->get_data === true) { getData($args); } + } + if (isset($args->get_optimization)) { + if ($args->get_optimization === true) { getOptimization($args); } + } + if (isset($args->get_instance_data)) { + if ($args->get_instance_data === true) { getInstanceData($args); } + } + if (isset($args->get_instance_names)) { + if ($args->get_instance_names === true) { getInstanceNames(); } + } + if (isset($args->set_nest_data)) { + if ($args->set_nest_data === true) { setNestData($args); } + } + if (isset($args->get_nest_data)) { + if ($args->get_nest_data === true) { getNests(); } + } +} +function getInstanceData($args) { + global $db; + $sql_instancedata = "SELECT data, type FROM instance WHERE name = :name"; + if (isset($args->instance_name)) { + $stmt = $db->prepare($sql_instancedata); + $stmt->bindValue(':name', $args->instance_name, PDO::PARAM_STR); + $stmt->execute(); + $result = $stmt->fetch(); + $result['data'] = json_decode($result['data']); + echo json_encode($result); + } else { + echo json_encode(array('status'=>'Error: no instance name?')); + } +} +function getInstanceNames() { + global $db; + $sql_instances = "SELECT name, type FROM instance"; + $result = $db->query($sql_instances)->fetchAll(PDO::FETCH_ASSOC); + echo json_encode($result); +} +function getSpawnData($args) { + global $db; + $binds = array(); + if (isset($args->spawns) || isset($args->stops)) { + if (isset($args->spawns) && count($args->spawns) > 0) { + $spawns_in = str_repeat('?,', count($args->spawns) - 1) . '?'; + $binds = array_merge($binds, $args->spawns); + } + if (isset($args->stops) && count($args->stops) > 0) { + $stops_in = str_repeat('?,', count($args->stops) - 1) . '?'; + $binds = array_merge($binds, $args->stops); + } + if ($stops_in && $spawns_in) { + $points_string = "(pokestop_id IN (" . $stops_in . ") OR spawn_id IN (" . $spawns_in . "))"; + } else if ($stops_in) { + $points_string = "pokestop_id IN (" . $stops_in . ")"; + } else if ($spawns_in) { + $points_string = "spawn_id IN (" . $spawns_in . ")"; + } else { + echo json_encode(array('spawns' => null, 'status'=>'Error: no points!')); + return; + } + if (is_numeric($args->nest_migration_timestamp) && (int)$args->nest_migration_timestamp == $args->nest_migration_timestamp) { + $ts = $args->nest_migration_timestamp; + } else { + $ts = 0; + } + $binds[] = $ts; + if (is_numeric($args->spawn_report_limit) && (int)$args->spawn_report_limit == $args->spawn_report_limit && (int)$args->spawn_report_limit != 0) { + $limit = " LIMIT " . $args->spawn_report_limit; + } else { + $limit = ''; + } + $sql_spawn = "SELECT pokemon_id, COUNT(pokemon_id) as count FROM pokemon WHERE " . $points_string . " AND first_seen_timestamp >= ? GROUP BY pokemon_id ORDER BY count DESC" . $limit; + $stmt = $db->prepare($sql_spawn); + try { + $stmt->execute($binds); + } catch (PDOException $e) { + //let_dump($e); + let_dump(array('sql_spawnpoint' => $sql_spawn)); + let_dump(array('binds_count' => count($binds), 'stop_count' => count($args->stops), 'spawn_count' => count($args->spawns))); + let_dump($args); + } + $result = $stmt->fetchAll(PDO::FETCH_ASSOC); + } + echo json_encode(array('spawns' => $result)); +} +function setNestData($args) { + global $mdb; + $binds = array(); + $sql_nests = "INSERT INTO nests (pokemon_id, updated, name, pokemon_count, pokemon_avg, nest_id, lat, lon, polygon_path) VALUES (?,?,?,?,?,?,?,?,?) on DUPLICATE KEY UPDATE pokemon_id = ?, updated = ?, name = ?, pokemon_count = ?, pokemon_avg = ?"; + $stmt = $mdb->prepare($sql_nests); + $result = $stmt->execute(array_merge($binds, [$args->nest_pokemon, $args->updated, $args->name, $args->pokemon_count, $args->avg_spawns, $args->nest_id, $args->lat, $args->lon, $args->path, $args->nest_pokemon, $args->updated, $args->name, $args->pokemon_count, $args->avg_spawns])); + echo $result; +} +function getNests() { + global $mdb; + $sql_import_nests = "SELECT name, nest_id, lat, lon, polygon_path FROM nests"; + $stmt = $mdb->prepare($sql_import_nests); + $stmt->execute(); + $import_nests = $stmt->fetchAll(PDO::FETCH_ASSOC); + echo json_encode(array('nests' => $import_nests)); +} +function getData($args) { + global $db; + $binds = array(); + + if ($args->show_gyms === true) { + $sql_gym = "SELECT id, lat, lon as lng, ex_raid_eligible as ex, name, updated FROM gym WHERE lat > ? AND lon > ? AND lat < ? AND lon < ?"; + $stmt = $db->prepare($sql_gym); + $stmt->execute(array_merge($binds, [$args->min_lat, $args->min_lng, $args->max_lat, $args->max_lng])); + $gyms = $stmt->fetchAll(PDO::FETCH_ASSOC); + } + + if ($args->show_pokestops === true) { + $sql_pokestop = "SELECT id, lat, lon as lng, name, updated, deleted FROM pokestop WHERE lat > ? AND lon > ? AND lat < ? AND lon < ?"; + $stmt = $db->prepare($sql_pokestop); + $stmt->execute(array_merge($binds, [$args->min_lat, $args->min_lng, $args->max_lat, $args->max_lng])); + $stops = $stmt->fetchAll(PDO::FETCH_ASSOC); + } + + if ($args->show_quests === true) { + $sql_quest = "SELECT id, lat, lon as lng, name, deleted FROM pokestop WHERE quest_type is NULL AND lat > ? AND lon > ? AND lat < ? AND lon < ?"; + $stmt = $db->prepare($sql_quest); + $stmt->execute(array_merge($binds, [$args->min_lat, $args->min_lng, $args->max_lat, $args->max_lng])); + $quests = $stmt->fetchAll(PDO::FETCH_ASSOC); + } + + if ($args->show_spawnpoints === true) { + $sql_spawnpoint = "SELECT id, despawn_sec, lat, lon as lng, last_seen as updated FROM spawnpoint WHERE lat > ? AND lon > ? AND lat < ? AND lon < ?"; + $stmt = $db->prepare($sql_spawnpoint); + $stmt->execute([$args->min_lat, $args->min_lng, $args->max_lat, $args->max_lng]); + $spawns = $stmt->fetchAll(PDO::FETCH_ASSOC); + } + + echo json_encode(array('gyms' => $gyms, 'pokestops' => $stops, 'quests' => $quests, 'spawnpoints' => $spawns )); +} +function getOptimization($args) { + if (isset($args->points)) { + $points = $args->points; + } else { + echo json_encode(array('status'=>'Error: no points')); + return; + } + $best_attempt = array(); + for($x=0; $x<$args->optimization_attempts;$x++) { + shuffle($points); + $working_gyms = $points; + $attempt = array(); + while(count($working_gyms) > 0) { + $gym1 = array_pop($working_gyms); + foreach ($working_gyms as $i => $gym2) { + $dist = haversine($gym1, $gym2); + if ($dist < $args->circle_size) { + unset($working_gyms[$i]); + } + } + $attempt[] = $gym1; + } + if(count($best_attempt) == 0 || count($attempt) < count($best_attempt)) { + $best_attempt = $attempt; + } + } + if ($args->do_tsp) { + $working_gyms = $best_attempt; + $index = rand(0,count($working_gyms)-1); + $gym1 = $working_gyms[$index]; + while(count($working_gyms) > 0) { + unset($working_gyms[$index]); + $final_attempt[] = $gym1; + unset($working_gyms[$index]); + foreach ($working_gyms as $i => $gym2) { + $dist = haversine($gym1, $gym2); + while ($distances[$dist]) { + $dist++; + } + $distances[$dist] = $gym2; + $index = $i; + } + ksort($distances); + $closest_gym = array_shift($distances); + $gym1 = $closest_gym; + } + $best_attempt = $final_attempt; + } + echo json_encode(array('bestAttempt' => $best_attempt)); +} +function haversine($gym1, $gym2) { + $r = 6371000; + $latFrom = ($gym1->lat * M_PI / 180); + $lngFrom = ($gym1->lng * M_PI / 180); + $latTo = ($gym2->lat * M_PI / 180); + $lngTo = ($gym2->lng * M_PI / 180); + $latDelta = $latTo - $latFrom; + $lngDelta = $lngTo - $lngFrom; + $a = 2 * asin(sqrt(pow(sin($latDelta / 2), 2) + + cos($latFrom) * cos($latTo) * pow(sin($lngDelta / 2), 2))); + return $a * $r; +} +?> diff --git a/other/de.js b/other/de.js new file mode 100644 index 0000000..e8f06e7 --- /dev/null +++ b/other/de.js @@ -0,0 +1,179 @@ +//de +let deSubs = { + "nest": "Nest", + "polygon": "Polygon", + "getSpawnReport": "Spawn-Bericht", + "removeMap": "Entfernen", + "exportPolygon": "Polygon exportieren", + "exportVP": "sichtbare Punkte exportieren", + "countVP": "sichtbare Punkte zählen", + "copyClipboard": "Kopieren", + "poiViewer": "Wayfarer Modus", + "routeGenerator": "Planungsmodus", + "hideGyms": "Arenen aus", + "showGyms": "Arenen an", + "hidePokestops": "Pokestops aus", + "showPokestops": "Pokestops an", + "hidePokestopRange": "Pokestop Umkreis aus", + "showPokestopRange": "Pokestop Umkreis an", + "hideSpawnpoints": "Spawnpoints aus", + "showSpawnpoints": "Spawnpoints an", + "showAllPOIS": "Alle Punkte", + "showUnknownPOIS": "Nur unbekannte Punkte", + "hideViewingCells": "S2 Zellen aus", + "showViewingCells": "S2 Zellen an", + "enableManualCircle": "Kreise zeichnen an", + "disableManualCircle": "Kreise zeichnen aus", + "importOSM": "Nester von OSM importieren", + "importPolygon": "Polygon importieren", + "importInstance": "Instanz importieren", + "importAdBounds": "Verwaltungsgrenzen importieren", + "importSubmissions": "POIs importieren", + "poiData": "Daten der POI im Format: lat, lng, Titel", + "csvOpener": "oder Datei im CSV-Format auswählen:", + "submissionRangeCheck": "20m-Radius für Wayfarer Vorschläge anzeigen", + "clearRoute": "Route löschen", + "clearShapes": "Alle Formen löschen", + "clearSubs": "POIs löschen", + "generateRoute": "Kreise generieren (Bootstrap)", + "generateOptimizedRoute": "Optimierte Kreise generieren", + "getOutput": "Ausgabe generieren", + "openSettings": "Einstellungen öffnen", + "delete": "Löschen", + "noData": "Keine Daten verfügbar.", + "exEligible": " (ex-fähig)", + "despawnTime": " Despawn-Zeit: ", + "unknownDespawnTime": " unbekannte Despawn-Zeit ", + "count": "Anzahl: ", + "countTotal": "Gesamtzahl: ", + "countGyms": "Anzahl Arenen: ", + "countStops": "Anzahl Pokestops: ", + "countSpawnpoints": "Anzahl Spawnpoints: ", + "spawnReport": "Spawn-Bericht - ", + "unnamed": "unbenannt", + "at": "bei", + "skipped": " übersprungen, keine Daten", + "nestReport": "Nest-Bericht für alle sichtbaren Nester", + "settings": "Einstellungen", + "routeOptAtt": "Routen-Optimierungsversuche:", + "tries": "Versuche", + "s2cells0": "Rot, Level:", + "s2cells1": "Blau, Level 14", + "s2cells2": "Grün, Level 17", + "s2CountPOI": "POIs zählen", + "circleRadius": "Kreis Radius:", + "other": "anderer:", + "lastNestMigration": "Letzter Nestwechsel:", + "spawnReportLimit": "Spawn-Bericht Grenze:", + "spawnReportLimitExp": "Pokemon (0 für unbegrenzt)", + "selectLanguage": "Wähle die Sprache aus:", + "chooseTileset": "Wähle den Kartenstil:", + "ownTileset": "Eigenes Tileset", + "close": "Schließen", + "output": "Ausgabe", + "generatedRoute": "Generierte Route:", + "getAllNests": "Alle Nest-Berichte", + "countPoints": "Punkte in Kreisen zählen", + "optimize": "Optimiere!", + "optimizeGyms": "Optimiere für Arenen", + "optimizePokestops": "Optimiere für Pokestops", + "optimizeSpawnpoints": "Optimiere für Spawnpoints", + "optimizeUnknownSpawnpoints": "Optimiere für Spawnpoints ohne TTH", + "on": "An", + "off": "Aus", + "optimizePiP": "Optimiere Punkte in Polygonen", + "optimizePiNP": "Optimiere Punkte in Nestpolygonen", + "optimizePiC": "Optimiere Punkte in Kreisen", + "getOptimization": "Generiere Optimierung", + "copied": "Kopiert!", + "selectInstance": "Instanz auswählen:", + "instanceColor": "Instanz-Farbe:", + "polygonColor": "Polygon-Farbe:", + "polygonDataType": "Polygon Datentyp:", + "coordinateList": "Koordinatenliste (latitude,longitude in neue Zeile)", + "geoJson": "GeoJSON", + "poracle": "PoracleJS-Format", + "polygonData": "Polygon-Daten:", + "import": "Importieren", + "importNest": "Als Nest importieren", + "exportPolygonPoints": "Polygon-Punkte exportieren", + "gyms": "Arenen:", + "pokestops": "Pokestops:", + "spawnpoints": "Spawnpoints:", + "pokemon": "Pokémon", + "getOwnLocation": "Zu meiner Position!", + "coordTypeUnsorted": "unsortiert", + "coordTypeSorted": "autosortiert", + "countCircles": "Anzahl der Kreise:", + "adBoundsHeader": "Auswahl der Verwaltungsebene", + "adBounds1": "Kreise", + "adBounds2": "Städte/Gemeinden", + "adBounds3": "Ortsteile", + "getAdBounds": "Erzeuge Polygone", + "hideOldSpawnpoints": "Alte Spawnpoints einblenden", + "showOldSpawnpoints": "Alte Spawnpoints ausblenden", + "oldSpawnpointsTitle": "Keine Spawnpoints älter als:", + "instanceMode": "Kreise als passiv importieren: ", + "enableNewPOI": "Neuen POI setzen an", + "disableNewPOI": "Neuen POI setzen aus", + "exportPOIs": "Exportieren", + "exportPOILabel": "Dein POI hat die folgenden Koordinaten:", + "outputAvgPt": "durchschnittliche Punkte/Kreis: ", + "exportListCount": "Polygone zum Exportieren: ", + "chooseName": "Bitte wähle einen Namen!", + "addToExport": "Zum Export hinzufügen", + "removeFromExport": "Aus dem Export entfernen", + "name": "Name:", + "saveFile": "Als Datei speichern", + "ownRadius": "eigener Radius", + "drawnCircles": "eigene Kreise", + "selectInstances": "Instanzen auswählen", + "importCirclesIns": "importierte Kreise", + "importCirclesHl": "Eigene Koordinaten: (latitude,longitude in neue Zeile)", + "importCirclesBtn": "Kreise importieren", + "showRoute": "Route anzeigen", + "hideRoute": "Route ausblenden", + "newRoute": "Neue Route", + "hideQuests": "Stops ohne Quest ausblenden", + "showQuests": "Stops ohne Quest einblenden", + "questCheck": "Zu prüfende Instanzen:", + "questCheckButton": "Anzeigen!", + "showBorders": "Grenzen der Instanzen anzeigen", + "generateWithS2Cells": "Bootstrap mit S2 Zellen", + "lastUpdate": "Letzte Aktualisierung (UTC): ", + "stop_deleted": "als gelöscht markiert", + "coords": "Koordinaten", + "drawPolygon": "Polygon zeichnen", + "drawCircle": "Freien Kreis zeichnen", + "searchErr": "Ort nicht gefunden", + "searchCancel": "Abbrechen", + "searchPlaceholder": "Suchen...", + "editEdit": "Layer bearbeiten", + "editEditDisabled": "Keine Layer vorhanden", + "v2": "v2.0 (1100m)", + "circleID": "Kreis ID:", + "manualdbHint": "nur mit manualdb nutzbar:", + "importFromDB": "Nester aus DB importieren", + "writeAllToDB": "Nester in DB aktualisieren", + "nestOptions": "Nestoptionen", + "writeSuccess": "Nest(er) erfolgreich eingetragen/aktualisiert!", + "writeToDB": "In DB eintragen", + "instanceLength": "Instanzlänge:", + "area": "Fläche", + "osmOptions": "OSM Optionen", + "osmPark": "Park", + "osmMeadow": "Wiese", + "osmRecGround": "Erholungsgebiet", + "osmGrass": "Grasland", + "osmPitch": "Spielfeld", + "osmGolf": "Golfkurs", + "osmPlayground": "Spielplatz", + "osmScrub": "Brachland", + "osmImport": "Nester von OSM importieren", + "mergePolygons": "Sichtbare Polygone zusammenfassen", + "enableCellScan": "cell scan tool aktivieren", + "disableCellScan": "cell scan tool deaktivieren", + "coordsS2": "Koordinaten der S2 Zellenmitte:", + "circleS2Cells": "Zeichne S2 Zellen" +}; +let dePokemon = ["Bisasam","Bisaknosp","Bisaflor","Glumanda","Glutexo","Glurak","Schiggy","Schillok","Turtok","Raupy","Safcon","Smettbo","Hornliu","Kokuna","Bibor","Taubsi","Tauboga","Tauboss","Rattfratz","Rattikarl","Habitak","Ibitak","Rettan","Arbok","Pikachu","Raichu","Sandan","Sandamer","Nidoran♀","Nidorina","Nidoqueen","Nidoran♂","Nidorino","Nidoking","Piepi","Pixi","Vulpix","Vulnona","Pummeluff","Knuddeluff","Zubat","Golbat","Myrapla","Duflor","Giflor","Paras","Parasek","Bluzuk","Omot","Digda","Digdri","Mauzi","Snobilikat","Enton","Entoron","Menki","Rasaff","Fukano","Arkani","Quapsel","Quaputzi","Quappo","Abra","Kadabra","Simsala","Machollo","Maschock","Machomei","Knofensa","Ultrigaria","Sarzenia","Tentacha","Tentoxa","Kleinstein","Georok","Geowaz","Ponita","Gallopa","Flegmon","Lahmus","Magnetilo","Magneton","Porenta","Dodu","Dodri","Jurob","Jugong","Sleima","Sleimok","Muschas","Austos","Nebulak","Alpollo","Gengar","Onix","Traumato","Hypno","Krabby","Kingler","Voltobal","Lektrobal","Owei","Kokowei","Tragosso","Knogga","Kicklee","Nockchan","Schlurp","Smogon","Smogmog","Rihorn","Rizeros","Chaneira","Tangela","Kangama","Seeper","Seemon","Goldini","Golking","Sterndu","Starmie","Pantimos","Sichlor","Rossana","Elektek","Magmar","Pinsir","Tauros","Karpador","Garados","Lapras","Ditto","Evoli","Aquana","Blitza","Flamara","Porygon","Amonitas","Amoroso","Kabuto","Kabutops","Aerodactyl","Relaxo","Arktos","Zapdos","Lavados","Dratini","Dragonir","Dragoran","Mewtu","Mew","Endivie","Lorblatt","Meganie","Feurigel","Igelavar","Tornupto","Karnimani","Tyracroc","Impergator","Wiesor","Wiesenior","Hoothoot","Noctuh","Ledyba","Ledian","Webarak","Ariados","Iksbat","Lampi","Lanturn","Pichu","Pii","Fluffeluff","Togepi","Togetic","Natu","Xatu","Voltilamm","Waaty","Ampharos","Blubella","Marill","Azumarill","Mogelbaum","Quaxo","Hoppspross","Hubelupf","Papungha","Griffel","Sonnkern","Sonnflora","Yanma","Felino","Morlord","Psiana","Nachtara","Kramurx","Laschoking","Traunfugil","Icognito","Woingenau","Girafarig","Tannza","Forstellka","Dummisel","Skorgla","Stahlos","Snubbull","Granbull","Baldorfish","Scherox","Pottrott","Skaraborn","Sniebel","Teddiursa","Ursaring","Schneckmag","Magcargo","Quiekel","Keifel","Corasonn","Remoraid","Octillery","Botogel","Mantax","Panzaeron","Hunduster","Hundemon","Seedraking","Phanpy","Donphan","Porygon2","Damhirplex","Farbeagle","Rabauz","Kapoera","Kussilla","Elekid","Magby","Miltank","Heiteira","Raikou","Entei","Suicune","Larvitar","Pupitar","Despotar","Lugia","Ho-Oh","Celebi","Geckarbor","Reptain","Gewaldro","Flemmli","Jungglut","Lohgock","Hydropi","Moorabbel","Sumpex","Fiffyen","Magnayen","Zigzachs","Geradaks","Waumpel","Schaloko","Papinella","Panekon","Pudox","Loturzel","Lombrero","Kappalores","Samurzel","Blanas","Tengulist","Schwalbini","Schwalboss","Wingull","Pelipper","Trasla","Kirlia","Guardevoir","Gehweiher","Maskeregen","Knilz","Kapilz","Bummelz","Muntier","Letarking","Nincada","Ninjask","Ninjatom","Flurmel","Krakeelo","Krawumms","Makuhita","Hariyama","Azurill","Nasgnet","Eneco","Enekoro","Zobiris","Flunkifer","Stollunior","Stollrak","Stolloss","Meditie","Meditalis","Frizelbliz","Voltenso","Plusle","Minun","Volbeat","Illumise","Roselia","Schluppuck","Schlukwech","Kanivanha","Tohaido","Wailmer","Wailord","Camaub","Camerupt","Qurtel","Spoink","Groink","Pandir","Knacklion","Vibrava","Libelldra","Tuska","Noktuska","Wablu","Altaria","Sengo","Vipitis","Lunastein","Sonnfel","Schmerbe","Welsar","Krebscorps","Krebutack","Puppance","Lepumentas","Liliep","Wielie","Anorith","Armaldo","Barschwa","Milotic","Formeo","Kecleon","Shuppet","Banette","Zwirrlicht","Zwirrklop","Tropius","Palimpalim","Absol","Isso","Schneppke","Firnontor","Seemops","Seejong","Walraisa","Perlu","Aalabyss","Saganabyss","Relicanth","Liebiskus","Kindwurm","Draschel","Brutalanda","Tanhel","Metang","Metagross","Regirock","Regice","Registeel","Latias","Latios","Kyogre","Groudon","Rayquaza","Jirachi","Deoxys","Chelast","Chelcarain","Chelterrar","Panflam","Panpyro","Panferno","Plinfa","Pliprin","Impoleon","Staralili","Staravia","Staraptor","Bidiza","Bidifas","Zirpurze","Zirpeise","Sheinux","Luxio","Luxtra","Knospi","Roserade","Koknodon","Rameidon","Schilterus","Bollterus","Burmy","Burmadame","Moterpel","Wadribie","Honweisel","Pachirisu","Bamelin","Bojelin","Kikugi","Kinoso","Schalellos","Gastrodon","Ambidiffel","Driftlon","Drifzepeli","Haspiror","Schlapor","Traunmagil","Kramshef","Charmian","Shnurgarst","Klingplim","Skunkapuh","Skuntank","Bronzel","Bronzong","Mobai","Pantimimi","Wonneira","Plaudagei","Kryppuk","Kaumalat","Knarksel","Knakrack","Mampfaxo","Riolu","Lucario","Hippopotas","Hippoterus","Pionskora","Piondragi","Glibunkel","Toxiquak","Venuflibis","Finneon","Lumineon","Mantirps","Shnebedeck","Rexblisar","Snibunna","Magnezone","Schlurplek","Rihornior","Tangoloss","Elevoltek","Magbrant","Togekiss","Yanmega","Folipurba","Glaziola","Skorgro","Mamutel","Porygon-Z","Galagladi","Voluminas","Zwirrfinst","Frosdedje","Rotom","Selfe","Vesprit","Tobutz","Dialga","Palkia","Heatran","Regigigas","Giratina","Cresselia","Phione","Manaphy","Darkrai","Shaymin","Arceus","Victini","Serpifeu","Efoserp","Serpiroyal","Floink","Ferkokel","Flambirex","Ottaro","Zwottronin","Admurai","Nagelotz","Kukmarda","Yorkleff","Terribark","Bissbark","Felilou","Kleoparda","Vegimak","Vegichita","Grillmak","Grillchita","Sodamak","Sodachita","Somniam","Somnivora","Dusselgurr","Navitaub","Fasasnob","Elezeba","Zebritz","Kiesling","Sedimantur","Brockoloss","Fleknoil","Fletiamo","Rotomurf","Stalobor","Ohrdoch","Praktibalk","Strepoli","Meistagrif","Schallquap","Mebrana","Branawarz","Jiutesto","Karadonis","Strawickl","Folikon","Matrifol","Toxiped","Rollum","Cerapendra","Waumboll","Elfun","Lilminip","Dressella","Barschuft","Ganovil","Rokkaiman","Rabigator","Flampion","Flampivian","Maracamba","Lithomith","Castellith","Zurrokex","Irokex","Symvolara","Makabaja","Echnatoll","Galapaflos","Karippas","Flapteryx","Aeropteryx","Unratütox","Deponitox","Zorua","Zoroark","Picochilla","Chillabell","Mollimorba","Hypnomorba","Morbitesse","Monozyto","Mitodos","Zytomega","Piccolente","Swaroness","Gelatini","Gelatroppo","Gelatwino","Sesokitz","Kronjuwild","Emolga","Laukaps","Cavalanzas","Tarnpignon","Hutsassa","Quabbel","Apoquallyp","Mamolida","Wattzapf","Voltula","Kastadur","Tentantel","Klikk","Kliklak","Klikdiklak","Zapplardin","Zapplalek","Zapplarang","Pygraulon","Megalon","Lichtel","Laternecto","Skelabra","Milza","Sharfax","Maxax","Petznief","Siberio","Frigometri","Schnuthelm","Hydragil","Flunschlik","Lin-Fu","Wie-Shu","Shardrago","Golbit","Golgantes","Gladiantri","Caesurio","Bisofank","Geronimatz","Washakwil","Skallyk","Grypheldis","Furnifraß","Fermicula","Kapuno","Duodino","Trikephalo","Ignivor","Ramoth","Kobalium","Terrakium","Viridium","Boreos","Voltolos","Reshiram","Zekrom","Demeteros","Kyurem","Keldeo","Meloetta","Genesect","Igamaro","Igastarnish","Brigaron","Fynx","Rutena","Fennexis","Froxy","Amphizel","Quajutsu","Scoppel","Grebbit","Dartiri","Dartignis","Fiaro","Purmel","Puponcho","Vivillon","Leufeo","Pyroleo","Flabébé","Floette","Florges","Mähikel","Chevrumm","Pam-Pam","Pandagro","Coiffwaff","Psiau","Psiaugon","Gramokles","Duokles","Durengard","Parfi","Parfinesse","Flauschling","Sabbaione","Iscalar","Calamanero","Bithora","Thanathora","Algitt","Tandrak","Scampisto","Wummer","Eguana","Elezard","Balgoras","Monargoras","Amarino","Amagarga","Feelinara","Resladero","Dedenne","Rocara","Viscora","Viscargot","Viscogon","Clavion","Paragoni","Trombork","Irrbis","Pumpdjinn","Arktip","Arktilas","eF-eM","UHaFnir","Xerneas","Yveltal","Zygarde","Diancie","Hoopa","Volcanion","Bauz","Arboretoss","Silvarro","Flamiau","Miezunder","Fuegro","Robball","Marikeck","Primarene","Peppeck","Trompeck","Tukanon","Mangunior","Manguspektor","Mabula","Akkup","Donarion","Krabbox","Krawell","Choreogel","Wommel","Bandelby","Wuffels","Wolwerock","Lusardin","Garstella","Aggrostella","Pampuli","Pampross","Araqua","Aranestro","Imantis","Mantidea","Bubungus","Lamellux","Molunk","Amfira","Velursi","Kosturso","Frubberl","Frubaila","Fruyal","Curelei","Kommandutan","Quartermak","Reißlaus","Tectass","Sankabuh","Colossand","Gufa","Typ:Null","Amigento","Meteno","Koalelu","Tortunator","Togedemaru","Mimigma","Knirfish","Sen-Long","Moruda","Miniras","Mediras","Grandiras","Kapu-Riki","Kapu-Fala","Kapu-Toro","Kapu-Kime","Cosmog","Cosmovum","Solgaleo","Lunala","Anego","Masskito","Schabelle","Voltriant","Kaguron","Katagami","Schlingking","Necrozma","Magearna","Marshadow"]; diff --git a/other/en.js b/other/en.js new file mode 100644 index 0000000..4af2bc4 --- /dev/null +++ b/other/en.js @@ -0,0 +1,179 @@ +//en +let enSubs = { + "nest": "Nest", + "polygon": "Polygon", + "getSpawnReport": "Get spawn report", + "removeMap": "Remove from map", + "exportPolygon": "Export polygon", + "exportVP": "Export visible points (CSV)", + "countVP": "Count Visible points", + "copyClipboard": "Copy to clipboard", + "poiViewer": "Wayfarer mode", + "routeGenerator": "Planning mode", + "hideGyms": "Hide gyms", + "showGyms": "Show gyms", + "hidePokestops": "Hide pokestops", + "showPokestops": "Show pokestops", + "hidePokestopRange": "Hide pokestop range", + "showPokestopRange": "Show pokestop range", + "hideSpawnpoints": "Hide spawnpoints", + "showSpawnpoints": "Show spawnpoints", + "showAllPOIS": "Show all points", + "showUnknownPOIS": "Show unknown points only", + "hideViewingCells": "Hide viewing cells", + "showViewingCells": "Show viewing cells", + "enableManualCircle": "Enable manual circle mode", + "disableManualCircle": "Disable manual circle mode", + "importOSM": "Import nests from OSM", + "importPolygon": "Import polygon", + "importInstance": "Import instance", + "importAdBounds": "Import administrative boundaries", + "importSubmissions": "Import POIs", + "poiData": "POI data in format: lat, lng, title", + "csvOpener": "or select a CSV file:", + "submissionRangeCheck": "Show 20m range for Wayfarer submissions", + "clearRoute": "Clear route", + "clearShapes": "Clear all shapes", + "clearSubs": "Delete POIs", + "generateRoute": "Generate circles (bootstrap)", + "generateOptimizedRoute": "Generate optimized circles", + "getOutput": "Get output", + "openSettings": "Open settings", + "delete": "Delete", + "noData": "No data available.", + "exEligible": " (ex-eligible)", + "despawnTime": " Despawn time: ", + "unknownDespawnTime": " unknown despawn time ", + "count": "Count: ", + "countTotal": "Count total: ", + "countGyms": "Count gyms: ", + "countStops": "Count stops: ", + "countSpawnpoints": "Count spawnpoints: ", + "spawnReport": "Spawn report - ", + "unnamed": "unnamed", + "at": "at", + "skipped": " skipped, no data", + "nestReport": "Nest report - all nests in view", + "settings": "Settings", + "routeOptAtt": "Route optimization attempts:", + "tries": "Tries", + "s2cells0": "Red, level:", + "s2cells1": "Blue, level 14", + "s2cells2": "Green, level 17", + "s2CountPOI": "Show POI count", + "circleRadius": "Circle radius:", + "other": "other:", + "lastNestMigration": "Last nest migration:", + "spawnReportLimit": "Spawn report limit:", + "spawnReportLimitExp": "Pokemon (0 for unlimited)", + "selectLanguage": "Select language:", + "chooseTileset": "Choose tileset:", + "ownTileset": "Own tileset", + "close": "Close", + "output": "Output", + "generatedRoute": "Generated route:", + "getAllNests": "Get all nest reports", + "countPoints": "Count points in circles", + "optimize": "Optimize!", + "optimizeGyms": "Optimize for gyms", + "optimizePokestops": "Optimize for pokestops", + "optimizeSpawnpoints": "Optimize for all spawnpoints", + "optimizeUnknownSpawnpoints": "Optimize for spawnpoints without TTH", + "on": "On", + "off": "Off", + "optimizePiP": "Optimize points in polygons", + "optimizePiNP": "Optimize points in nest polygons", + "optimizePiC": "Optimize points in circles", + "getOptimization": "Get optimization", + "copied": "Copied!", + "selectInstance": "Select an instance:", + "instanceColor": "Instance color:", + "polygonColor": "Polygon color:", + "polygonDataType": "Polygon data type:", + "coordinateList": "Coordinate list: (latitude,longitude on each new line)", + "geoJson": "GeoJSON", + "poracle": "PoracleJS format", + "polygonData": "Polygon data:", + "import": "Import", + "importNest": "Import as nest", + "exportPolygonPoints": "Export polygon points (CSV)", + "gyms": "Gyms:", + "pokestops": "Pokestops:", + "spawnpoints": "Spawnpoints:", + "pokemon": "Pokémon", + "getOwnLocation": "Get to my location!", + "coordTypeUnsorted": "unsorted", + "coordTypeSorted": "auto-sorted", + "countCircles": "Number of circles:", + "adBoundsHeader": "Select level of administrative boundaries", + "adBounds1": "Counties", + "adBounds2": "Cities", + "adBounds3": "Wards", + "getAdBounds": "Get polygons", + "hideOldSpawnpoints": "Show old spawnpoints", + "showOldSpawnpoints": "Hide old spawnpoints", + "oldSpawnpointsTitle": "No spawnpoints last updated before:", + "instanceMode": "Import circles in passive mode: ", + "enableNewPOI": "Enable new POI", + "disableNewPOI": "Disable new POI", + "exportPOIs": "Export", + "exportPOILabel": "Your POI has the following coordinates:", + "outputAvgPt": "Average points per circle: ", + "exportListCount": "Objects on exportlist: ", + "chooseName": "Please choose a name!", + "addToExport": "Add to exportlist", + "removeFromExport": "Remove from exportlist", + "name": "Name:", + "saveFile": "Save as File", + "ownRadius": "own radius", + "drawnCircles": "drawn circles", + "selectInstances": "Select instances", + "importCirclesIns": "imported circles", + "importCirclesHl": "Own coordinates: (latitude,longitude on each new line)", + "importCirclesBtn": "Import circles", + "showRoute": "Show route", + "hideRoute": "Hide route", + "newRoute": "New route", + "hideQuests": "Hide stops with missing quests", + "showQuests": "Show stops with missing quests", + "questCheck": "Quest instances to be checked:", + "questCheckButton": "Show it!", + "showBorders": "Show instance borders", + "generateWithS2Cells": "bootstrap with s2 cells", + "lastUpdate": "Last update (UTC): ", + "stop_deleted": "marked as deleted", + "coords": "Coordinates", + "drawPolygon": "Draw a polygon", + "drawCircle": "Draw a free circle", + "searchErr": "Location not found", + "searchCancel": "Cancel", + "searchPlaceholder": "Search...", + "editEdit": "Edit layers", + "editEditDisabled": "No layers to edit", + "v2": "v2.0 (1100m)", + "circleID": "Circle ID:", + "manualdbHint": "only usable with manualdb:", + "importFromDB": "Import nests from db", + "writeAllToDB": "Update nests in db", + "nestOptions": "Nestoptions", + "writeSuccess": "Nest(s) successfully added/updated!", + "writeToDB": "Write to db", + "instanceLength": "Length of instance:", + "area": "Area", + "osmOptions": "OSM Options", + "osmPark": "Park", + "osmMeadow": "Meadow", + "osmRecGround": "Recreation Ground", + "osmGrass": "Grass", + "osmPitch": "Pitch", + "osmGolf": "Golf course", + "osmPlayground": "Playground", + "osmScrub": "Scrub", + "osmImport": "Import nests from OSM", + "mergePolygons": "Merge visible polygons", + "enableCellScan": "activate cell scan tool", + "disableCellScan": "deactivate cell scan tool", + "coordsS2": "S2 cell center coordinates:", + "circleS2Cells": "Draw circle S2 cells" +}; +let enPokemon = ["Bulbasaur","Ivysaur","Venusaur","Charmander","Charmeleon","Charizard","Squirtle","Wartortle","Blastoise","Caterpie","Metapod","Butterfree","Weedle","Kakuna","Beedrill","Pidgey","Pidgeotto","Pidgeot","Rattata","Raticate","Spearow","Fearow","Ekans","Arbok","Pikachu","Raichu","Sandshrew","Sandslash","Nidoran\u2640","Nidorina","Nidoqueen","Nidoran\u2642","Nidorino","Nidoking","Clefairy","Clefable","Vulpix","Ninetales","Jigglypuff","Wigglytuff","Zubat","Golbat","Oddish","Gloom","Vileplume","Paras","Parasect","Venonat","Venomoth","Diglett","Dugtrio","Meowth","Persian","Psyduck","Golduck","Mankey","Primeape","Growlithe","Arcanine","Poliwag","Poliwhirl","Poliwrath","Abra","Kadabra","Alakazam","Machop","Machoke","Machamp","Bellsprout","Weepinbell","Victreebel","Tentacool","Tentacruel","Geodude","Graveler","Golem","Ponyta","Rapidash","Slowpoke","Slowbro","Magnemite","Magneton","Farfetch\u2019d","Doduo","Dodrio","Seel","Dewgong","Grimer","Muk","Shellder","Cloyster","Gastly","Haunter","Gengar","Onix","Drowzee","Hypno","Krabby","Kingler","Voltorb","Electrode","Exeggcute","Exeggutor","Cubone","Marowak","Hitmonlee","Hitmonchan","Lickitung","Koffing","Weezing","Rhyhorn","Rhydon","Chansey","Tangela","Kangaskhan","Horsea","Seadra","Goldeen","Seaking","Staryu","Starmie","Mr. Mime","Scyther","Jynx","Electabuzz","Magmar","Pinsir","Tauros","Magikarp","Gyarados","Lapras","Ditto","Eevee","Vaporeon","Jolteon","Flareon","Porygon","Omanyte","Omastar","Kabuto","Kabutops","Aerodactyl","Snorlax","Articuno","Zapdos","Moltres","Dratini","Dragonair","Dragonite","Mewtwo","Mew","Chikorita","Bayleef","Meganium","Cyndaquil","Quilava","Typhlosion","Totodile","Croconaw","Feraligatr","Sentret","Furret","Hoothoot","Noctowl","Ledyba","Ledian","Spinarak","Ariados","Crobat","Chinchou","Lanturn","Pichu","Cleffa","Igglybuff","Togepi","Togetic","Natu","Xatu","Mareep","Flaaffy","Ampharos","Bellossom","Marill","Azumarill","Sudowoodo","Politoed","Hoppip","Skiploom","Jumpluff","Aipom","Sunkern","Sunflora","Yanma","Wooper","Quagsire","Espeon","Umbreon","Murkrow","Slowking","Misdreavus","Unown","Wobbuffet","Girafarig","Pineco","Forretress","Dunsparce","Gligar","Steelix","Snubbull","Granbull","Qwilfish","Scizor","Shuckle","Heracross","Sneasel","Teddiursa","Ursaring","Slugma","Magcargo","Swinub","Piloswine","Corsola","Remoraid","Octillery","Delibird","Mantine","Skarmory","Houndour","Houndoom","Kingdra","Phanpy","Donphan","Porygon2","Stantler","Smeargle","Tyrogue","Hitmontop","Smoochum","Elekid","Magby","Miltank","Blissey","Raikou","Entei","Suicune","Larvitar","Pupitar","Tyranitar","Lugia","Ho-Oh","Celebi","Treecko","Grovyle","Sceptile","Torchic","Combusken","Blaziken","Mudkip","Marshtomp","Swampert","Poochyena","Mightyena","Zigzagoon","Linoone","Wurmple","Silcoon","Beautifly","Cascoon","Dustox","Lotad","Lombre","Ludicolo","Seedot","Nuzleaf","Shiftry","Taillow","Swellow","Wingull","Pelipper","Ralts","Kirlia","Gardevoir","Surskit","Masquerain","Shroomish","Breloom","Slakoth","Vigoroth","Slaking","Nincada","Ninjask","Shedinja","Whismur","Loudred","Exploud","Makuhita","Hariyama","Azurill","Nosepass","Skitty","Delcatty","Sableye","Mawile","Aron","Lairon","Aggron","Meditite","Medicham","Electrike","Manectric","Plusle","Minun","Volbeat","Illumise","Roselia","Gulpin","Swalot","Carvanha","Sharpedo","Wailmer","Wailord","Numel","Camerupt","Torkoal","Spoink","Grumpig","Spinda","Trapinch","Vibrava","Flygon","Cacnea","Cacturne","Swablu","Altaria","Zangoose","Seviper","Lunatone","Solrock","Barboach","Whiscash","Corphish","Crawdaunt","Baltoy","Claydol","Lileep","Cradily","Anorith","Armaldo","Feebas","Milotic","Castform","Kecleon","Shuppet","Banette","Duskull","Dusclops","Tropius","Chimecho","Absol","Wynaut","Snorunt","Glalie","Spheal","Sealeo","Walrein","Clamperl","Huntail","Gorebyss","Relicanth","Luvdisc","Bagon","Shelgon","Salamence","Beldum","Metang","Metagross","Regirock","Regice","Registeel","Latias","Latios","Kyogre","Groudon","Rayquaza","Jirachi","Deoxys","Turtwig","Grotle","Torterra","Chimchar","Monferno","Infernape","Piplup","Prinplup","Empoleon","Starly","Staravia","Staraptor","Bidoof","Bibarel","Kricketot","Kricketune","Shinx","Luxio","Luxray","Budew","Roserade","Cranidos","Rampardos","Shieldon","Bastiodon","Burmy","Wormadam","Mothim","Combee","Vespiquen","Pachirisu","Buizel","Floatzel","Cherubi","Cherrim","Shellos","Gastrodon","Ambipom","Drifloon","Drifblim","Buneary","Lopunny","Mismagius","Honchkrow","Glameow","Purugly","Chingling","Stunky","Skuntank","Bronzor","Bronzong","Bonsly","Mime Jr.","Happiny","Chatot","Spiritomb","Gible","Gabite","Garchomp","Munchlax","Riolu","Lucario","Hippopotas","Hippowdon","Skorupi","Drapion","Croagunk","Toxicroak","Carnivine","Finneon","Lumineon","Mantyke","Snover","Abomasnow","Weavile","Magnezone","Lickilicky","Rhyperior","Tangrowth","Electivire","Magmortar","Togekiss","Yanmega","Leafeon","Glaceon","Gliscor","Mamoswine","Porygon-Z","Gallade","Probopass","Dusknoir","Froslass","Rotom","Uxie","Mesprit","Azelf","Dialga","Palkia","Heatran","Regigigas","Giratina","Cresselia","Phione","Manaphy","Darkrai","Shaymin","Arceus","Victini","Snivy","Servine","Serperior","Tepig","Pignite","Emboar","Oshawott","Dewott","Samurott","Patrat","Watchog","Lillipup","Herdier","Stoutland","Purrloin","Liepard","Pansage","Simisage","Pansear","Simisear","Panpour","Simipour","Munna","Musharna","Pidove","Tranquill","Unfezant","Blitzle","Zebstrika","Roggenrola","Boldore","Gigalith","Woobat","Swoobat","Drilbur","Excadrill","Audino","Timburr","Gurdurr","Conkeldurr","Tympole","Palpitoad","Seismitoad","Throh","Sawk","Sewaddle","Swadloon","Leavanny","Venipede","Whirlipede","Scolipede","Cottonee","Whimsicott","Petilil","Lilligant","Basculin","Sandile","Krokorok","Krookodile","Darumaka","Darmanitan","Maractus","Dwebble","Crustle","Scraggy","Scrafty","Sigilyph","Yamask","Cofagrigus","Tirtouga","Carracosta","Archen","Archeops","Trubbish","Garbodor","Zorua","Zoroark","Minccino","Cinccino","Gothita","Gothorita","Gothitelle","Solosis","Duosion","Reuniclus","Ducklett","Swanna","Vanillite","Vanillish","Vanilluxe","Deerling","Sawsbuck","Emolga","Karrablast","Escavalier","Foongus","Amoonguss","Frillish","Jellicent","Alomomola","Joltik","Galvantula","Ferroseed","Ferrothorn","Klink","Klang","Klinklang","Tynamo","Eelektrik","Eelektross","Elgyem","Beheeyem","Litwick","Lampent","Chandelure","Axew","Fraxure","Haxorus","Cubchoo","Beartic","Cryogonal","Shelmet","Accelgor","Stunfisk","Mienfoo","Mienshao","Druddigon","Golett","Golurk","Pawniard","Bisharp","Bouffalant","Rufflet","Braviary","Vullaby","Mandibuzz","Heatmor","Durant","Deino","Zweilous","Hydreigon","Larvesta","Volcarona","Cobalion","Terrakion","Virizion","Tornadus","Thundurus","Reshiram","Zekrom","Landorus","Kyurem","Keldeo","Meloetta","Genesect","Chespin","Quilladin","Chesnaught","Fennekin","Braixen","Delphox","Froakie","Frogadier","Greninja","Bunnelby","Diggersby","Fletchling","Fletchinder","Talonflame","Scatterbug","Spewpa","Vivillon","Litleo","Pyroar","Flabébé","Floette","Florges","Skiddo","Gogoat","Pancham","Pangoro","Furfrou","Espurr","Meowstic","Honedge","Doublade","Aegislash","Spritzee","Aromatisse","Swirlix","Slurpuff","Inkay","Malamar","Binacle","Barbaracle","Skrelp","Dragalge","Clauncher","Clawitzer","Helioptile","Heliolisk","Tyrunt","Tyrantrum","Amaura","Aurorus","Sylveon","Hawlucha","Dedenne","Carbink","Goomy","Sliggoo","Goodra","Klefki","Phantump","Trevenant","Pumpkaboo","Gourgeist","Bergmite","Avalugg","Noibat","Noivern","Xerneas","Yveltal","Zygarde","Diancie","Hoopa","Volcanion","Rowlet","Dartrix","Decidueye","Litten","Torracat","Incineroar","Popplio","Brionne","Primarina","Pikipek","Trumbeak","Toucannon","Yungoos","Gumshoos","Grubbin","Charjabug","Vikavolt","Crabrawler","Crabominable","Oricorio","Cutiefly","Ribombee","Rockruff","Lycanroc","Wishiwashi","Mareanie","Toxapex","Mudbray","Mudsdale","Dewpider","Araquanid","Fomantis","Lurantis","Morelull","Shiinotic","Salandit","Salazzle","Stufful","Bewear","Bounsweet","Steenee","Tsareena","Comfey","Oranguru","Passimian","Wimpod","Golisopod","Sandygast","Palossand","Pyukumuku","Type: Null","Silvally","Minior","Komala","Turtonator","Togedemaru","Mimikyu","Bruxish","Drampa","Dhelmise","Jangmo-o","Hakamo-o","Kommo-o","Tapu Koko","Tapu Lele","Tapu Bulu","Tapu Fini","Cosmog","Cosmoem","Solgaleo","Lunala","Nihilego","Buzzwole","Pheromosa","Xurkitree","Celesteela","Kartana","Guzzlord","Necrozma","Magearna","Marshadow"]; diff --git a/other/fr.js b/other/fr.js new file mode 100644 index 0000000..75d7237 --- /dev/null +++ b/other/fr.js @@ -0,0 +1,176 @@ +//fr +let frSubs = { + "nest": "Nid", + "polygon": "Polygone", + "getSpawnReport": "Rapport de spawns", + "removeMap": "Supprime du plan", + "exportPolygon": "Exporte polygone", + "exportVP": "Exporte points visibles", + "countVP": "Compte points visibles", + "copyClipboard": "Copier", + "poiViewer": "Mode Wayfarer", + "routeGenerator": "Mode de planification", + "hideGyms": "Cache les arènes", + "showGyms": "Montre les arènes", + "hidePokestops": "Cache les pokéstops", + "showPokestops": "Montre les pokéstops", + "hidePokestopRange": "Cache la zone des pokéstops", + "showPokestopRange": "Montre la zone des pokéstops", + "hideSpawnpoints": "Cache les spawnpoints", + "showSpawnpoints": "Montre les spawnpoints", + "showAllPOIS": "Montre tous les POIs", + "showUnknownPOIS": "Montre seulement les points inconnus", + "hideViewingCells": "Cache cells s2", + "showViewingCells": "Montre cells s2", + "enableManualCircle": "Active le mode manuel du cercle", + "disableManualCircle": "Désactive le mode manuel du cercle", + "importOSM": "Importer les nests d'OSM", + "importPolygon": "Importe polygone", + "importInstance": "Importe d'instances", + "importAdBounds": "Importe de frontières administratives", + "importSubmissions": "Importe de POIs", + "poiData": "POI data en format: lat, lng, title", + "csvOpener": "ou selectionne un fichier CSV:", + "submissionRangeCheck": "Montre la zone de 20m pour soumissions Wayfarer", + "clearRoute": "Dégage la route", + "clearShapes": "Dégage tous", + "clearSubs": "Supprime les POIs", + "generateRoute": "Génère des cercles (bootstrap)", + "generateOptimizedRoute": "Génère des cercles optimisés", + "getOutput": "Obtiens le résultat", + "openSettings": "Ouvre les paramètres", + "delete": "Supprime", + "noData": "aucune donnée disponible.", + "exEligible": " (ex-eligible)", + "despawnTime": " Moment de despawn: ", + "unknownDespawnTime": " moment de despawn inconnu ", + "count": "Compte: ", + "countTotal": "Compte total: ", + "countGyms": "Compte d'arènes: ", + "countStops": "Compte de stops: ", + "countSpawnpoints": "Compte des spawnpoints: ", + "spawnReport": "Rapport de spawns - ", + "unnamed": "sans nom", + "at": "à", + "skipped": " sauté, pas de données", + "nestReport": "Rapport de nids - tous les nids en vue", + "settings": "Paramètres", + "routeOptAtt": "Essais d'optimisation de la route:", + "tries": "Essais", + "s2cells0": "Rouge, level:", + "s2cells1": "Bleu, level 14", + "s2cells2": "Vert, level 17", + "s2CountPOI": "Montre compte de POIs", + "circleRadius": "Rayon du cercle:", + "other": "autres:", + "lastNestMigration": "Dernières migration de nids:", + "spawnReportLimit": "limit du rapport des spawns:", + "spawnReportLimitExp": "Pokémon (0 pour illimité)", + "selectLanguage": "Choisis une langue:", + "chooseTileset": "Choisis un tileset:", + "ownTileset": "Tileset propre", + "close": "Ferme", + "output": "Résultat", + "generatedRoute": "Route générée:", + "getAllNests": "Obtiens tous les rapports de nids", + "countPoints": "Compte les points à l'intérieur des cercles", + "optimize": "Optimise!", + "optimizeGyms": "Optimise pour les arènes", + "optimizePokestops": "Optimise pour les pokéstops", + "optimizeSpawnpoints": "Optimise pour tous les spawnpoints", + "optimizeUnknownSpawnpoints": "Optimise pour les spawnpoints sans TTH", + "on": "Activé", + "off": "Desactivé", + "optimizePiP": "Optimise les points dans les polygons", + "optimizePiNP": "Optimise les points dans les polygons de nid", + "optimizePiC": "Optimise les points dans les cercles", + "getOptimization": "Obtiens l'optimisation", + "copied": "Copié!", + "selectInstance": "Choisis une instance:", + "instanceColor": "Couleur de l'instance:", + "polygonColor": "Couleur du polygone:", + "polygonDataType": "Type de données de polygone:", + "coordinateList": "List des coordinates: (latitude,longitude sur une ligne)", + "geoJson": "GeoJSON", + "poracle": "Format PoracleJS", + "polygonData": "Données de polygone:", + "import": "Importe", + "importNest": "Importe comme nid", + "exportPolygonPoints": "Exporte les points du polygone (CSV)", + "gyms": "Arènes:", + "pokestops": "Pokéstops:", + "spawnpoints": "Spawnpoints:", + "pokemon": "Pokémon", + "getOwnLocation": "Localise moi!", + "coordTypeUnsorted": "non triés", + "coordTypeSorted": "auto-triés", + "countCircles": "Compte de cercles:", + "adBoundsHeader": "Choisis le niveau de frontières administratives", + "adBounds1": "Départements", + "adBounds2": "Villes", + "adBounds3": "Quartiers", + "getAdBounds": "Obtiens les polygons", + "hideOldSpawnpoints": "Montre les vieux spawnpoints", + "showOldSpawnpoints": "Cache les vieux spawnpoints", + "oldSpawnpointsTitle": "Pas de spawnpoints actualisés avant:", + "instanceMode": "Importe les cercles en mode passive: ", + "enableNewPOI": "Active nouveau POI", + "disableNewPOI": "Désactive nouveau POI", + "exportPOIs": "Exporte", + "exportPOILabel": "Ton POI a les coordinates suivants:", + "outputAvgPt": "Points par cercle en moyenne: ", + "exportListCount": "Objets sur la liste d'export: ", + "chooseName": "Choisis un nom!", + "addToExport": "Ajoute sur la liste d'export", + "removeFromExport": "Supprime de la liste d'export", + "name": "Nom:", + "saveFile": "Sauver comme fichier", + "ownRadius": "rayon propre", + "drawnCircles": "cercles dessinés", + "selectInstances": "Choisis les instances", + "importCirclesIns": "cercles importés", + "importCirclesHl": "Coordinates propre: (latitude,longitude on each new line)", + "importCirclesBtn": "Cercles importés", + "showRoute": "Montre route", + "hideRoute": "Cache route", + "newRoute": "Nouveau route", + "hideQuests": "Montre stops sans quest", + "showQuests": "Cache stops sans quest", + "questCheck": "Instances à vérifier:", + "questCheckButton": "Montre!", + "showBorders": "Montre les frontières des instances", + "generateWithS2Cells": "Bootstrap avec cells s2", + "lastUpdate": "Dernière actualisation (UTC): ", + "stop_deleted": "marqué pour suppression", + "coords": "Coordinates", + "drawPolygon": "Tire un polygon", + "drawCircle": "Tire un cercle libre", + "searchErr": "Location pas connu", + "searchCancel": "Annuler", + "searchPlaceholder": "Chercher...", + "editEdit": "Editer les couches", + "editEditDisabled": "Pas de couche à éditer", + "v2": "v2.0 (1100m)", + "circleID": "ID du cercle:", + "manualdbHint": "seulement utilisable avec manualdb:", + "importFromDB": "Importer les nids de la bd", + "writeAllToDB": "Actualise les nids en bd", + "nestOptions": "Options de nid", + "writeSuccess": "Réussi à actualiser/inscrire le(s) nid(s)", + "writeToDB": "Inscrire en bd", + "instanceLength": "Longueur de l'instance:", + "area": "Superficie", + "osmOptions": "Options OSM", + "osmPark": "Parc", + "osmMeadow": "Prairie", + "osmRecGround": "Terrain de loisirs", + "osmGrass": "Pâturage", + "osmPitch": "Terrain de jeu", + "osmGolf": "Parcours de golf", + "osmPlayground": "Terrain de jeux", + "osmScrub": "Broussailles", + "osmImport": "Importer les nids d'OSM", + "mergePolygons": "Fussioner les polygons visibles", + "circleS2Cells": "Dessiner les cellules S2" +}; +let frPokemon = ["Bulbasaur","Ivysaur","Venusaur","Charmander","Charmeleon","Charizard","Squirtle","Wartortle","Blastoise","Caterpie","Metapod","Butterfree","Weedle","Kakuna","Beedrill","Pidgey","Pidgeotto","Pidgeot","Rattata","Raticate","Spearow","Fearow","Ekans","Arbok","Pikachu","Raichu","Sandshrew","Sandslash","Nidoran\u2640","Nidorina","Nidoqueen","Nidoran\u2642","Nidorino","Nidoking","Clefairy","Clefable","Vulpix","Ninetales","Jigglypuff","Wigglytuff","Zubat","Golbat","Oddish","Gloom","Vileplume","Paras","Parasect","Venonat","Venomoth","Diglett","Dugtrio","Meowth","Persian","Psyduck","Golduck","Mankey","Primeape","Growlithe","Arcanine","Poliwag","Poliwhirl","Poliwrath","Abra","Kadabra","Alakazam","Machop","Machoke","Machamp","Bellsprout","Weepinbell","Victreebel","Tentacool","Tentacruel","Geodude","Graveler","Golem","Ponyta","Rapidash","Slowpoke","Slowbro","Magnemite","Magneton","Farfetch\u2019d","Doduo","Dodrio","Seel","Dewgong","Grimer","Muk","Shellder","Cloyster","Gastly","Haunter","Gengar","Onix","Drowzee","Hypno","Krabby","Kingler","Voltorb","Electrode","Exeggcute","Exeggutor","Cubone","Marowak","Hitmonlee","Hitmonchan","Lickitung","Koffing","Weezing","Rhyhorn","Rhydon","Chansey","Tangela","Kangaskhan","Horsea","Seadra","Goldeen","Seaking","Staryu","Starmie","Mr. Mime","Scyther","Jynx","Electabuzz","Magmar","Pinsir","Tauros","Magikarp","Gyarados","Lapras","Ditto","Eevee","Vaporeon","Jolteon","Flareon","Porygon","Omanyte","Omastar","Kabuto","Kabutops","Aerodactyl","Snorlax","Articuno","Zapdos","Moltres","Dratini","Dragonair","Dragonite","Mewtwo","Mew","Chikorita","Bayleef","Meganium","Cyndaquil","Quilava","Typhlosion","Totodile","Croconaw","Feraligatr","Sentret","Furret","Hoothoot","Noctowl","Ledyba","Ledian","Spinarak","Ariados","Crobat","Chinchou","Lanturn","Pichu","Cleffa","Igglybuff","Togepi","Togetic","Natu","Xatu","Mareep","Flaaffy","Ampharos","Bellossom","Marill","Azumarill","Sudowoodo","Politoed","Hoppip","Skiploom","Jumpluff","Aipom","Sunkern","Sunflora","Yanma","Wooper","Quagsire","Espeon","Umbreon","Murkrow","Slowking","Misdreavus","Unown","Wobbuffet","Girafarig","Pineco","Forretress","Dunsparce","Gligar","Steelix","Snubbull","Granbull","Qwilfish","Scizor","Shuckle","Heracross","Sneasel","Teddiursa","Ursaring","Slugma","Magcargo","Swinub","Piloswine","Corsola","Remoraid","Octillery","Delibird","Mantine","Skarmory","Houndour","Houndoom","Kingdra","Phanpy","Donphan","Porygon2","Stantler","Smeargle","Tyrogue","Hitmontop","Smoochum","Elekid","Magby","Miltank","Blissey","Raikou","Entei","Suicune","Larvitar","Pupitar","Tyranitar","Lugia","Ho-Oh","Celebi","Treecko","Grovyle","Sceptile","Torchic","Combusken","Blaziken","Mudkip","Marshtomp","Swampert","Poochyena","Mightyena","Zigzagoon","Linoone","Wurmple","Silcoon","Beautifly","Cascoon","Dustox","Lotad","Lombre","Ludicolo","Seedot","Nuzleaf","Shiftry","Taillow","Swellow","Wingull","Pelipper","Ralts","Kirlia","Gardevoir","Surskit","Masquerain","Shroomish","Breloom","Slakoth","Vigoroth","Slaking","Nincada","Ninjask","Shedinja","Whismur","Loudred","Exploud","Makuhita","Hariyama","Azurill","Nosepass","Skitty","Delcatty","Sableye","Mawile","Aron","Lairon","Aggron","Meditite","Medicham","Electrike","Manectric","Plusle","Minun","Volbeat","Illumise","Roselia","Gulpin","Swalot","Carvanha","Sharpedo","Wailmer","Wailord","Numel","Camerupt","Torkoal","Spoink","Grumpig","Spinda","Trapinch","Vibrava","Flygon","Cacnea","Cacturne","Swablu","Altaria","Zangoose","Seviper","Lunatone","Solrock","Barboach","Whiscash","Corphish","Crawdaunt","Baltoy","Claydol","Lileep","Cradily","Anorith","Armaldo","Feebas","Milotic","Castform","Kecleon","Shuppet","Banette","Duskull","Dusclops","Tropius","Chimecho","Absol","Wynaut","Snorunt","Glalie","Spheal","Sealeo","Walrein","Clamperl","Huntail","Gorebyss","Relicanth","Luvdisc","Bagon","Shelgon","Salamence","Beldum","Metang","Metagross","Regirock","Regice","Registeel","Latias","Latios","Kyogre","Groudon","Rayquaza","Jirachi","Deoxys","Turtwig","Grotle","Torterra","Chimchar","Monferno","Infernape","Piplup","Prinplup","Empoleon","Starly","Staravia","Staraptor","Bidoof","Bibarel","Kricketot","Kricketune","Shinx","Luxio","Luxray","Budew","Roserade","Cranidos","Rampardos","Shieldon","Bastiodon","Burmy","Wormadam","Mothim","Combee","Vespiquen","Pachirisu","Buizel","Floatzel","Cherubi","Cherrim","Shellos","Gastrodon","Ambipom","Drifloon","Drifblim","Buneary","Lopunny","Mismagius","Honchkrow","Glameow","Purugly","Chingling","Stunky","Skuntank","Bronzor","Bronzong","Bonsly","Mime Jr.","Happiny","Chatot","Spiritomb","Gible","Gabite","Garchomp","Munchlax","Riolu","Lucario","Hippopotas","Hippowdon","Skorupi","Drapion","Croagunk","Toxicroak","Carnivine","Finneon","Lumineon","Mantyke","Snover","Abomasnow","Weavile","Magnezone","Lickilicky","Rhyperior","Tangrowth","Electivire","Magmortar","Togekiss","Yanmega","Leafeon","Glaceon","Gliscor","Mamoswine","Porygon-Z","Gallade","Probopass","Dusknoir","Froslass","Rotom","Uxie","Mesprit","Azelf","Dialga","Palkia","Heatran","Regigigas","Giratina","Cresselia","Phione","Manaphy","Darkrai","Shaymin","Arceus","Victini","Snivy","Servine","Serperior","Tepig","Pignite","Emboar","Oshawott","Dewott","Samurott","Patrat","Watchog","Lillipup","Herdier","Stoutland","Purrloin","Liepard","Pansage","Simisage","Pansear","Simisear","Panpour","Simipour","Munna","Musharna","Pidove","Tranquill","Unfezant","Blitzle","Zebstrika","Roggenrola","Boldore","Gigalith","Woobat","Swoobat","Drilbur","Excadrill","Audino","Timburr","Gurdurr","Conkeldurr","Tympole","Palpitoad","Seismitoad","Throh","Sawk","Sewaddle","Swadloon","Leavanny","Venipede","Whirlipede","Scolipede","Cottonee","Whimsicott","Petilil","Lilligant","Basculin","Sandile","Krokorok","Krookodile","Darumaka","Darmanitan","Maractus","Dwebble","Crustle","Scraggy","Scrafty","Sigilyph","Yamask","Cofagrigus","Tirtouga","Carracosta","Archen","Archeops","Trubbish","Garbodor","Zorua","Zoroark","Minccino","Cinccino","Gothita","Gothorita","Gothitelle","Solosis","Duosion","Reuniclus","Ducklett","Swanna","Vanillite","Vanillish","Vanilluxe","Deerling","Sawsbuck","Emolga","Karrablast","Escavalier","Foongus","Amoonguss","Frillish","Jellicent","Alomomola","Joltik","Galvantula","Ferroseed","Ferrothorn","Klink","Klang","Klinklang","Tynamo","Eelektrik","Eelektross","Elgyem","Beheeyem","Litwick","Lampent","Chandelure","Axew","Fraxure","Haxorus","Cubchoo","Beartic","Cryogonal","Shelmet","Accelgor","Stunfisk","Mienfoo","Mienshao","Druddigon","Golett","Golurk","Pawniard","Bisharp","Bouffalant","Rufflet","Braviary","Vullaby","Mandibuzz","Heatmor","Durant","Deino","Zweilous","Hydreigon","Larvesta","Volcarona","Cobalion","Terrakion","Virizion","Tornadus","Thundurus","Reshiram","Zekrom","Landorus","Kyurem","Keldeo","Meloetta","Genesect","Chespin","Quilladin","Chesnaught","Fennekin","Braixen","Delphox","Froakie","Frogadier","Greninja","Bunnelby","Diggersby","Fletchling","Fletchinder","Talonflame","Scatterbug","Spewpa","Vivillon","Litleo","Pyroar","Flabébé","Floette","Florges","Skiddo","Gogoat","Pancham","Pangoro","Furfrou","Espurr","Meowstic","Honedge","Doublade","Aegislash","Spritzee","Aromatisse","Swirlix","Slurpuff","Inkay","Malamar","Binacle","Barbaracle","Skrelp","Dragalge","Clauncher","Clawitzer","Helioptile","Heliolisk","Tyrunt","Tyrantrum","Amaura","Aurorus","Sylveon","Hawlucha","Dedenne","Carbink","Goomy","Sliggoo","Goodra","Klefki","Phantump","Trevenant","Pumpkaboo","Gourgeist","Bergmite","Avalugg","Noibat","Noivern","Xerneas","Yveltal","Zygarde","Diancie","Hoopa","Volcanion","Rowlet","Dartrix","Decidueye","Litten","Torracat","Incineroar","Popplio","Brionne","Primarina","Pikipek","Trumbeak","Toucannon","Yungoos","Gumshoos","Grubbin","Charjabug","Vikavolt","Crabrawler","Crabominable","Oricorio","Cutiefly","Ribombee","Rockruff","Lycanroc","Wishiwashi","Mareanie","Toxapex","Mudbray","Mudsdale","Dewpider","Araquanid","Fomantis","Lurantis","Morelull","Shiinotic","Salandit","Salazzle","Stufful","Bewear","Bounsweet","Steenee","Tsareena","Comfey","Oranguru","Passimian","Wimpod","Golisopod","Sandygast","Palossand","Pyukumuku","Type: Null","Silvally","Minior","Komala","Turtonator","Togedemaru","Mimikyu","Bruxish","Drampa","Dhelmise","Jangmo-o","Hakamo-o","Kommo-o","Tapu Koko","Tapu Lele","Tapu Bulu","Tapu Fini","Cosmog","Cosmoem","Solgaleo","Lunala","Nihilego","Buzzwole","Pheromosa","Xurkitree","Celesteela","Kartana","Guzzlord","Necrozma","Magearna","Marshadow"]; diff --git a/other/leaflet-search.js b/other/leaflet-search.js new file mode 100644 index 0000000..1a8cb78 --- /dev/null +++ b/other/leaflet-search.js @@ -0,0 +1,1032 @@ +/* + * Leaflet Control Search v2.9.7 - 2019-01-14 + * + * Copyright 2019 Stefano Cudini + * stefano.cudini@gmail.com + * http://labs.easyblog.it/ + * + * Licensed under the MIT license. + * + * Demo: + * http://labs.easyblog.it/maps/leaflet-search/ + * + * Source: + * git@github.com:stefanocudini/leaflet-search.git + * + */ +/* + Name Data passed Description + + Managed Events: + search:locationfound {latlng, title, layer} fired after moved and show markerLocation + search:expanded {} fired after control was expanded + search:collapsed {} fired after control was collapsed + search:cancel {} fired after cancel button clicked + + Public methods: + setLayer() L.LayerGroup() set layer search at runtime + showAlert() 'Text message' show alert message + searchText() 'Text searched' search text by external code +*/ + +//TODO implement can do research on multiple sources layers and remote +//TODO history: false, //show latest searches in tooltip +//FIXME option condition problem {autoCollapse: true, markerLocation: true} not show location +//FIXME option condition problem {autoCollapse: false } +// +//TODO here insert function search inputText FIRST in _recordsCache keys and if not find results.. +// run one of callbacks search(sourceData,jsonpUrl or options.layer) and run this.showTooltip +// +//TODO change structure of _recordsCache +// like this: _recordsCache = {"text-key1": {loc:[lat,lng], ..other attributes.. }, {"text-key2": {loc:[lat,lng]}...}, ...} +// in this mode every record can have a free structure of attributes, only 'loc' is required +//TODO important optimization!!! always append data in this._recordsCache +// now _recordsCache content is emptied and replaced with new data founded +// always appending data on _recordsCache give the possibility of caching ajax, jsonp and layersearch! +// +//TODO here insert function search inputText FIRST in _recordsCache keys and if not find results.. +// run one of callbacks search(sourceData,jsonpUrl or options.layer) and run this.showTooltip +// +//TODO change structure of _recordsCache +// like this: _recordsCache = {"text-key1": {loc:[lat,lng], ..other attributes.. }, {"text-key2": {loc:[lat,lng]}...}, ...} +// in this way every record can have a free structure of attributes, only 'loc' is required + +(function (factory) { + if(typeof define === 'function' && define.amd) { + //AMD + define(['leaflet'], factory); + } else if(typeof module !== 'undefined') { + // Node/CommonJS + module.exports = factory(require('leaflet')); + } else { + // Browser globals + if(typeof window.L === 'undefined') + throw 'Leaflet must be loaded first'; + factory(window.L); + } +})(function (L) { + + +L.Control.Search = L.Control.extend({ + + includes: L.version[0]==='1' ? L.Evented.prototype : L.Mixin.Events, + + options: { + url: '', //url for search by ajax request, ex: "search.php?q={s}". Can be function to returns string for dynamic parameter setting + layer: null, //layer where search markers(is a L.LayerGroup) + sourceData: null, //function to fill _recordsCache, passed searching text by first param and callback in second + //TODO implements uniq option 'sourceData' to recognizes source type: url,array,callback or layer + jsonpParam: null, //jsonp param name for search by jsonp service, ex: "callback" + propertyLoc: 'loc', //field for remapping location, using array: ['latname','lonname'] for select double fields(ex. ['lat','lon'] ) support dotted format: 'prop.subprop.title' + propertyName: 'title', //property in marker.options(or feature.properties for vector layer) trough filter elements in layer, + formatData: null, //callback for reformat all data from source to indexed data object + filterData: null, //callback for filtering data from text searched, params: textSearch, allRecords + moveToLocation: null, //callback run on location found, params: latlng, title, map + buildTip: null, //function to return row tip html node(or html string), receive text tooltip in first param + container: '', //container id to insert Search Control + zoom: null, //default zoom level for move to location + minLength: 1, //minimal text length for autocomplete + initial: true, //search elements only by initial text + casesensitive: false, //search elements in case sensitive text + autoType: true, //complete input with first suggested result and select this filled-in text. + delayType: 400, //delay while typing for show tooltip + tooltipLimit: -1, //limit max results to show in tooltip. -1 for no limit, 0 for no results + tipAutoSubmit: true, //auto map panTo when click on tooltip + firstTipSubmit: false, //auto select first result con enter click + autoResize: true, //autoresize on input change + collapsed: true, //collapse search control at startup + autoCollapse: false, //collapse search control after submit(on button or on tips if enabled tipAutoSubmit) + autoCollapseTime: 1200, //delay for autoclosing alert and collapse after blur + textErr: 'Location not found', //error message + textCancel: 'Cancel', //title in cancel button + textPlaceholder: 'Search...', //placeholder value + hideMarkerOnCollapse: false, //remove circle and marker on search control collapsed + position: 'topleft', + marker: { //custom L.Marker or false for hide + icon: false, //custom L.Icon for maker location or false for hide + animate: true, //animate a circle over location found + circle: { //draw a circle in location found + radius: 10, + weight: 3, + color: '#e03', + stroke: true, + fill: false + } + } + }, + + _getPath: function(obj, prop) { + var parts = prop.split('.'), + last = parts.pop(), + len = parts.length, + cur = parts[0], + i = 1; + + if(len > 0) + while((obj = obj[cur]) && i < len) + cur = parts[i++]; + + if(obj) + return obj[last]; + }, + + _isObject: function(obj) { + return Object.prototype.toString.call(obj) === "[object Object]"; + }, + + initialize: function(options) { + L.Util.setOptions(this, options || {}); + this._inputMinSize = this.options.textPlaceholder ? this.options.textPlaceholder.length : 10; + this._layer = this.options.layer || new L.LayerGroup(); + this._filterData = this.options.filterData || this._defaultFilterData; + this._formatData = this.options.formatData || this._defaultFormatData; + this._moveToLocation = this.options.moveToLocation || this._defaultMoveToLocation; + this._autoTypeTmp = this.options.autoType; //useful for disable autoType temporarily in delete/backspace keydown + this._countertips = 0; //number of tips items + this._recordsCache = {}; //key,value table! to store locations! format: key,latlng + this._curReq = null; + }, + + onAdd: function (map) { + this._map = map; + this._container = L.DomUtil.create('div', 'leaflet-control-search'); + this._input = this._createInput(this.options.textPlaceholder, 'search-input'); + this._tooltip = this._createTooltip('search-tooltip'); + this._cancel = this._createCancel(this.options.textCancel, 'search-cancel'); + this._button = this._createButton(this.options.textPlaceholder, 'search-button'); + this._alert = this._createAlert('search-alert'); + + if(this.options.collapsed===false) + this.expand(this.options.collapsed); + + if(this.options.marker) { + + if(this.options.marker instanceof L.Marker || this.options.marker instanceof L.CircleMarker) + this._markerSearch = this.options.marker; + + else if(this._isObject(this.options.marker)) + this._markerSearch = new L.Control.Search.Marker([0,0], this.options.marker); + + this._markerSearch._isMarkerSearch = true; + } + + this.setLayer( this._layer ); + + map.on({ + // 'layeradd': this._onLayerAddRemove, + // 'layerremove': this._onLayerAddRemove + 'resize': this._handleAutoresize + }, this); + return this._container; + }, + addTo: function (map) { + + if(this.options.container) { + this._container = this.onAdd(map); + this._wrapper = L.DomUtil.get(this.options.container); + this._wrapper.style.position = 'relative'; + this._wrapper.appendChild(this._container); + } + else + L.Control.prototype.addTo.call(this, map); + + return this; + }, + + onRemove: function(map) { + this._recordsCache = {}; + // map.off({ + // 'layeradd': this._onLayerAddRemove, + // 'layerremove': this._onLayerAddRemove + // }, this); + map.off({ + // 'layeradd': this._onLayerAddRemove, + // 'layerremove': this._onLayerAddRemove + 'resize': this._handleAutoresize + }, this); + }, + + // _onLayerAddRemove: function(e) { + // //without this, run setLayer also for each Markers!! to optimize! + // if(e.layer instanceof L.LayerGroup) + // if( L.stamp(e.layer) != L.stamp(this._layer) ) + // this.setLayer(e.layer); + // }, + + setLayer: function(layer) { //set search layer at runtime + //this.options.layer = layer; //setting this, run only this._recordsFromLayer() + this._layer = layer; + this._layer.addTo(this._map); + return this; + }, + + showAlert: function(text) { + var self = this; + text = text || this.options.textErr; + this._alert.style.display = 'block'; + this._alert.innerHTML = text; + clearTimeout(this.timerAlert); + + this.timerAlert = setTimeout(function() { + self.hideAlert(); + },this.options.autoCollapseTime); + return this; + }, + + hideAlert: function() { + this._alert.style.display = 'none'; + return this; + }, + + cancel: function() { + this._input.value = ''; + this._handleKeypress({ keyCode: 8 });//simulate backspace keypress + this._input.size = this._inputMinSize; + this._input.focus(); + this._cancel.style.display = 'none'; + this._hideTooltip(); + this.fire('search:cancel'); + return this; + }, + + expand: function(toggle) { + toggle = typeof toggle === 'boolean' ? toggle : true; + this._input.style.display = 'block'; + L.DomUtil.addClass(this._container, 'search-exp'); + if ( toggle !== false ) { + this._input.focus(); + this._map.on('dragstart click', this.collapse, this); + } + this.fire('search:expanded'); + return this; + }, + + collapse: function() { + this._hideTooltip(); + this.cancel(); + this._alert.style.display = 'none'; + this._input.blur(); + if(this.options.collapsed) + { + this._input.style.display = 'none'; + this._cancel.style.display = 'none'; + L.DomUtil.removeClass(this._container, 'search-exp'); + if (this.options.hideMarkerOnCollapse) { + this._map.removeLayer(this._markerSearch); + } + this._map.off('dragstart click', this.collapse, this); + } + this.fire('search:collapsed'); + return this; + }, + + collapseDelayed: function() { //collapse after delay, used on_input blur + var self = this; + if (!this.options.autoCollapse) return this; + clearTimeout(this.timerCollapse); + this.timerCollapse = setTimeout(function() { + self.collapse(); + }, this.options.autoCollapseTime); + return this; + }, + + collapseDelayedStop: function() { + clearTimeout(this.timerCollapse); + return this; + }, + + ////start DOM creations + _createAlert: function(className) { + var alert = L.DomUtil.create('div', className, this._container); + alert.style.display = 'none'; + + L.DomEvent + .on(alert, 'click', L.DomEvent.stop, this) + .on(alert, 'click', this.hideAlert, this); + + return alert; + }, + + _createInput: function (text, className) { + var self = this; + var label = L.DomUtil.create('label', className, this._container); + var input = L.DomUtil.create('input', className, this._container); + input.type = 'text'; + input.size = this._inputMinSize; + input.value = ''; + input.autocomplete = 'off'; + input.autocorrect = 'off'; + input.autocapitalize = 'off'; + input.placeholder = text; + input.style.display = 'none'; + input.role = 'search'; + input.id = input.role + input.type + input.size; + + label.htmlFor = input.id; + label.style.display = 'none'; + label.value = text; + + L.DomEvent + .disableClickPropagation(input) + .on(input, 'keyup', this._handleKeypress, this) + .on(input, 'paste', function(e) { + setTimeout(function(e) { + self._handleKeypress(e); + },10,e); + }, this) + .on(input, 'blur', this.collapseDelayed, this) + .on(input, 'focus', this.collapseDelayedStop, this); + + return input; + }, + + _createCancel: function (title, className) { + var cancel = L.DomUtil.create('a', className, this._container); + cancel.href = '#'; + cancel.title = title; + cancel.style.display = 'none'; + cancel.innerHTML = "";//imageless(see css) + + L.DomEvent + .on(cancel, 'click', L.DomEvent.stop, this) + .on(cancel, 'click', this.cancel, this); + + return cancel; + }, + + _createButton: function (title, className) { + var button = L.DomUtil.create('a', className, this._container); + button.href = '#'; + button.title = title; + + L.DomEvent + .on(button, 'click', L.DomEvent.stop, this) + .on(button, 'click', this._handleSubmit, this) + .on(button, 'focus', this.collapseDelayedStop, this) + .on(button, 'blur', this.collapseDelayed, this); + + return button; + }, + + _createTooltip: function(className) { + var self = this; + var tool = L.DomUtil.create('ul', className, this._container); + tool.style.display = 'none'; + L.DomEvent + .disableClickPropagation(tool) + .on(tool, 'blur', this.collapseDelayed, this) + .on(tool, 'mousewheel', function(e) { + self.collapseDelayedStop(); + L.DomEvent.stopPropagation(e);//disable zoom map + }, this) + .on(tool, 'mouseover', function(e) { + self.collapseDelayedStop(); + }, this); + return tool; + }, + + _createTip: function(text, val) {//val is object in recordCache, usually is Latlng + var tip; + + if(this.options.buildTip) + { + tip = this.options.buildTip.call(this, text, val); //custom tip node or html string + if(typeof tip === 'string') + { + var tmpNode = L.DomUtil.create('div'); + tmpNode.innerHTML = tip; + tip = tmpNode.firstChild; + } + } + else + { + tip = L.DomUtil.create('li', ''); + tip.innerHTML = text; + } + + L.DomUtil.addClass(tip, 'search-tip'); + tip._text = text; //value replaced in this._input and used by _autoType + + if(this.options.tipAutoSubmit) + L.DomEvent + .disableClickPropagation(tip) + .on(tip, 'click', L.DomEvent.stop, this) + .on(tip, 'click', function(e) { + this._input.value = text; + this._handleAutoresize(); + this._input.focus(); + this._hideTooltip(); + this._handleSubmit(); + }, this); + + return tip; + }, + + //////end DOM creations + + _getUrl: function(text) { + return (typeof this.options.url === 'function') ? this.options.url(text) : this.options.url; + }, + + _defaultFilterData: function(text, records) { + + var I, icase, regSearch, frecords = {}; + + text = text.replace(/[.*+?^${}()|[\]\\]/g, ''); //sanitize remove all special characters + if(text==='') + return []; + + I = this.options.initial ? '^' : ''; //search only initial text + icase = !this.options.casesensitive ? 'i' : undefined; + + regSearch = new RegExp(I + text, icase); + + //TODO use .filter or .map + for(var key in records) { + if( regSearch.test(key) ) + frecords[key]= records[key]; + } + + return frecords; + }, + + showTooltip: function(records) { + + + this._countertips = 0; + this._tooltip.innerHTML = ''; + this._tooltip.currentSelection = -1; //inizialized for _handleArrowSelect() + + if(this.options.tooltipLimit) + { + for(var key in records)//fill tooltip + { + if(this._countertips === this.options.tooltipLimit) + break; + + this._countertips++; + + this._tooltip.appendChild( this._createTip(key, records[key]) ); + } + } + + if(this._countertips > 0) + { + this._tooltip.style.display = 'block'; + + if(this._autoTypeTmp) + this._autoType(); + + this._autoTypeTmp = this.options.autoType;//reset default value + } + else + this._hideTooltip(); + + this._tooltip.scrollTop = 0; + + return this._countertips; + }, + + _hideTooltip: function() { + this._tooltip.style.display = 'none'; + this._tooltip.innerHTML = ''; + return 0; + }, + + _defaultFormatData: function(json) { //default callback for format data to indexed data + var self = this, + propName = this.options.propertyName, + propLoc = this.options.propertyLoc, + i, jsonret = {}; + + if( L.Util.isArray(propLoc) ) + for(i in json) + jsonret[ self._getPath(json[i],propName) ]= L.latLng( json[i][ propLoc[0] ], json[i][ propLoc[1] ] ); + else + for(i in json) + jsonret[ self._getPath(json[i],propName) ]= L.latLng( self._getPath(json[i],propLoc) ); + //TODO throw new Error("propertyName '"+propName+"' not found in JSON data"); + return jsonret; + }, + + _recordsFromJsonp: function(text, callAfter) { //extract searched records from remote jsonp service + L.Control.Search.callJsonp = callAfter; + var script = L.DomUtil.create('script','leaflet-search-jsonp', document.getElementsByTagName('body')[0] ), + url = L.Util.template(this._getUrl(text)+'&'+this.options.jsonpParam+'=L.Control.Search.callJsonp', {s: text}); //parsing url + //rnd = '&_='+Math.floor(Math.random()*10000); + //TODO add rnd param or randomize callback name! in recordsFromJsonp + script.type = 'text/javascript'; + script.src = url; + return { abort: function() { script.parentNode.removeChild(script); } }; + }, + + _recordsFromAjax: function(text, callAfter) { //Ajax request + if (window.XMLHttpRequest === undefined) { + window.XMLHttpRequest = function() { + try { return new ActiveXObject("Microsoft.XMLHTTP.6.0"); } + catch (e1) { + try { return new ActiveXObject("Microsoft.XMLHTTP.3.0"); } + catch (e2) { throw new Error("XMLHttpRequest is not supported"); } + } + }; + } + var IE8or9 = ( L.Browser.ie && !window.atob && document.querySelector ), + request = IE8or9 ? new XDomainRequest() : new XMLHttpRequest(), + url = L.Util.template(this._getUrl(text), {s: text}); + + //rnd = '&_='+Math.floor(Math.random()*10000); + //TODO add rnd param or randomize callback name! in recordsFromAjax + + request.open("GET", url); + + + request.onload = function() { + callAfter( JSON.parse(request.responseText) ); + }; + request.onreadystatechange = function() { + if(request.readyState === 4 && request.status === 200) { + this.onload(); + } + }; + + request.send(); + return request; + }, + + _searchInLayer: function(layer, retRecords, propName) { + var self = this, loc; + + if(layer instanceof L.Control.Search.Marker) return; + + if(layer instanceof L.Marker || layer instanceof L.CircleMarker) + { + if(self._getPath(layer.options,propName)) + { + loc = layer.getLatLng(); + loc.layer = layer; + retRecords[ self._getPath(layer.options,propName) ] = loc; + } + else if(self._getPath(layer.feature.properties,propName)) + { + loc = layer.getLatLng(); + loc.layer = layer; + retRecords[ self._getPath(layer.feature.properties,propName) ] = loc; + } + else { + //throw new Error("propertyName '"+propName+"' not found in marker"); + console.warn("propertyName '"+propName+"' not found in marker"); + } + } + else if(layer instanceof L.Path || layer instanceof L.Polyline || layer instanceof L.Polygon) + { + if(self._getPath(layer.options,propName)) + { + loc = layer.getBounds().getCenter(); + loc.layer = layer; + retRecords[ self._getPath(layer.options,propName) ] = loc; + } + else if(self._getPath(layer.feature.properties,propName)) + { + loc = layer.getBounds().getCenter(); + loc.layer = layer; + retRecords[ self._getPath(layer.feature.properties,propName) ] = loc; + } + else { + //throw new Error("propertyName '"+propName+"' not found in shape"); + console.warn("propertyName '"+propName+"' not found in shape"); + } + } + else if(layer.hasOwnProperty('feature'))//GeoJSON + { + if(layer.feature.properties.hasOwnProperty(propName)) + { + if(layer.getLatLng && typeof layer.getLatLng === 'function') { + loc = layer.getLatLng(); + loc.layer = layer; + retRecords[ layer.feature.properties[propName] ] = loc; + } else if(layer.getBounds && typeof layer.getBounds === 'function') { + loc = layer.getBounds().getCenter(); + loc.layer = layer; + retRecords[ layer.feature.properties[propName] ] = loc; + } else { + console.warn("Unknown type of Layer"); + } + } + else { + //throw new Error("propertyName '"+propName+"' not found in feature"); + console.warn("propertyName '"+propName+"' not found in feature"); + } + } + else if(layer instanceof L.LayerGroup) + { + layer.eachLayer(function (layer) { + self._searchInLayer(layer, retRecords, propName); + }); + } + }, + + _recordsFromLayer: function() { //return table: key,value from layer + var self = this, + retRecords = {}, + propName = this.options.propertyName; + + this._layer.eachLayer(function (layer) { + self._searchInLayer(layer, retRecords, propName); + }); + + return retRecords; + }, + + _autoType: function() { + + //TODO implements autype without selection(useful for mobile device) + + var start = this._input.value.length, + firstRecord = this._tooltip.firstChild ? this._tooltip.firstChild._text : '', + end = firstRecord.length; + + if (firstRecord.indexOf(this._input.value) === 0) { // If prefix match + this._input.value = firstRecord; + this._handleAutoresize(); + + if (this._input.createTextRange) { + var selRange = this._input.createTextRange(); + selRange.collapse(true); + selRange.moveStart('character', start); + selRange.moveEnd('character', end); + selRange.select(); + } + else if(this._input.setSelectionRange) { + this._input.setSelectionRange(start, end); + } + else if(this._input.selectionStart) { + this._input.selectionStart = start; + this._input.selectionEnd = end; + } + } + }, + + _hideAutoType: function() { // deselect text: + + var sel; + if ((sel = this._input.selection) && sel.empty) { + sel.empty(); + } + else if (this._input.createTextRange) { + sel = this._input.createTextRange(); + sel.collapse(true); + var end = this._input.value.length; + sel.moveStart('character', end); + sel.moveEnd('character', end); + sel.select(); + } + else { + if (this._input.getSelection) { + this._input.getSelection().removeAllRanges(); + } + this._input.selectionStart = this._input.selectionEnd; + } + }, + + _handleKeypress: function (e) { //run _input keyup event + var self = this; + + switch(e.keyCode) + { + case 27://Esc + this.collapse(); + break; + case 13://Enter + if(this._countertips == 1 || (this.options.firstTipSubmit && this._countertips > 0)) { + if(this._tooltip.currentSelection == -1) { + this._handleArrowSelect(1); + } + } + this._handleSubmit(); //do search + break; + case 38://Up + this._handleArrowSelect(-1); + break; + case 40://Down + this._handleArrowSelect(1); + break; + case 8://Backspace + case 45://Insert + case 46://Delete + this._autoTypeTmp = false;//disable temporarily autoType + break; + case 37://Left + case 39://Right + case 16://Shift + case 17://Ctrl + case 35://End + case 36://Home + break; + default://All keys + if(this._input.value.length) + this._cancel.style.display = 'block'; + else + this._cancel.style.display = 'none'; + + if(this._input.value.length >= this.options.minLength) + { + clearTimeout(this.timerKeypress); //cancel last search request while type in + this.timerKeypress = setTimeout(function() { //delay before request, for limit jsonp/ajax request + + self._fillRecordsCache(); + + }, this.options.delayType); + } + else + this._hideTooltip(); + } + + this._handleAutoresize(); + }, + + searchText: function(text) { + var code = text.charCodeAt(text.length); + + this._input.value = text; + + this._input.style.display = 'block'; + L.DomUtil.addClass(this._container, 'search-exp'); + + this._autoTypeTmp = false; + + this._handleKeypress({keyCode: code}); + }, + + _fillRecordsCache: function() { + + var self = this, + inputText = this._input.value, records; + + if(this._curReq && this._curReq.abort) + this._curReq.abort(); + //abort previous requests + + L.DomUtil.addClass(this._container, 'search-load'); + + if(this.options.layer) + { + //TODO _recordsFromLayer must return array of objects, formatted from _formatData + this._recordsCache = this._recordsFromLayer(); + + records = this._filterData( this._input.value, this._recordsCache ); + + this.showTooltip( records ); + + L.DomUtil.removeClass(this._container, 'search-load'); + } + else + { + if(this.options.sourceData) + this._retrieveData = this.options.sourceData; + + else if(this.options.url) //jsonp or ajax + this._retrieveData = this.options.jsonpParam ? this._recordsFromJsonp : this._recordsFromAjax; + + this._curReq = this._retrieveData.call(this, inputText, function(data) { + + self._recordsCache = self._formatData.call(self, data); + + //TODO refact! + if(self.options.sourceData) + records = self._filterData( self._input.value, self._recordsCache ); + else + records = self._recordsCache; + + self.showTooltip( records ); + + L.DomUtil.removeClass(self._container, 'search-load'); + }); + } + }, + + _handleAutoresize: function() { + var maxWidth; + + if (this._input.style.maxWidth !== this._map._container.offsetWidth) { + maxWidth = this._map._container.clientWidth; + + // other side margin + padding + width border + width search-button + width search-cancel + maxWidth -= 10 + 20 + 1 + 30 + 22; + + this._input.style.maxWidth = maxWidth.toString() + 'px'; + } + + if (this.options.autoResize && (this._container.offsetWidth + 20 < this._map._container.offsetWidth)) { + this._input.size = this._input.value.length < this._inputMinSize ? this._inputMinSize : this._input.value.length; + } + }, + + _handleArrowSelect: function(velocity) { + + var searchTips = this._tooltip.hasChildNodes() ? this._tooltip.childNodes : []; + + for (i=0; i= (searchTips.length - 1))) {// If at end of list. + L.DomUtil.addClass(searchTips[this._tooltip.currentSelection], 'search-tip-select'); + } + else if ((velocity == -1 ) && (this._tooltip.currentSelection <= 0)) { // Going back up to the search box. + this._tooltip.currentSelection = -1; + } + else if (this._tooltip.style.display != 'none') { + this._tooltip.currentSelection += velocity; + + L.DomUtil.addClass(searchTips[this._tooltip.currentSelection], 'search-tip-select'); + + this._input.value = searchTips[this._tooltip.currentSelection]._text; + + // scroll: + var tipOffsetTop = searchTips[this._tooltip.currentSelection].offsetTop; + + if (tipOffsetTop + searchTips[this._tooltip.currentSelection].clientHeight >= this._tooltip.scrollTop + this._tooltip.clientHeight) { + this._tooltip.scrollTop = tipOffsetTop - this._tooltip.clientHeight + searchTips[this._tooltip.currentSelection].clientHeight; + } + else if (tipOffsetTop <= this._tooltip.scrollTop) { + this._tooltip.scrollTop = tipOffsetTop; + } + } + }, + + _handleSubmit: function() { //button and tooltip click and enter submit + + this._hideAutoType(); + + this.hideAlert(); + this._hideTooltip(); + + if(this._input.style.display == 'none') //on first click show _input only + this.expand(); + else + { + if(this._input.value === '') //hide _input only + this.collapse(); + else + { + var loc = this._getLocation(this._input.value); + + if(loc===false) + this.showAlert(); + else + { + this.showLocation(loc, this._input.value); + this.fire('search:locationfound', { + latlng: loc, + text: this._input.value, + layer: loc.layer ? loc.layer : null + }); + } + } + } + }, + + _getLocation: function(key) { //extract latlng from _recordsCache + + if( this._recordsCache.hasOwnProperty(key) ) + return this._recordsCache[key];//then after use .loc attribute + else + return false; + }, + + _defaultMoveToLocation: function(latlng, title, map) { + if(this.options.zoom) + this._map.setView(latlng, this.options.zoom); + else + this._map.panTo(latlng); + }, + + showLocation: function(latlng, title) { //set location on map from _recordsCache + var self = this; + + self._map.once('moveend zoomend', function(e) { + + if(self._markerSearch) { + self._markerSearch.addTo(self._map).setLatLng(latlng); + } + + }); + + self._moveToLocation(latlng, title, self._map); + //FIXME autoCollapse option hide self._markerSearch before visualized!! + if(self.options.autoCollapse) + self.collapse(); + + return self; + } +}); + +L.Control.Search.Marker = L.Marker.extend({ + + includes: L.version[0]==='1' ? L.Evented.prototype : L.Mixin.Events, + + options: { + icon: new L.Icon.Default(), + animate: true, + circle: { + radius: 10, + weight: 3, + color: '#e03', + stroke: true, + fill: false + } + }, + + initialize: function (latlng, options) { + L.setOptions(this, options); + + if(options.icon === true) + options.icon = new L.Icon.Default(); + + L.Marker.prototype.initialize.call(this, latlng, options); + + if( L.Control.Search.prototype._isObject(this.options.circle) ) + this._circleLoc = new L.CircleMarker(latlng, this.options.circle); + }, + + onAdd: function (map) { + L.Marker.prototype.onAdd.call(this, map); + if(this._circleLoc) { + map.addLayer(this._circleLoc); + if(this.options.animate) + this.animate(); + } + }, + + onRemove: function (map) { + L.Marker.prototype.onRemove.call(this, map); + if(this._circleLoc) + map.removeLayer(this._circleLoc); + }, + + setLatLng: function (latlng) { + L.Marker.prototype.setLatLng.call(this, latlng); + if(this._circleLoc) + this._circleLoc.setLatLng(latlng); + return this; + }, + + _initIcon: function () { + if(this.options.icon) + L.Marker.prototype._initIcon.call(this); + }, + + _removeIcon: function () { + if(this.options.icon) + L.Marker.prototype._removeIcon.call(this); + }, + + animate: function() { + //TODO refact animate() more smooth! like this: http://goo.gl/DDlRs + if(this._circleLoc) + { + var circle = this._circleLoc, + tInt = 200, //time interval + ss = 5, //frames + mr = parseInt(circle._radius/ss), + oldrad = this.options.circle.radius, + newrad = circle._radius * 2, + acc = 0; + + circle._timerAnimLoc = setInterval(function() { + acc += 0.5; + mr += acc; //adding acceleration + newrad -= mr; + + circle.setRadius(newrad); + + if(newrad]+)>)/ig,"")};var m={_init:function(b,d){var c=this;this.settings=a.extend({},a.fn.multi_select.defaults,d);this.$el=a(b);this.selectedValues=[];this.basicClass="multi-button";this.selectColors="green blue aqua red yellow maroon purple".split(" ");var e=this.settings;a(b).each(function(){a(this).css({position:"relative",width:e.buttonWidth});$wrapper=c._styleElement(a(this));$list=c._createList(a(this));a(this).append($list); +a(this).data("list",$list);c._addEvents(this);c._setSelected()})},init:function(){this._init.call(this,this.$el,this.settings)},_createList:function(b){var d=this,c=d.settings,e=this.getData(),g=c.selectedIndexes;c=c.listMaxHeight;var h={};c&&(h={"overflow-x":"hidden","overflow-y":"auto",display:"none","max-height":c});var f=a("