Justin
4 years ago
commit
ef047f049f
32 changed files with 12167 additions and 0 deletions
@ -0,0 +1,14 @@ |
|||||||
|
{ |
||||||
|
"presets": [ |
||||||
|
[ |
||||||
|
"@babel/env", |
||||||
|
{ |
||||||
|
"targets": { |
||||||
|
"browsers": "> 1%" |
||||||
|
}, |
||||||
|
"corejs": "3.6", |
||||||
|
"useBuiltIns": "usage" |
||||||
|
} |
||||||
|
] |
||||||
|
] |
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
{ |
||||||
|
"extends": ["eslint:recommended", "plugin:prettier/recommended", "plugin:@typescript-eslint/recommended"], |
||||||
|
"parser": "@typescript-eslint/parser", |
||||||
|
"parserOptions": { |
||||||
|
"ecmaVersion": 11, |
||||||
|
"sourceType": "module" |
||||||
|
}, |
||||||
|
"plugins": ["@typescript-eslint", "jest"], |
||||||
|
"rules": { |
||||||
|
"no-var": 2, |
||||||
|
"prefer-arrow-callback": 2, |
||||||
|
"@typescript-eslint/ban-ts-comment": 0, |
||||||
|
"@typescript-eslint/no-empty-function": 1 |
||||||
|
}, |
||||||
|
"env": { |
||||||
|
"browser": true, |
||||||
|
"es6": true, |
||||||
|
"jest/globals": true |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
# Copyright 2020 Google LLC |
||||||
|
# |
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
# you may not use this file except in compliance with the License. |
||||||
|
# You may obtain a copy of the License at |
||||||
|
# |
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
# |
||||||
|
# Unless required by applicable law or agreed to in writing, software |
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
# See the License for the specific language governing permissions and |
||||||
|
# limitations under the License. |
||||||
|
|
||||||
|
# https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners |
||||||
|
|
||||||
|
.github/ @googlemaps/dpe |
@ -0,0 +1,20 @@ |
|||||||
|
# Copyright 2020 Google LLC |
||||||
|
# |
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
# you may not use this file except in compliance with the License. |
||||||
|
# You may obtain a copy of the License at |
||||||
|
# |
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
# |
||||||
|
# Unless required by applicable law or agreed to in writing, software |
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
# See the License for the specific language governing permissions and |
||||||
|
# limitations under the License. |
||||||
|
|
||||||
|
version: 2 |
||||||
|
updates: |
||||||
|
- package-ecosystem: "npm" |
||||||
|
directory: "/" |
||||||
|
schedule: |
||||||
|
interval: "weekly" |
@ -0,0 +1,25 @@ |
|||||||
|
# Copyright 2020 Google LLC |
||||||
|
# |
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
# you may not use this file except in compliance with the License. |
||||||
|
# You may obtain a copy of the License at |
||||||
|
# |
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
# |
||||||
|
# Unless required by applicable law or agreed to in writing, software |
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
# See the License for the specific language governing permissions and |
||||||
|
# limitations under the License. |
||||||
|
|
||||||
|
name: Build |
||||||
|
on: [push, pull_request] |
||||||
|
jobs: |
||||||
|
test: |
||||||
|
runs-on: ubuntu-latest |
||||||
|
steps: |
||||||
|
- uses: actions/checkout@v2 |
||||||
|
- run: npm i |
||||||
|
- run: npm run lint |
||||||
|
- run: npm test |
||||||
|
- uses: codecov/codecov-action@v1 |
@ -0,0 +1,51 @@ |
|||||||
|
# Copyright 2020 Google LLC |
||||||
|
# |
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
# you may not use this file except in compliance with the License. |
||||||
|
# You may obtain a copy of the License at |
||||||
|
# |
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
# |
||||||
|
# Unless required by applicable law or agreed to in writing, software |
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
# See the License for the specific language governing permissions and |
||||||
|
# limitations under the License. |
||||||
|
|
||||||
|
name: e2e |
||||||
|
on: |
||||||
|
push: |
||||||
|
schedule: |
||||||
|
- cron: "0 12 * * *" |
||||||
|
jobs: |
||||||
|
chrome: |
||||||
|
runs-on: ubuntu-latest |
||||||
|
services: |
||||||
|
hub: |
||||||
|
image: selenium/standalone-chrome |
||||||
|
volumes: |
||||||
|
- ${{ github.workspace }}:${{ github.workspace }} |
||||||
|
ports: |
||||||
|
- 4444:4444 |
||||||
|
steps: |
||||||
|
- uses: actions/checkout@v2 |
||||||
|
- run: npm i |
||||||
|
- run: npm run test:e2e |
||||||
|
env: |
||||||
|
GOOGLE_MAPS_API_KEY: ${{ secrets.SYNCED_GOOGLE_MAPS_API_KEY_WEB }} |
||||||
|
firefox: |
||||||
|
runs-on: ubuntu-latest |
||||||
|
services: |
||||||
|
hub: |
||||||
|
image: selenium/standalone-firefox |
||||||
|
volumes: |
||||||
|
- ${{ github.workspace }}:${{ github.workspace }} |
||||||
|
ports: |
||||||
|
- 4444:4444 |
||||||
|
steps: |
||||||
|
- uses: actions/checkout@v2 |
||||||
|
- run: npm i |
||||||
|
- run: npm run test:e2e |
||||||
|
env: |
||||||
|
GOOGLE_MAPS_API_KEY: ${{ secrets.SYNCED_GOOGLE_MAPS_API_KEY_WEB }} |
||||||
|
BROWSER: firefox |
@ -0,0 +1,53 @@ |
|||||||
|
# Copyright 2020 Google LLC |
||||||
|
# |
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
# you may not use this file except in compliance with the License. |
||||||
|
# You may obtain a copy of the License at |
||||||
|
# |
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
# |
||||||
|
# Unless required by applicable law or agreed to in writing, software |
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
# See the License for the specific language governing permissions and |
||||||
|
# limitations under the License. |
||||||
|
|
||||||
|
name: "Release" |
||||||
|
on: |
||||||
|
push: |
||||||
|
branches: |
||||||
|
- main |
||||||
|
jobs: |
||||||
|
build: |
||||||
|
runs-on: ubuntu-latest |
||||||
|
steps: |
||||||
|
- uses: actions/checkout@v2 |
||||||
|
- name: Test |
||||||
|
run: | |
||||||
|
npm i |
||||||
|
npm test |
||||||
|
- name: Release |
||||||
|
uses: cycjimmy/semantic-release-action@v2 |
||||||
|
with: |
||||||
|
extra_plugins: | |
||||||
|
"@semantic-release/commit-analyzer" |
||||||
|
"@semantic-release/release-notes-generator" |
||||||
|
"@semantic-release/git |
||||||
|
"@semantic-release/github |
||||||
|
"@semantic-release/npm |
||||||
|
env: |
||||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
||||||
|
NPM_TOKEN: ${{ secrets.NPM_WOMBAT_TOKEN }} |
||||||
|
- run: | |
||||||
|
npm i |
||||||
|
npm run docs |
||||||
|
cp -r dist docs/dist |
||||||
|
cp -r examples docs/examples |
||||||
|
cp -r images docs/images |
||||||
|
- uses: peaceiris/actions-gh-pages@v3 |
||||||
|
with: |
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }} |
||||||
|
publish_dir: ./docs |
||||||
|
user_name: 'googlemaps-bot' |
||||||
|
user_email: 'googlemaps-bot@users.noreply.github.com' |
||||||
|
commit_message: ${{ github.event.head_commit.message }} |
@ -0,0 +1,228 @@ |
|||||||
|
node_modules |
||||||
|
dist/ |
||||||
|
.npmrc |
||||||
|
**/docs |
||||||
|
|
||||||
|
# Logs |
||||||
|
logs |
||||||
|
*.log |
||||||
|
npm-debug.log* |
||||||
|
yarn-debug.log* |
||||||
|
yarn-error.log* |
||||||
|
lerna-debug.log* |
||||||
|
|
||||||
|
# Diagnostic reports (https://nodejs.org/api/report.html) |
||||||
|
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json |
||||||
|
|
||||||
|
# Runtime data |
||||||
|
pids |
||||||
|
*.pid |
||||||
|
*.seed |
||||||
|
*.pid.lock |
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover |
||||||
|
lib-cov |
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul |
||||||
|
coverage |
||||||
|
*.lcov |
||||||
|
|
||||||
|
# nyc test coverage |
||||||
|
.nyc_output |
||||||
|
|
||||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) |
||||||
|
.grunt |
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/) |
||||||
|
bower_components |
||||||
|
|
||||||
|
# node-waf configuration |
||||||
|
.lock-wscript |
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html) |
||||||
|
build/Release |
||||||
|
|
||||||
|
# Dependency directories |
||||||
|
node_modules/ |
||||||
|
jspm_packages/ |
||||||
|
|
||||||
|
# TypeScript v1 declaration files |
||||||
|
typings/ |
||||||
|
|
||||||
|
# TypeScript cache |
||||||
|
*.tsbuildinfo |
||||||
|
|
||||||
|
# Optional npm cache directory |
||||||
|
.npm |
||||||
|
|
||||||
|
# Optional eslint cache |
||||||
|
.eslintcache |
||||||
|
|
||||||
|
# Microbundle cache |
||||||
|
.rpt2_cache/ |
||||||
|
.rts2_cache_cjs/ |
||||||
|
.rts2_cache_es/ |
||||||
|
.rts2_cache_umd/ |
||||||
|
|
||||||
|
# Optional REPL history |
||||||
|
.node_repl_history |
||||||
|
|
||||||
|
# Output of 'npm pack' |
||||||
|
*.tgz |
||||||
|
|
||||||
|
# Yarn Integrity file |
||||||
|
.yarn-integrity |
||||||
|
|
||||||
|
# dotenv environment variables file |
||||||
|
.env |
||||||
|
.env.test |
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/) |
||||||
|
.cache |
||||||
|
|
||||||
|
# next.js build output |
||||||
|
.next |
||||||
|
|
||||||
|
# nuxt.js build output |
||||||
|
.nuxt |
||||||
|
|
||||||
|
# gatsby files |
||||||
|
.cache/ |
||||||
|
public |
||||||
|
|
||||||
|
# vuepress build output |
||||||
|
.vuepress/dist |
||||||
|
|
||||||
|
# Serverless directories |
||||||
|
.serverless/ |
||||||
|
|
||||||
|
# FuseBox cache |
||||||
|
.fusebox/ |
||||||
|
|
||||||
|
# DynamoDB Local files |
||||||
|
.dynamodb/ |
||||||
|
|
||||||
|
# TernJS port file |
||||||
|
.tern-port |
||||||
|
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm |
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 |
||||||
|
|
||||||
|
# User-specific stuff |
||||||
|
.idea/**/workspace.xml |
||||||
|
.idea/**/tasks.xml |
||||||
|
.idea/**/usage.statistics.xml |
||||||
|
.idea/**/dictionaries |
||||||
|
.idea/**/shelf |
||||||
|
|
||||||
|
# Generated files |
||||||
|
.idea/**/contentModel.xml |
||||||
|
|
||||||
|
# Sensitive or high-churn files |
||||||
|
.idea/**/dataSources/ |
||||||
|
.idea/**/dataSources.ids |
||||||
|
.idea/**/dataSources.local.xml |
||||||
|
.idea/**/sqlDataSources.xml |
||||||
|
.idea/**/dynamic.xml |
||||||
|
.idea/**/uiDesigner.xml |
||||||
|
.idea/**/dbnavigator.xml |
||||||
|
|
||||||
|
# Gradle |
||||||
|
.idea/**/gradle.xml |
||||||
|
.idea/**/libraries |
||||||
|
|
||||||
|
# Gradle and Maven with auto-import |
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files, |
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using |
||||||
|
# auto-import. |
||||||
|
# .idea/modules.xml |
||||||
|
# .idea/*.iml |
||||||
|
# .idea/modules |
||||||
|
# *.iml |
||||||
|
# *.ipr |
||||||
|
|
||||||
|
# CMake |
||||||
|
cmake-build-*/ |
||||||
|
|
||||||
|
# Mongo Explorer plugin |
||||||
|
.idea/**/mongoSettings.xml |
||||||
|
|
||||||
|
# File-based project format |
||||||
|
*.iws |
||||||
|
|
||||||
|
# IntelliJ |
||||||
|
out/ |
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin |
||||||
|
.idea_modules/ |
||||||
|
|
||||||
|
# JIRA plugin |
||||||
|
atlassian-ide-plugin.xml |
||||||
|
|
||||||
|
# Cursive Clojure plugin |
||||||
|
.idea/replstate.xml |
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ) |
||||||
|
com_crashlytics_export_strings.xml |
||||||
|
crashlytics.properties |
||||||
|
crashlytics-build.properties |
||||||
|
fabric.properties |
||||||
|
|
||||||
|
# Editor-based Rest Client |
||||||
|
.idea/httpRequests |
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file |
||||||
|
.idea/caches/build_file_checksums.ser |
||||||
|
|
||||||
|
# General |
||||||
|
.DS_Store |
||||||
|
.AppleDouble |
||||||
|
.LSOverride |
||||||
|
|
||||||
|
# Icon must end with two \r |
||||||
|
Icon |
||||||
|
|
||||||
|
|
||||||
|
# Thumbnails |
||||||
|
._* |
||||||
|
|
||||||
|
# Files that might appear in the root of a volume |
||||||
|
.DocumentRevisions-V100 |
||||||
|
.fseventsd |
||||||
|
.Spotlight-V100 |
||||||
|
.TemporaryItems |
||||||
|
.Trashes |
||||||
|
.VolumeIcon.icns |
||||||
|
.com.apple.timemachine.donotpresent |
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share |
||||||
|
.AppleDB |
||||||
|
.AppleDesktop |
||||||
|
Network Trash Folder |
||||||
|
Temporary Items |
||||||
|
.apdisk |
||||||
|
|
||||||
|
# Windows thumbnail cache files |
||||||
|
Thumbs.db |
||||||
|
Thumbs.db:encryptable |
||||||
|
ehthumbs.db |
||||||
|
ehthumbs_vista.db |
||||||
|
|
||||||
|
# Dump file |
||||||
|
*.stackdump |
||||||
|
|
||||||
|
# Folder config file |
||||||
|
[Dd]esktop.ini |
||||||
|
|
||||||
|
# Recycle Bin used on file shares |
||||||
|
$RECYCLE.BIN/ |
||||||
|
|
||||||
|
# Windows Installer files |
||||||
|
*.cab |
||||||
|
*.msi |
||||||
|
*.msix |
||||||
|
*.msm |
||||||
|
*.msp |
||||||
|
|
||||||
|
# Windows shortcuts |
||||||
|
*.lnk |
@ -0,0 +1,17 @@ |
|||||||
|
branches: |
||||||
|
- "+([0-9])?(.{+([0-9]),x}).x" |
||||||
|
- main |
||||||
|
- next |
||||||
|
- next-major |
||||||
|
- name: beta |
||||||
|
prerelease: true |
||||||
|
- name: alpha |
||||||
|
prerelease: true |
||||||
|
plugins: |
||||||
|
- "@semantic-release/commit-analyzer" |
||||||
|
- "@semantic-release/release-notes-generator" |
||||||
|
- "@semantic-release/github" |
||||||
|
- "@semantic-release/npm" |
||||||
|
- "@semantic-release/git" |
||||||
|
options: |
||||||
|
debug: true |
@ -0,0 +1,25 @@ |
|||||||
|
# How to become a contributor and submit your own code |
||||||
|
|
||||||
|
1. Submit an issue describing your proposed change to the repo in question. |
||||||
|
1. The repo owner will respond to your issue promptly. |
||||||
|
1. Fork the desired repo, develop and test your code changes. |
||||||
|
1. Ensure that your code adheres to the existing style in the code to which |
||||||
|
you are contributing. |
||||||
|
1. Ensure that your code has an appropriate set of tests which all pass. |
||||||
|
1. Title your pull request following [Conventional Commits](https://www.conventionalcommits.org/) styling. |
||||||
|
1. Submit a pull request. |
||||||
|
|
||||||
|
## Running the tests |
||||||
|
|
||||||
|
1. Install dependencies: |
||||||
|
|
||||||
|
npm i |
||||||
|
1. Run lint |
||||||
|
|
||||||
|
npm run lint |
||||||
|
npm run format # will fix some issues |
||||||
|
|
||||||
|
1. Run the tests: |
||||||
|
|
||||||
|
# Run unit tests. |
||||||
|
npm test |
@ -0,0 +1,202 @@ |
|||||||
|
|
||||||
|
Apache License |
||||||
|
Version 2.0, January 2004 |
||||||
|
http://www.apache.org/licenses/ |
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION |
||||||
|
|
||||||
|
1. Definitions. |
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction, |
||||||
|
and distribution as defined by Sections 1 through 9 of this document. |
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by |
||||||
|
the copyright owner that is granting the License. |
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all |
||||||
|
other entities that control, are controlled by, or are under common |
||||||
|
control with that entity. For the purposes of this definition, |
||||||
|
"control" means (i) the power, direct or indirect, to cause the |
||||||
|
direction or management of such entity, whether by contract or |
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the |
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity. |
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity |
||||||
|
exercising permissions granted by this License. |
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications, |
||||||
|
including but not limited to software source code, documentation |
||||||
|
source, and configuration files. |
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical |
||||||
|
transformation or translation of a Source form, including but |
||||||
|
not limited to compiled object code, generated documentation, |
||||||
|
and conversions to other media types. |
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or |
||||||
|
Object form, made available under the License, as indicated by a |
||||||
|
copyright notice that is included in or attached to the work |
||||||
|
(an example is provided in the Appendix below). |
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object |
||||||
|
form, that is based on (or derived from) the Work and for which the |
||||||
|
editorial revisions, annotations, elaborations, or other modifications |
||||||
|
represent, as a whole, an original work of authorship. For the purposes |
||||||
|
of this License, Derivative Works shall not include works that remain |
||||||
|
separable from, or merely link (or bind by name) to the interfaces of, |
||||||
|
the Work and Derivative Works thereof. |
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including |
||||||
|
the original version of the Work and any modifications or additions |
||||||
|
to that Work or Derivative Works thereof, that is intentionally |
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner |
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of |
||||||
|
the copyright owner. For the purposes of this definition, "submitted" |
||||||
|
means any form of electronic, verbal, or written communication sent |
||||||
|
to the Licensor or its representatives, including but not limited to |
||||||
|
communication on electronic mailing lists, source code control systems, |
||||||
|
and issue tracking systems that are managed by, or on behalf of, the |
||||||
|
Licensor for the purpose of discussing and improving the Work, but |
||||||
|
excluding communication that is conspicuously marked or otherwise |
||||||
|
designated in writing by the copyright owner as "Not a Contribution." |
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity |
||||||
|
on behalf of whom a Contribution has been received by Licensor and |
||||||
|
subsequently incorporated within the Work. |
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of |
||||||
|
this License, each Contributor hereby grants to You a perpetual, |
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
||||||
|
copyright license to reproduce, prepare Derivative Works of, |
||||||
|
publicly display, publicly perform, sublicense, and distribute the |
||||||
|
Work and such Derivative Works in Source or Object form. |
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of |
||||||
|
this License, each Contributor hereby grants to You a perpetual, |
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
||||||
|
(except as stated in this section) patent license to make, have made, |
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work, |
||||||
|
where such license applies only to those patent claims licensable |
||||||
|
by such Contributor that are necessarily infringed by their |
||||||
|
Contribution(s) alone or by combination of their Contribution(s) |
||||||
|
with the Work to which such Contribution(s) was submitted. If You |
||||||
|
institute patent litigation against any entity (including a |
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work |
||||||
|
or a Contribution incorporated within the Work constitutes direct |
||||||
|
or contributory patent infringement, then any patent licenses |
||||||
|
granted to You under this License for that Work shall terminate |
||||||
|
as of the date such litigation is filed. |
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the |
||||||
|
Work or Derivative Works thereof in any medium, with or without |
||||||
|
modifications, and in Source or Object form, provided that You |
||||||
|
meet the following conditions: |
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or |
||||||
|
Derivative Works a copy of this License; and |
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices |
||||||
|
stating that You changed the files; and |
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works |
||||||
|
that You distribute, all copyright, patent, trademark, and |
||||||
|
attribution notices from the Source form of the Work, |
||||||
|
excluding those notices that do not pertain to any part of |
||||||
|
the Derivative Works; and |
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its |
||||||
|
distribution, then any Derivative Works that You distribute must |
||||||
|
include a readable copy of the attribution notices contained |
||||||
|
within such NOTICE file, excluding those notices that do not |
||||||
|
pertain to any part of the Derivative Works, in at least one |
||||||
|
of the following places: within a NOTICE text file distributed |
||||||
|
as part of the Derivative Works; within the Source form or |
||||||
|
documentation, if provided along with the Derivative Works; or, |
||||||
|
within a display generated by the Derivative Works, if and |
||||||
|
wherever such third-party notices normally appear. The contents |
||||||
|
of the NOTICE file are for informational purposes only and |
||||||
|
do not modify the License. You may add Your own attribution |
||||||
|
notices within Derivative Works that You distribute, alongside |
||||||
|
or as an addendum to the NOTICE text from the Work, provided |
||||||
|
that such additional attribution notices cannot be construed |
||||||
|
as modifying the License. |
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and |
||||||
|
may provide additional or different license terms and conditions |
||||||
|
for use, reproduction, or distribution of Your modifications, or |
||||||
|
for any such Derivative Works as a whole, provided Your use, |
||||||
|
reproduction, and distribution of the Work otherwise complies with |
||||||
|
the conditions stated in this License. |
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise, |
||||||
|
any Contribution intentionally submitted for inclusion in the Work |
||||||
|
by You to the Licensor shall be under the terms and conditions of |
||||||
|
this License, without any additional terms or conditions. |
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify |
||||||
|
the terms of any separate license agreement you may have executed |
||||||
|
with Licensor regarding such Contributions. |
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade |
||||||
|
names, trademarks, service marks, or product names of the Licensor, |
||||||
|
except as required for reasonable and customary use in describing the |
||||||
|
origin of the Work and reproducing the content of the NOTICE file. |
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or |
||||||
|
agreed to in writing, Licensor provides the Work (and each |
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS, |
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
||||||
|
implied, including, without limitation, any warranties or conditions |
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A |
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the |
||||||
|
appropriateness of using or redistributing the Work and assume any |
||||||
|
risks associated with Your exercise of permissions under this License. |
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory, |
||||||
|
whether in tort (including negligence), contract, or otherwise, |
||||||
|
unless required by applicable law (such as deliberate and grossly |
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be |
||||||
|
liable to You for damages, including any direct, indirect, special, |
||||||
|
incidental, or consequential damages of any character arising as a |
||||||
|
result of this License or out of the use or inability to use the |
||||||
|
Work (including but not limited to damages for loss of goodwill, |
||||||
|
work stoppage, computer failure or malfunction, or any and all |
||||||
|
other commercial damages or losses), even if such Contributor |
||||||
|
has been advised of the possibility of such damages. |
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing |
||||||
|
the Work or Derivative Works thereof, You may choose to offer, |
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity, |
||||||
|
or other liability obligations and/or rights consistent with this |
||||||
|
License. However, in accepting such obligations, You may act only |
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf |
||||||
|
of any other Contributor, and only if You agree to indemnify, |
||||||
|
defend, and hold each Contributor harmless for any liability |
||||||
|
incurred by, or claims asserted against, such Contributor by reason |
||||||
|
of your accepting any such warranty or additional liability. |
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS |
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work. |
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following |
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]" |
||||||
|
replaced with your own identifying information. (Don't include |
||||||
|
the brackets!) The text should be enclosed in the appropriate |
||||||
|
comment syntax for the file format. We also recommend that a |
||||||
|
file or class name and description of purpose be included on the |
||||||
|
same "printed page" as the copyright notice for easier |
||||||
|
identification within third-party archives. |
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner] |
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
you may not use this file except in compliance with the License. |
||||||
|
You may obtain a copy of the License at |
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software |
||||||
|
distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
See the License for the specific language governing permissions and |
||||||
|
limitations under the License. |
@ -0,0 +1,61 @@ |
|||||||
|
# Google Maps JavaScript MarkerWithLabel |
||||||
|
|
||||||
|
[![npm](https://img.shields.io/npm/v/@googlemaps/markerwithlabel)](https://www.npmjs.com/package/@googlemaps/markerwithlabel) |
||||||
|
![Build](https://github.com/googlemaps/js-markerwithlabel/workflows/Build/badge.svg) |
||||||
|
![Release](https://github.com/googlemaps/js-markerwithlabel/workflows/Release/badge.svg) |
||||||
|
[![codecov](https://codecov.io/gh/googlemaps/js-markerwithlabel/branch/main/graph/badge.svg)](https://codecov.io/gh/googlemaps/js-markerwithlabel) |
||||||
|
![GitHub contributors](https://img.shields.io/github/contributors/googlemaps/js-markerwithlabel?color=green) |
||||||
|
[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release) |
||||||
|
[![](https://github.com/jpoehnelt/in-solidarity-bot/raw/main/static//badge-flat.png)](https://github.com/apps/in-solidarity) |
||||||
|
|
||||||
|
## Description |
||||||
|
|
||||||
|
The library creates and manages per-zoom-level clusters for large amounts of markers. |
||||||
|
|
||||||
|
> **Note**: This library is the nearly the same interface as the existing library `@google/markerwithlabel`, but renamed and in its own repository. All future development will continue here. |
||||||
|
|
||||||
|
> **Note**: There are some breaking changes from `@google/markerwithlabel` including anchor position. This should be consider a major version bump! |
||||||
|
|
||||||
|
## Install |
||||||
|
|
||||||
|
Available via npm as the package [@googlemaps/markerwithlabel](https://www.npmjs.com/package/@googlemaps/markerwithlabel). |
||||||
|
|
||||||
|
`npm i @googlemaps/markerwithlabel` |
||||||
|
|
||||||
|
or |
||||||
|
|
||||||
|
`yarn add @googlemaps/markerwithlabel` |
||||||
|
|
||||||
|
Alternativly you may add the umd package directly to the html document using the unpkg link. |
||||||
|
|
||||||
|
`<script src="https://unpkg.com/@googlemaps/markerwithlabel/dist/index.min.js"></script>` |
||||||
|
|
||||||
|
When adding via unpkg, the loader can be accessed at `MarkerClusterer`. |
||||||
|
|
||||||
|
A version can be specified by using `https://unpkg.com/@googlemaps/markerwithlabel@VERSION/dist/...`. |
||||||
|
|
||||||
|
## Documentation |
||||||
|
|
||||||
|
The reference documentation can be found at this [link](https://googlemaps.github.io/js-markerwithlabel/index.html). |
||||||
|
|
||||||
|
## Example |
||||||
|
|
||||||
|
```js |
||||||
|
new MarkerWithLabel({ |
||||||
|
position: new google.maps.LatLng(49.475, -123.84), |
||||||
|
clickable: true, |
||||||
|
draggable: true, |
||||||
|
map: map, |
||||||
|
labelContent: "foo", // can also be HTMLElement |
||||||
|
labelAnchor: new google.maps.Point(-21, 3), |
||||||
|
labelClass: "labels", // the CSS class for the label |
||||||
|
labelStyle: { opacity: 1.0 }, |
||||||
|
}) |
||||||
|
``` |
||||||
|
|
||||||
|
View the package in action: |
||||||
|
|
||||||
|
- [Basic Example](https://googlemaps.github.io/js-markerwithlabel/examples/basic.html) |
||||||
|
- [Events Example](https://googlemaps.github.io/js-markerwithlabel/examples/events.html) |
||||||
|
- [Lettered Example](https://googlemaps.github.io/js-markerwithlabel/examples/lettered.html) |
||||||
|
- [Picture Example](https://googlemaps.github.io/js-markerwithlabel/examples/picturelabel.html) |
@ -0,0 +1,80 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html> |
||||||
|
<head> |
||||||
|
<meta http-equiv="content-type" content="text/html; charset=utf-8" /> |
||||||
|
<title>MarkerWithLabel Example</title> |
||||||
|
<style type="text/css"> |
||||||
|
.labels { |
||||||
|
color: #ea4335; |
||||||
|
background-color: white; |
||||||
|
font-family: Roboto, Arial, sans-serif; |
||||||
|
font-size: 10px; |
||||||
|
font-weight: bold; |
||||||
|
text-align: center; |
||||||
|
width: 40px; |
||||||
|
padding: 2px; |
||||||
|
border: 1px solid #999; |
||||||
|
box-sizing: border-box; |
||||||
|
white-space: nowrap; |
||||||
|
} |
||||||
|
</style> |
||||||
|
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBIwzALxUPNbatRBj3Xi1Uhp0fFzwWNBkE"></script> |
||||||
|
<script src="../dist/index.dev.js"></script> |
||||||
|
<script> |
||||||
|
function initMap() { |
||||||
|
var latLng = new google.maps.LatLng(49.47805, -123.84716); |
||||||
|
var homeLatLng = new google.maps.LatLng(49.47805, -123.84716); |
||||||
|
|
||||||
|
var map = new google.maps.Map(document.getElementById("map_canvas"), { |
||||||
|
zoom: 12, |
||||||
|
center: latLng, |
||||||
|
mapTypeId: google.maps.MapTypeId.ROADMAP, |
||||||
|
}); |
||||||
|
|
||||||
|
var marker1 = new MarkerWithLabel({ |
||||||
|
position: homeLatLng, |
||||||
|
draggable: false, |
||||||
|
clickable: false, |
||||||
|
map: map, |
||||||
|
labelContent: "$425K", |
||||||
|
labelAnchor: new google.maps.Point(-21, 3), |
||||||
|
labelClass: "labels", // the CSS class for the label |
||||||
|
labelStyle: { opacity: 0.75 }, |
||||||
|
}); |
||||||
|
|
||||||
|
var marker2 = new MarkerWithLabel({ |
||||||
|
position: new google.maps.LatLng(49.475, -123.84), |
||||||
|
draggable: true, |
||||||
|
map: map, |
||||||
|
labelContent: "$395K", |
||||||
|
labelAnchor: new google.maps.Point(-21, 3), |
||||||
|
labelClass: "labels", // the CSS class for the label |
||||||
|
labelStyle: { opacity: 1.0 }, |
||||||
|
}); |
||||||
|
|
||||||
|
var iw1 = new google.maps.InfoWindow({ |
||||||
|
content: "Home For Sale", |
||||||
|
}); |
||||||
|
var iw2 = new google.maps.InfoWindow({ |
||||||
|
content: "Another Home For Sale", |
||||||
|
}); |
||||||
|
google.maps.event.addListener(marker1, "click", function (e) { |
||||||
|
iw1.open(map, this); |
||||||
|
}); |
||||||
|
google.maps.event.addListener(marker2, "click", function (e) { |
||||||
|
iw2.open(map, this); |
||||||
|
}); |
||||||
|
} |
||||||
|
</script> |
||||||
|
</head> |
||||||
|
<body onload="initMap()"> |
||||||
|
<p> |
||||||
|
A basic example of markers with labels. Note that an information window |
||||||
|
appears whether you click the marker portion or the label portion of the |
||||||
|
MarkerWithLabel. The two markers shown here are both draggable so you can |
||||||
|
easily verify that markers and labels overlap as expected. |
||||||
|
</p> |
||||||
|
<div id="map_canvas" style="height: 400px; width: 100%"></div> |
||||||
|
<div id="log"></div> |
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1,93 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html> |
||||||
|
<head> |
||||||
|
<meta http-equiv="content-type" content="text/html; charset=utf-8" /> |
||||||
|
<title>MarkerWithLabel Mouse Events</title> |
||||||
|
<style type="text/css"> |
||||||
|
.labels { |
||||||
|
color: red; |
||||||
|
background-color: white; |
||||||
|
font-family: "Lucida Grande", "Arial", sans-serif; |
||||||
|
font-size: 10px; |
||||||
|
font-weight: bold; |
||||||
|
text-align: center; |
||||||
|
width: 40px; |
||||||
|
border: 2px solid black; |
||||||
|
white-space: nowrap; |
||||||
|
} |
||||||
|
</style> |
||||||
|
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBIwzALxUPNbatRBj3Xi1Uhp0fFzwWNBkE"></script> |
||||||
|
<script src="../dist/index.dev.js"></script> |
||||||
|
<script> |
||||||
|
function initMap() { |
||||||
|
var latLng = new google.maps.LatLng(49.47805, -123.84716); |
||||||
|
var homeLatLng = new google.maps.LatLng(49.47805, -123.84716); |
||||||
|
|
||||||
|
var map = new google.maps.Map(document.getElementById("map_canvas"), { |
||||||
|
zoom: 12, |
||||||
|
center: latLng, |
||||||
|
mapTypeId: google.maps.MapTypeId.ROADMAP, |
||||||
|
}); |
||||||
|
|
||||||
|
var marker = new MarkerWithLabel({ |
||||||
|
position: homeLatLng, |
||||||
|
draggable: true, |
||||||
|
raiseOnDrag: true, |
||||||
|
map: map, |
||||||
|
labelContent: "$425K", |
||||||
|
labelAnchor: new google.maps.Point(22, 0), |
||||||
|
labelClass: "labels", // the CSS class for the label |
||||||
|
}); |
||||||
|
|
||||||
|
var iw = new google.maps.InfoWindow({ |
||||||
|
content: "Home For Sale", |
||||||
|
}); |
||||||
|
google.maps.event.addListener(marker, "click", function (e) { |
||||||
|
iw.open(map, this); |
||||||
|
}); |
||||||
|
|
||||||
|
google.maps.event.addListener(marker, "click", function (e) { |
||||||
|
log("Click"); |
||||||
|
}); |
||||||
|
google.maps.event.addListener(marker, "dblclick", function (e) { |
||||||
|
log("Double Click"); |
||||||
|
}); |
||||||
|
google.maps.event.addListener(marker, "mouseover", function (e) { |
||||||
|
log("Mouse Over"); |
||||||
|
}); |
||||||
|
google.maps.event.addListener(marker, "mouseout", function (e) { |
||||||
|
log("Mouse Out"); |
||||||
|
}); |
||||||
|
google.maps.event.addListener(marker, "mouseup", function (e) { |
||||||
|
log("Mouse Up"); |
||||||
|
}); |
||||||
|
google.maps.event.addListener(marker, "mousedown", function (e) { |
||||||
|
log("Mouse Down"); |
||||||
|
}); |
||||||
|
google.maps.event.addListener(marker, "dragstart", function (mEvent) { |
||||||
|
log("Drag Start: " + mEvent.latLng.toString()); |
||||||
|
}); |
||||||
|
google.maps.event.addListener(marker, "drag", function (mEvent) { |
||||||
|
log("Drag: " + mEvent.latLng.toString()); |
||||||
|
}); |
||||||
|
google.maps.event.addListener(marker, "dragend", function (mEvent) { |
||||||
|
log("Drag End: " + mEvent.latLng.toString()); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
function log(h) { |
||||||
|
document.getElementById("log").innerHTML += h + "<br />"; |
||||||
|
} |
||||||
|
</script> |
||||||
|
</head> |
||||||
|
<body onload="initMap()"> |
||||||
|
<p> |
||||||
|
Try interacting with the marker (mouseover, mouseout, click, double-click, |
||||||
|
mouse down, mouse up, drag) to see a log of events that are fired. Events |
||||||
|
are fired whether you are interacting with the marker portion or the label |
||||||
|
portion. |
||||||
|
</p> |
||||||
|
<div id="map_canvas" style="height: 400px; width: 100%"></div> |
||||||
|
<div id="log"></div> |
||||||
|
</body> |
||||||
|
</html> |
After Width: | Height: | Size: 7.7 KiB |
@ -0,0 +1,63 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html> |
||||||
|
<head> |
||||||
|
<meta http-equiv="content-type" content="text/html; charset=utf-8" /> |
||||||
|
<title>Lettered Marker</title> |
||||||
|
<style type="text/css"> |
||||||
|
.labels { |
||||||
|
color: white; |
||||||
|
background-color: #ea4335; |
||||||
|
font-family: Roboto, Arial, sans-serif; |
||||||
|
font-size: 10px; |
||||||
|
text-align: center; |
||||||
|
width: 10px; |
||||||
|
white-space: nowrap; |
||||||
|
} |
||||||
|
</style> |
||||||
|
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBIwzALxUPNbatRBj3Xi1Uhp0fFzwWNBkE"></script> |
||||||
|
<script src="../dist/index.dev.js"></script> |
||||||
|
<script> |
||||||
|
var marker; |
||||||
|
function initMap() { |
||||||
|
var latLng = new google.maps.LatLng(49.47805, -123.84716); |
||||||
|
var homeLatLng = new google.maps.LatLng(49.47805, -123.84716); |
||||||
|
|
||||||
|
var map = new google.maps.Map(document.getElementById("map_canvas"), { |
||||||
|
zoom: 12, |
||||||
|
center: latLng, |
||||||
|
mapTypeId: google.maps.MapTypeId.ROADMAP, |
||||||
|
}); |
||||||
|
|
||||||
|
marker = new MarkerWithLabel({ |
||||||
|
position: homeLatLng, |
||||||
|
map: map, |
||||||
|
draggable: true, |
||||||
|
raiseOnDrag: true, |
||||||
|
labelContent: "A", |
||||||
|
labelAnchor: new google.maps.Point(-6, -35), |
||||||
|
labelClass: "labels", // the CSS class for the label |
||||||
|
labelInBackground: false, |
||||||
|
}); |
||||||
|
|
||||||
|
var iw = new google.maps.InfoWindow({ |
||||||
|
content: "", |
||||||
|
}); |
||||||
|
google.maps.event.addListener(marker, "click", function (e) { |
||||||
|
iw.open(map, this); |
||||||
|
}); |
||||||
|
} |
||||||
|
function log(h) { |
||||||
|
document.getElementById("log").innerHTML += h + "<br />"; |
||||||
|
} |
||||||
|
</script> |
||||||
|
</head> |
||||||
|
<body onload="initMap()"> |
||||||
|
<p> |
||||||
|
With MarkerWithLabel you can easily modify a standard marker to include an |
||||||
|
identifying character of your choice. In this case the marker is |
||||||
|
superimposed with the letter "A". |
||||||
|
</p> |
||||||
|
<div id="map_canvas" style="height: 400px; width: 100%"></div> |
||||||
|
<div id="log"></div> |
||||||
|
</body> |
||||||
|
</html> |
After Width: | Height: | Size: 8.9 KiB |
@ -0,0 +1,60 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html> |
||||||
|
<head> |
||||||
|
<meta http-equiv="content-type" content="text/html; charset=utf-8" /> |
||||||
|
<title>Picture Label for Marker</title> |
||||||
|
<style type="text/css"> |
||||||
|
.labels { |
||||||
|
width: 100px; |
||||||
|
} |
||||||
|
</style> |
||||||
|
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBIwzALxUPNbatRBj3Xi1Uhp0fFzwWNBkE&callback=initMap&v=beta"></script> |
||||||
|
<script src="../dist/index.dev.js"></script> |
||||||
|
<script> |
||||||
|
var marker, pictureLabel; |
||||||
|
function initMap() { |
||||||
|
var latLng = new google.maps.LatLng(49.47805, -123.84716); |
||||||
|
var homeLatLng = new google.maps.LatLng(49.47805, -123.84716); |
||||||
|
|
||||||
|
var map = new google.maps.Map(document.getElementById("map_canvas"), { |
||||||
|
zoom: 12, |
||||||
|
center: latLng, |
||||||
|
mapTypeId: google.maps.MapTypeId.ROADMAP, |
||||||
|
}); |
||||||
|
|
||||||
|
pictureLabel = document.createElement("img"); |
||||||
|
pictureLabel.src = "home.jpg"; |
||||||
|
|
||||||
|
marker = new MarkerWithLabel({ |
||||||
|
position: homeLatLng, |
||||||
|
map: map, |
||||||
|
draggable: true, |
||||||
|
raiseOnDrag: true, |
||||||
|
labelContent: pictureLabel, |
||||||
|
labelAnchor: new google.maps.Point(-50, 0), |
||||||
|
labelClass: "labels", // the CSS class for the label |
||||||
|
labelStyle: { opacity: 0.5 }, |
||||||
|
}); |
||||||
|
|
||||||
|
var iw = new google.maps.InfoWindow({ |
||||||
|
content: "Home For Sale", |
||||||
|
}); |
||||||
|
google.maps.event.addListener(marker, "click", function (e) { |
||||||
|
iw.open(map, this); |
||||||
|
}); |
||||||
|
} |
||||||
|
function log(h) { |
||||||
|
document.getElementById("log").innerHTML += h + "<br />"; |
||||||
|
} |
||||||
|
</script> |
||||||
|
</head> |
||||||
|
<body onload="initMap()"> |
||||||
|
<p> |
||||||
|
This is an example of how to use a picture as a marker label. Since the |
||||||
|
picture label is quite large, the opacity of the label is set to 0.50 to |
||||||
|
make it possible to get a rough idea of what's on the map behind the |
||||||
|
picture. |
||||||
|
</p> |
||||||
|
<div id="map_canvas" style="height: 400px; width: 100%"></div> |
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1,23 @@ |
|||||||
|
/** |
||||||
|
* Copyright 2020 Google LLC |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
module.exports = { |
||||||
|
transform: { |
||||||
|
"^.+\\.tsx?$": "ts-jest", |
||||||
|
}, |
||||||
|
collectCoverage: true, |
||||||
|
testPathIgnorePatterns: ["/dist/"], |
||||||
|
}; |
@ -0,0 +1,68 @@ |
|||||||
|
{ |
||||||
|
"name": "@googlemaps/markerwithlabel", |
||||||
|
"version": "1.0.0", |
||||||
|
"keywords": [ |
||||||
|
"label", |
||||||
|
"google", |
||||||
|
"maps", |
||||||
|
"marker" |
||||||
|
], |
||||||
|
"homepage": "https://github.com/googlemaps/js-markerwithlabel", |
||||||
|
"bugs": { |
||||||
|
"url": "https://github.com/googlemaps/js-markerwithlabel/issues" |
||||||
|
}, |
||||||
|
"repository": { |
||||||
|
"type": "git", |
||||||
|
"url": "https://github.com/googlemaps/js-markerwithlabel.git" |
||||||
|
}, |
||||||
|
"license": "Apache-2.0", |
||||||
|
"author": "Justin Poehnelt", |
||||||
|
"files": [ |
||||||
|
"dist/*", |
||||||
|
"images/*" |
||||||
|
], |
||||||
|
"main": "dist/index.umd.js", |
||||||
|
"unpkg": "dist/index.min.js", |
||||||
|
"module": "dist/index.esm.js", |
||||||
|
"types": "dist/index.d.ts", |
||||||
|
"scripts": { |
||||||
|
"docs": "typedoc", |
||||||
|
"format": "prettier *.json *.js e2e/* examples/*.html --write && eslint src/* --fix", |
||||||
|
"lint": "eslint src/*", |
||||||
|
"prepare": "rollup -c", |
||||||
|
"test": "jest --passWithNoTests src/*", |
||||||
|
"test:e2e": "jest --passWithNoTests e2e/*" |
||||||
|
}, |
||||||
|
"devDependencies": { |
||||||
|
"@babel/preset-env": "^7.11.5", |
||||||
|
"@babel/runtime-corejs3": "^7.11.2", |
||||||
|
"@googlemaps/jest-mocks": "^0.1.0", |
||||||
|
"@types/googlemaps": "^3.39.13", |
||||||
|
"@types/jest": "^26.0.14", |
||||||
|
"@types/selenium-webdriver": "^4.0.9", |
||||||
|
"@typescript-eslint/eslint-plugin": ">=4.1.0", |
||||||
|
"@typescript-eslint/parser": ">=4.1.0", |
||||||
|
"chromedriver": "^85.0.1", |
||||||
|
"core-js": "^3.6.5", |
||||||
|
"eslint": "^7.8.1", |
||||||
|
"eslint-config-prettier": "^6.11.0", |
||||||
|
"eslint-plugin-jest": "^24.0.0", |
||||||
|
"eslint-plugin-prettier": "^3.1.4", |
||||||
|
"geckodriver": "^1.20.0", |
||||||
|
"jest": "^26.4.2", |
||||||
|
"prettier": "^2.1.1", |
||||||
|
"rollup": "^2.26.11", |
||||||
|
"rollup-plugin-babel": "^4.4.0", |
||||||
|
"rollup-plugin-commonjs": "^10.1.0", |
||||||
|
"rollup-plugin-terser": "^7.0.2", |
||||||
|
"rollup-plugin-typescript2": "^0.27.2", |
||||||
|
"selenium-webdriver": "^4.0.0-alpha.7", |
||||||
|
"ts-jest": "^26.3.0", |
||||||
|
"typedoc": "^0.19.1", |
||||||
|
"typescript": "^4.0.2" |
||||||
|
}, |
||||||
|
"publishConfig": { |
||||||
|
"access": "public", |
||||||
|
"registry": "https://wombat-dressing-room.appspot.com" |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,73 @@ |
|||||||
|
/** |
||||||
|
* Copyright 2020 Google LLC |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
import babel from "rollup-plugin-babel"; |
||||||
|
import commonjs from "rollup-plugin-commonjs"; |
||||||
|
import { terser } from "rollup-plugin-terser"; |
||||||
|
import typescript from "rollup-plugin-typescript2"; |
||||||
|
|
||||||
|
const babelOptions = { |
||||||
|
extensions: [".js", ".ts"], |
||||||
|
}; |
||||||
|
|
||||||
|
const terserOptions = { output: { comments: "" } }; |
||||||
|
|
||||||
|
export default [ |
||||||
|
{ |
||||||
|
input: "src/index.ts", |
||||||
|
plugins: [ |
||||||
|
typescript(), |
||||||
|
commonjs(), |
||||||
|
babel(babelOptions), |
||||||
|
terser(terserOptions), |
||||||
|
], |
||||||
|
output: [ |
||||||
|
{ |
||||||
|
file: "dist/index.umd.js", |
||||||
|
format: "umd", |
||||||
|
sourcemap: true, |
||||||
|
exports: "default", |
||||||
|
name: "MarkerWithLabel", |
||||||
|
}, |
||||||
|
{ |
||||||
|
file: "dist/index.min.js", |
||||||
|
format: "iife", |
||||||
|
sourcemap: true, |
||||||
|
exports: "default", |
||||||
|
name: "MarkerWithLabel", |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
{ |
||||||
|
input: "src/index.ts", |
||||||
|
plugins: [typescript(), commonjs()], |
||||||
|
output: { |
||||||
|
file: "dist/index.dev.js", |
||||||
|
format: "iife", |
||||||
|
name: "MarkerWithLabel", |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
input: "src/index.ts", |
||||||
|
plugins: [typescript()], |
||||||
|
output: { |
||||||
|
file: "dist/index.esm.js", |
||||||
|
format: "esm", |
||||||
|
sourcemap: true, |
||||||
|
name: "MarkerWithLabel", |
||||||
|
}, |
||||||
|
}, |
||||||
|
]; |
@ -0,0 +1,19 @@ |
|||||||
|
/** |
||||||
|
* Copyright 2020 Google LLC. All Rights Reserved. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
import { MarkerWithLabel } from "./marker"; |
||||||
|
|
||||||
|
export default MarkerWithLabel; |
@ -0,0 +1,130 @@ |
|||||||
|
/** |
||||||
|
* Copyright 2020 Google LLC. All Rights Reserved. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
import { Label } from "./label"; |
||||||
|
import { initialize } from "@googlemaps/jest-mocks"; |
||||||
|
|
||||||
|
class OverlayView {} |
||||||
|
beforeAll(() => { |
||||||
|
document.body.innerHTML = ""; |
||||||
|
initialize(); |
||||||
|
google.maps.OverlayView = OverlayView as any; |
||||||
|
Label.prototype.getProjection = (): google.maps.MapCanvasProjection => { |
||||||
|
return ({ |
||||||
|
fromPointToLatLng: () => {}, |
||||||
|
fromLatLngToPoint: () => {}, |
||||||
|
fromLatLngToDivPixel: (position: google.maps.LatLng) => { |
||||||
|
return { x: 1, y: 3 }; |
||||||
|
}, |
||||||
|
} as unknown) as google.maps.MapCanvasProjection; |
||||||
|
}; |
||||||
|
}); |
||||||
|
|
||||||
|
test("should render the divs correctly with string content", () => { |
||||||
|
const label = new Label({ labelContent: "foo", labelClass: "label" }); |
||||||
|
label.draw(); |
||||||
|
expect(label["labelDiv"]).toMatchInlineSnapshot(` |
||||||
|
<div |
||||||
|
class="label marker-label" |
||||||
|
style="position: absolute; opacity: 1; left: 1px; top: 3px; z-index: 4;" |
||||||
|
> |
||||||
|
foo |
||||||
|
</div> |
||||||
|
`);
|
||||||
|
expect(label["eventDiv"]).toMatchInlineSnapshot(` |
||||||
|
<div |
||||||
|
class="label marker-label-event" |
||||||
|
style="position: absolute; opacity: 0.01; cursor: pointer; left: 1px; top: 3px; z-index: 4; display: block;" |
||||||
|
> |
||||||
|
foo |
||||||
|
</div> |
||||||
|
`);
|
||||||
|
}); |
||||||
|
|
||||||
|
test("should render the divs correctly with node content", () => { |
||||||
|
const label = new Label({ labelContent: document.createElement("img") }); |
||||||
|
label.draw(); |
||||||
|
expect(label["labelDiv"]).toMatchInlineSnapshot(` |
||||||
|
<div |
||||||
|
class="marker-label" |
||||||
|
style="position: absolute; opacity: 1; left: 1px; top: 3px; z-index: 4;" |
||||||
|
> |
||||||
|
<img /> |
||||||
|
</div> |
||||||
|
`);
|
||||||
|
expect(label["eventDiv"]).toMatchInlineSnapshot(` |
||||||
|
<div |
||||||
|
class="marker-label marker-label-event" |
||||||
|
style="position: absolute; opacity: 0.01; cursor: pointer; left: 1px; top: 3px; z-index: 4; display: block;" |
||||||
|
> |
||||||
|
<img /> |
||||||
|
</div> |
||||||
|
`);
|
||||||
|
}); |
||||||
|
|
||||||
|
test("should render the divs with options", () => { |
||||||
|
const label = new Label({ |
||||||
|
labelContent: "foo", |
||||||
|
opacity: 0.5, |
||||||
|
labelClass: "label", |
||||||
|
position: { lat: 0, lng: 0 }, |
||||||
|
anchorPoint: { x: 100, y: 200 } as google.maps.Point, |
||||||
|
labelZIndexOffset: 10, |
||||||
|
zIndex: 1000, |
||||||
|
draggable: false, |
||||||
|
clickable: false, |
||||||
|
}); |
||||||
|
label.draw(); |
||||||
|
expect(label["labelDiv"]).toMatchInlineSnapshot(` |
||||||
|
<div |
||||||
|
class="label marker-label" |
||||||
|
style="position: absolute; opacity: 0.5; left: 1px; top: 3px; z-index: 1010;" |
||||||
|
> |
||||||
|
foo |
||||||
|
</div> |
||||||
|
`);
|
||||||
|
expect(label["eventDiv"]).toMatchInlineSnapshot(` |
||||||
|
<div |
||||||
|
class="label marker-label-event" |
||||||
|
style="position: absolute; opacity: 0.01; left: 1px; top: 3px; z-index: 1010; display: none; cursor: inherit;" |
||||||
|
> |
||||||
|
foo |
||||||
|
</div> |
||||||
|
`);
|
||||||
|
}); |
||||||
|
|
||||||
|
test("should render the event div based upon interactivity", () => { |
||||||
|
const label = new Label({ |
||||||
|
labelContent: "foo", |
||||||
|
draggable: false, |
||||||
|
clickable: false, |
||||||
|
}); |
||||||
|
|
||||||
|
[ |
||||||
|
[false, false, "none"], |
||||||
|
[true, false, "block"], |
||||||
|
[false, true, "block"], |
||||||
|
[true, true, "block"], |
||||||
|
].map(([clickable, draggable, display]: [boolean, boolean, string]) => { |
||||||
|
label.clickable = clickable; |
||||||
|
label.draggable = draggable; |
||||||
|
label.draw(); |
||||||
|
expect(label["eventDiv"].style.display).toBe(display); |
||||||
|
expect(label["eventDiv"].style.cursor).toBe( |
||||||
|
display === "block" ? "pointer" : "inherit" |
||||||
|
); |
||||||
|
}); |
||||||
|
}); |
@ -0,0 +1,186 @@ |
|||||||
|
/** |
||||||
|
* Copyright 2020 Google LLC. All Rights Reserved. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
import { MarkerWithLabelOptions } from "./marker"; |
||||||
|
import { OverlayViewSafe } from "./overlay-view-safe"; |
||||||
|
|
||||||
|
export type LabelOptions = Partial<MarkerWithLabelOptions>; |
||||||
|
|
||||||
|
const BLOCK = "block"; |
||||||
|
const NONE = "none"; |
||||||
|
const ABSOLUTE = "absolute"; |
||||||
|
const CURSOR = "pointer"; |
||||||
|
const LABEL_CLASS = "marker-label"; |
||||||
|
const EVENT_CLASS = "marker-label-event"; |
||||||
|
const EVENT_DIV_OPACITY = "0.01"; |
||||||
|
|
||||||
|
export class Label extends OverlayViewSafe { |
||||||
|
public anchor: google.maps.Point; |
||||||
|
public position: google.maps.LatLng; |
||||||
|
public zIndex: number; |
||||||
|
public clickable: boolean; |
||||||
|
public draggable: boolean; |
||||||
|
private labelDiv: HTMLElement; |
||||||
|
private eventDiv: HTMLElement; |
||||||
|
private zIndexOffset: number; |
||||||
|
private hoverCursor: string; |
||||||
|
|
||||||
|
constructor({ |
||||||
|
clickable = true, |
||||||
|
cursor = CURSOR, |
||||||
|
draggable = true, |
||||||
|
labelAnchor = new google.maps.Point(0, 0), |
||||||
|
labelClass = LABEL_CLASS, |
||||||
|
labelContent, |
||||||
|
position, |
||||||
|
opacity = 1, |
||||||
|
map, |
||||||
|
labelZIndexOffset = 1, |
||||||
|
zIndex = 0, |
||||||
|
}: LabelOptions) { |
||||||
|
super();
|
||||||
|
|
||||||
|
this.createElements(); |
||||||
|
|
||||||
|
this.anchor = labelAnchor; |
||||||
|
this.content = labelContent; |
||||||
|
this.className = labelClass; |
||||||
|
this.clickable = clickable; |
||||||
|
this.cursor = cursor; |
||||||
|
this.draggable = draggable; |
||||||
|
|
||||||
|
if (position instanceof google.maps.LatLng) { |
||||||
|
this.position = position; |
||||||
|
} else { |
||||||
|
this.position = new google.maps.LatLng(position); |
||||||
|
} |
||||||
|
|
||||||
|
this.opacity = opacity; |
||||||
|
this.zIndex = zIndex; |
||||||
|
this.zIndexOffset = labelZIndexOffset; |
||||||
|
|
||||||
|
if (map) { |
||||||
|
this.setMap(map); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
set content(content: string | HTMLElement) { |
||||||
|
if (typeof content === "string") { |
||||||
|
this.labelDiv.innerHTML = content; |
||||||
|
this.eventDiv.innerHTML = content; |
||||||
|
} else { |
||||||
|
this.labelDiv.innerHTML = ""; |
||||||
|
this.labelDiv.appendChild(content); |
||||||
|
this.eventDiv.innerHTML = ""; |
||||||
|
this.eventDiv.appendChild(content.cloneNode(true)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
set className(className: string) { |
||||||
|
this.labelDiv.className = className; |
||||||
|
this.labelDiv.classList.add(LABEL_CLASS); |
||||||
|
this.eventDiv.className = className; |
||||||
|
this.eventDiv.classList.add(EVENT_CLASS); |
||||||
|
} |
||||||
|
|
||||||
|
set cursor(cursor: string) { |
||||||
|
this.hoverCursor = cursor; |
||||||
|
if (this.isInteractive) { |
||||||
|
this.eventDiv.style.cursor = cursor; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
get cursor() { |
||||||
|
return this.isInteractive ? this.hoverCursor : "inherit"; |
||||||
|
} |
||||||
|
|
||||||
|
get isInteractive() { |
||||||
|
return this.draggable || this.clickable; |
||||||
|
} |
||||||
|
|
||||||
|
set opacity(opacity: number) { |
||||||
|
this.labelDiv.style.opacity = String(opacity); |
||||||
|
} |
||||||
|
|
||||||
|
set title(title: string) { |
||||||
|
this.eventDiv.title = title; |
||||||
|
} |
||||||
|
|
||||||
|
set visible(visible: boolean) { |
||||||
|
if (visible) { |
||||||
|
this.labelDiv.style.display = BLOCK; |
||||||
|
this.eventDiv.style.display = BLOCK; |
||||||
|
} else { |
||||||
|
this.labelDiv.style.display = NONE; |
||||||
|
this.eventDiv.style.display = NONE; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
onAdd() { |
||||||
|
this.getPanes().markerLayer.appendChild(this.labelDiv); |
||||||
|
this.getPanes().overlayMouseTarget.appendChild(this.eventDiv); |
||||||
|
} |
||||||
|
|
||||||
|
draw() { |
||||||
|
const coordinates = this.getProjection().fromLatLngToDivPixel( |
||||||
|
this.position |
||||||
|
); |
||||||
|
const x = Math.round(coordinates.x + this.anchor.x); |
||||||
|
const y = Math.round(coordinates.y + this.anchor.y); |
||||||
|
this.labelDiv.style.left = `${x}px`; |
||||||
|
this.labelDiv.style.top = `${y}px`; |
||||||
|
this.eventDiv.style.left = this.labelDiv.style.left; |
||||||
|
this.eventDiv.style.top = this.labelDiv.style.top; |
||||||
|
|
||||||
|
// If zIndex is not defined, used vertical position on map.
|
||||||
|
const zIndex = |
||||||
|
(this.zIndex || Math.ceil(coordinates.y)) + this.zIndexOffset; |
||||||
|
this.labelDiv.style.zIndex = String(zIndex); |
||||||
|
this.eventDiv.style.zIndex = String(zIndex); |
||||||
|
|
||||||
|
// If not interactive set display none on event div
|
||||||
|
this.eventDiv.style.display = this.isInteractive ? BLOCK : NONE; |
||||||
|
this.eventDiv.style.cursor = this.cursor; |
||||||
|
} |
||||||
|
|
||||||
|
addDomListener( |
||||||
|
event: string, |
||||||
|
handler: (event: Event) => void |
||||||
|
): google.maps.MapsEventListener { |
||||||
|
return google.maps.event.addDomListener(this.eventDiv, event, handler); |
||||||
|
} |
||||||
|
|
||||||
|
onRemove() { |
||||||
|
this.labelDiv.parentNode.removeChild(this.labelDiv); |
||||||
|
this.eventDiv.parentNode.removeChild(this.eventDiv); |
||||||
|
} |
||||||
|
|
||||||
|
private createElements(): void { |
||||||
|
this.labelDiv = document.createElement("div"); |
||||||
|
this.eventDiv = document.createElement("div"); |
||||||
|
|
||||||
|
// default class names
|
||||||
|
this.labelDiv.classList.add(LABEL_CLASS); |
||||||
|
this.labelDiv.classList.add(EVENT_CLASS); |
||||||
|
|
||||||
|
// default styles for both divs
|
||||||
|
this.labelDiv.style.position = ABSOLUTE; |
||||||
|
this.eventDiv.style.position = ABSOLUTE; |
||||||
|
|
||||||
|
// default styles for eventDiv
|
||||||
|
this.eventDiv.style.opacity = EVENT_DIV_OPACITY; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,30 @@ |
|||||||
|
/** |
||||||
|
* Copyright 2020 Google LLC. All Rights Reserved. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
import {extend} from "./util"; |
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||||
|
export interface MarkerSafe extends google.maps.Marker {} |
||||||
|
|
||||||
|
/** |
||||||
|
* @ignore |
||||||
|
*/ |
||||||
|
export class MarkerSafe { |
||||||
|
constructor(options: google.maps.MarkerOptions) { |
||||||
|
extend(MarkerSafe, google.maps.Marker); |
||||||
|
google.maps.Marker.call(this, options); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,262 @@ |
|||||||
|
/** |
||||||
|
* Copyright 2020 Google LLC. All Rights Reserved. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
import { abortEvent, stopPropagation } from "./util"; |
||||||
|
|
||||||
|
import { Label } from "./label"; |
||||||
|
import { MarkerSafe } from "./marker-safe"; |
||||||
|
|
||||||
|
const CLICK = "click"; |
||||||
|
const DBLCLICK = "dblclick"; |
||||||
|
const DRAG = "drag"; |
||||||
|
const DRAGEND = "dragend"; |
||||||
|
const DRAGSTART = "dragstart"; |
||||||
|
const MOUSEDOWN = "mousedown"; |
||||||
|
const MOUSEMOVE = "mousemove"; |
||||||
|
const MOUSEOVER = "mouseover"; |
||||||
|
const MOUSEOUT = "mouseout"; |
||||||
|
const MOUSEUP = "mouseup"; |
||||||
|
|
||||||
|
export interface MarkerWithLabelOptions extends google.maps.MarkerOptions { |
||||||
|
labelContent: string | HTMLElement; |
||||||
|
labelAnchor?: google.maps.Point; |
||||||
|
labelZIndexOffset?: number; |
||||||
|
labelClass?: string; |
||||||
|
} |
||||||
|
|
||||||
|
export class MarkerWithLabel extends MarkerSafe { |
||||||
|
private label: Label; |
||||||
|
private propertyListeners: google.maps.MapsEventListener[]; |
||||||
|
private interactiveListeners: google.maps.MapsEventListener[]; |
||||||
|
private isTouchScreen = false; |
||||||
|
private isDraggingLabel = false; |
||||||
|
private isMouseDownOnLabel = false; |
||||||
|
private shouldIgnoreClick = false; |
||||||
|
private eventOffset: google.maps.Point | null; |
||||||
|
private mouseOutTimeout: number; |
||||||
|
|
||||||
|
constructor(options: MarkerWithLabelOptions) { |
||||||
|
super({ ...options }); |
||||||
|
this.label = new Label({ ...{}, ...options }); |
||||||
|
|
||||||
|
this.propertyListeners = [ |
||||||
|
google.maps.event.addListener( |
||||||
|
this, |
||||||
|
"clickable_changed", |
||||||
|
this.handleClickableOrDraggableChange |
||||||
|
), |
||||||
|
google.maps.event.addListener(this, "cursor_changed", () => { |
||||||
|
this.label.cursor = this.getCursor(); |
||||||
|
}), |
||||||
|
google.maps.event.addListener( |
||||||
|
this, |
||||||
|
"draggable_changed", |
||||||
|
this.handleClickableOrDraggableChange |
||||||
|
), |
||||||
|
google.maps.event.addListener(this, "position_changed", () => { |
||||||
|
this.label.position = this.getPosition(); |
||||||
|
}), |
||||||
|
google.maps.event.addListener(this, "opacity_changed", () => { |
||||||
|
this.label.opacity = this.getOpacity(); |
||||||
|
}), |
||||||
|
google.maps.event.addListener(this, "title_changed", () => { |
||||||
|
this.label.title = this.getTitle(); |
||||||
|
}), |
||||||
|
google.maps.event.addListener(this, "visible_changed", () => { |
||||||
|
this.label.visible = this.getVisible(); |
||||||
|
}), |
||||||
|
google.maps.event.addListener(this, "zindex_changed", () => { |
||||||
|
this.label.zIndex = this.getZIndex(); |
||||||
|
this.label.draw(); |
||||||
|
}), |
||||||
|
]; |
||||||
|
} |
||||||
|
|
||||||
|
get isInteractive() { |
||||||
|
return this.getClickable() || this.getDraggable(); |
||||||
|
} |
||||||
|
|
||||||
|
setMap(map: google.maps.Map | google.maps.StreetViewPanorama | null): void { |
||||||
|
super.setMap(map); |
||||||
|
setTimeout(() => { |
||||||
|
this.label.setMap(map); |
||||||
|
this.removeInteractiveListeners(); |
||||||
|
if (map) { |
||||||
|
this.addInteractiveListeners(); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
private handleClickableOrDraggableChange() { |
||||||
|
this.label.clickable = this.getClickable(); |
||||||
|
this.label.draggable = this.getDraggable(); |
||||||
|
|
||||||
|
if (this.isInteractive) { |
||||||
|
this.addInteractiveListeners(); |
||||||
|
} else { |
||||||
|
this.removeInteractiveListeners(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private removeInteractiveListeners() { |
||||||
|
if (this.interactiveListeners) { |
||||||
|
this.interactiveListeners.forEach((l) => |
||||||
|
google.maps.event.removeListener(l) |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private addInteractiveListeners() { |
||||||
|
if (!this.interactiveListeners) { |
||||||
|
this.interactiveListeners = [ |
||||||
|
this.label.addDomListener(MOUSEOVER, (e) => { |
||||||
|
if (!this.isTouchScreen) { |
||||||
|
google.maps.event.trigger(this, MOUSEOVER, { |
||||||
|
latLng: this.getPosition(), |
||||||
|
}); |
||||||
|
|
||||||
|
abortEvent(e); |
||||||
|
} |
||||||
|
}), |
||||||
|
this.label.addDomListener(MOUSEOUT, (e) => { |
||||||
|
if (!this.isTouchScreen) { |
||||||
|
|
||||||
|
// wrap the mouseout event in a timeout to avoid the case where mouseup occurs out
|
||||||
|
if (this.mouseOutTimeout) { |
||||||
|
clearTimeout(this.mouseOutTimeout); |
||||||
|
} |
||||||
|
this.mouseOutTimeout = setTimeout(() => { |
||||||
|
if (this.isMouseDownOnLabel) { |
||||||
|
this.isMouseDownOnLabel = false; |
||||||
|
google.maps.event.trigger(this, MOUSEUP, { |
||||||
|
latLng: this.getPosition(), |
||||||
|
}); |
||||||
|
|
||||||
|
if (this.isDraggingLabel) { |
||||||
|
this.isDraggingLabel = false; |
||||||
|
this.shouldIgnoreClick = true; |
||||||
|
google.maps.event.trigger(this, DRAGEND, { |
||||||
|
latLng: this.getPosition(), |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
google.maps.event.trigger(this, MOUSEOUT, { |
||||||
|
latLng: this.getPosition(), |
||||||
|
}); |
||||||
|
}, 200); |
||||||
|
|
||||||
|
abortEvent(e); |
||||||
|
} |
||||||
|
}), |
||||||
|
this.label.addDomListener(MOUSEDOWN, (e) => { |
||||||
|
this.isDraggingLabel = false; |
||||||
|
this.isMouseDownOnLabel = true; |
||||||
|
google.maps.event.trigger(this, MOUSEDOWN, { |
||||||
|
latLng: this.getPosition(), |
||||||
|
}); |
||||||
|
if (!this.isTouchScreen) { |
||||||
|
abortEvent(e); |
||||||
|
} |
||||||
|
}), |
||||||
|
this.label.addDomListener(MOUSEUP, (e) => { |
||||||
|
const markerEvent = { latLng: this.getPosition() }; |
||||||
|
|
||||||
|
if (this.isMouseDownOnLabel) { |
||||||
|
this.isMouseDownOnLabel = false; |
||||||
|
|
||||||
|
google.maps.event.trigger(this, MOUSEUP, markerEvent); |
||||||
|
|
||||||
|
if (this.isDraggingLabel) { |
||||||
|
this.isDraggingLabel = false; |
||||||
|
this.shouldIgnoreClick = true; |
||||||
|
google.maps.event.trigger(this, DRAGEND, markerEvent); |
||||||
|
} |
||||||
|
|
||||||
|
if (!this.getDraggable()) { |
||||||
|
abortEvent(e); |
||||||
|
} |
||||||
|
} |
||||||
|
}), |
||||||
|
this.label.addDomListener(CLICK, (e) => { |
||||||
|
if (this.shouldIgnoreClick) { |
||||||
|
this.shouldIgnoreClick = false; |
||||||
|
} else { |
||||||
|
google.maps.event.trigger(this, CLICK, { |
||||||
|
latLng: this.getPosition(), |
||||||
|
}); |
||||||
|
} |
||||||
|
abortEvent(e); |
||||||
|
}), |
||||||
|
this.label.addDomListener(DBLCLICK, (e) => { |
||||||
|
google.maps.event.trigger(this, DBLCLICK, { |
||||||
|
latLng: this.getPosition(), |
||||||
|
}); |
||||||
|
abortEvent(e); |
||||||
|
}), |
||||||
|
google.maps.event.addListener(this.getMap(), MOUSEMOVE, (e) => { |
||||||
|
if (this.isMouseDownOnLabel && this.getDraggable()) { |
||||||
|
if (this.isDraggingLabel) { |
||||||
|
// Adjust for offset
|
||||||
|
const position = new google.maps.LatLng( |
||||||
|
e.latLng.lat() - this.eventOffset.y, |
||||||
|
e.latLng.lng() - this.eventOffset.x |
||||||
|
); |
||||||
|
// this.setPosition(position);
|
||||||
|
google.maps.event.trigger(this, DRAG, { |
||||||
|
...e, |
||||||
|
latLng: position, |
||||||
|
}); |
||||||
|
} else { |
||||||
|
this.isDraggingLabel = true; |
||||||
|
|
||||||
|
// Calculate and store event offset from marker position
|
||||||
|
this.eventOffset = new google.maps.Point( |
||||||
|
e.latLng.lng() - this.getPosition().lng(), |
||||||
|
e.latLng.lat() - this.getPosition().lat() |
||||||
|
); |
||||||
|
google.maps.event.trigger(this, DRAGSTART, { |
||||||
|
...e, |
||||||
|
latLng: this.getPosition(), |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
}), |
||||||
|
google.maps.event.addListener(this, DRAGSTART, () => { |
||||||
|
this.label.zIndex = 1000000; |
||||||
|
}), |
||||||
|
google.maps.event.addListener(this, DRAG, ({ latLng }) => { |
||||||
|
this.setPosition(latLng); |
||||||
|
}), |
||||||
|
google.maps.event.addListener(this, DRAGEND, () => { |
||||||
|
this.label.zIndex = this.getZIndex(); |
||||||
|
this.label.draw(); |
||||||
|
}), |
||||||
|
// Prevent touch events from passing through the label DIV to the underlying map.
|
||||||
|
this.label.addDomListener("touchstart", (e) => { |
||||||
|
this.isTouchScreen = true; |
||||||
|
stopPropagation(e); |
||||||
|
}), |
||||||
|
this.label.addDomListener("touchmove", (e) => { |
||||||
|
stopPropagation(e); |
||||||
|
}), |
||||||
|
this.label.addDomListener("touchend", (e) => { |
||||||
|
stopPropagation(e); |
||||||
|
}), |
||||||
|
]; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,29 @@ |
|||||||
|
/** |
||||||
|
* Copyright 2019 Google LLC. All Rights Reserved. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
import { extend } from "./util"; |
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||||
|
export interface OverlayViewSafe extends google.maps.OverlayView {} |
||||||
|
|
||||||
|
/** |
||||||
|
* @ignore |
||||||
|
*/ |
||||||
|
export class OverlayViewSafe { |
||||||
|
constructor() { |
||||||
|
extend(OverlayViewSafe, google.maps.OverlayView); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,53 @@ |
|||||||
|
/** |
||||||
|
* Copyright 2020 Google LLC. All Rights Reserved. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
/** |
||||||
|
* Extends an object's prototype by another's. |
||||||
|
* |
||||||
|
* @param type1 The Type to be extended. |
||||||
|
* @param type2 The Type to extend with. |
||||||
|
* @ignore |
||||||
|
*/ |
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
export function extend(type1: any, type2: any): void { |
||||||
|
// eslint-disable-next-line prefer-const
|
||||||
|
for (let property in type2.prototype) { |
||||||
|
type1.prototype[property] = type2.prototype[property]; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
export function abortEvent(e: Event | null) { |
||||||
|
e = e || window.event; |
||||||
|
if (e.stopPropagation) { |
||||||
|
e.stopPropagation(); |
||||||
|
} else { |
||||||
|
e.cancelBubble = true; |
||||||
|
} |
||||||
|
if (e.preventDefault) { |
||||||
|
e.preventDefault(); |
||||||
|
} else { |
||||||
|
e.returnValue = false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
export function stopPropagation(e: Event | null) { |
||||||
|
e = e || window.event; |
||||||
|
if (e.stopPropagation) { |
||||||
|
e.stopPropagation(); |
||||||
|
} else { |
||||||
|
e.cancelBubble = true; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
{ |
||||||
|
"compilerOptions": { |
||||||
|
"declaration": true, |
||||||
|
"declarationDir": "./dist", |
||||||
|
"noImplicitAny": true, |
||||||
|
"outDir": "./dist", |
||||||
|
"sourceMap": true, |
||||||
|
"esModuleInterop": true, |
||||||
|
"lib": ["DOM", "ESNext"], |
||||||
|
"types": ["googlemaps", "jest"], |
||||||
|
"target": "ES6", |
||||||
|
"moduleResolution": "node" |
||||||
|
}, |
||||||
|
"include": ["src/**/*"] |
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
/** |
||||||
|
* Copyright 2020 Google LLC |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
module.exports = { |
||||||
|
mode: "file", |
||||||
|
target: "es6", |
||||||
|
out: "docs", |
||||||
|
exclude: ["**/node_modules/**", "**/*.spec.ts", "**/*.test.ts"], |
||||||
|
name: "", |
||||||
|
excludePrivate: true, |
||||||
|
excludeNotExported: true, |
||||||
|
excludeExternals: true, |
||||||
|
}; |
Loading…
Reference in new issue