44 changed files with 3063 additions and 153 deletions
@ -1,10 +1,124 @@ |
|||||
|
|
||||
<div class="row"> |
<div class="row"> |
||||
<div class="col-12 col-sm-6 col-md-4 border"> |
|
||||
<div id="map"></div> |
|
||||
|
<div class="col-12"> |
||||
|
<div class="section-title">Contatti</div> |
||||
</div> |
</div> |
||||
|
|
||||
<div class="col-12 col-sm-6 col-md-8 border"> |
|
||||
a |
|
||||
|
<div class="col-12 col-sm-12 col-md-7 contacts"> |
||||
|
<i class="fa fa-map-marker"></i> <b>Sede:</b> Via Settimio Mobilio, 17 - SALERNO<br> |
||||
|
<i class="fa fa-phone"></i> <b>Telefono:</b> 089.405080 - 089.795900<br> |
||||
|
<i class="fa fa-fax"></i> <b>Fax:</b> 089.798628<br> |
||||
|
<i class="fa fa-envelope"></i> <b>E-Mail:</b> info@ordinefarmacistisalerno.it<br> |
||||
|
<i class="fa fa-envelope"></i> <b>E-Mail certificata:</b> ordinefarmacistisa@pec.fofi.it <br> |
||||
</div> |
</div> |
||||
|
|
||||
|
<div class="col-12 col-sm-12 col-md-5 mb-2"> |
||||
|
<div id="map"> |
||||
|
<iframe width="100%" height="100%" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="http://maps.google.it/maps?f=q&source=s_q&hl=it&geocode=&q=ordine+farmacisti+salerno&sll=41.442726,12.392578&sspn=17.04957,43.286133&ie=UTF8&hq=ordine+farmacisti&hnear=Salerno+SA&ll=40.685389,14.781933&spn=0.004012,0.014656&z=14&iwloc=A&cid=4099829483191197382&output=embed"></iframe> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
<div class="row last-news"> |
||||
|
|
||||
|
<div class="col-12"> |
||||
|
<div class="section-title">Ultime notizie</div> |
||||
|
|
||||
|
<p class="item"><a href=""><span class="date">07-12-2017 </span> - Chiusura Uffici sabato 9</a></p> |
||||
|
<p class="item"><a href=""><span class="date">07-12-2017 </span> - Chiusura Uffici sabato 9</a></p> |
||||
|
<p class="item"><a href=""><span class="date">07-12-2017 </span> - Chiusura Uffici sabato 9</a></p> |
||||
|
<p class="item"><a href=""><span class="date">07-12-2017 </span> - Chiusura Uffici sabato 9</a></p> |
||||
|
</div> |
||||
|
|
||||
|
<div class="col-12 my-2"> |
||||
|
<p class="text-right"><a class="font-12" href="">Vai a tutte le news <i class="fa fa-angle-right"></i></a></p> |
||||
|
</div> |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
<div class="row p-3"> |
||||
|
<div class="col-12 col-sm-4 col-md-3 spot"> |
||||
|
<div class="content"> |
||||
|
<a href="#"> |
||||
|
<div class="title">Piazza pitagora</div> |
||||
|
<img src="http://unsplash.it/800/600"> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="col-12 col-sm-4 col-md-3 spot"> |
||||
|
<div class="content"> |
||||
|
<a href="#"> |
||||
|
<div class="title">Dipartimento di Farmacia</div> |
||||
|
<img src="http://unsplash.it/800/608"> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="col-12 col-sm-4 col-md-3 spot"> |
||||
|
<div class="content"> |
||||
|
<a href="#"> |
||||
|
<div class="title">Forum degli iscritti</div> |
||||
|
<img src="http://unsplash.it/800/607"> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="col-12 col-sm-4 col-md-3 spot"> |
||||
|
<div class="content"> |
||||
|
<a href="#"> |
||||
|
<div class="title">F.O.F.I.</div> |
||||
|
<img src="http://unsplash.it/800/606"> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="col-12 col-sm-4 col-md-3 spot"> |
||||
|
<div class="content"> |
||||
|
<a href="#"> |
||||
|
<div class="title">ASSO.FA.N.T.</div> |
||||
|
<img src="http://unsplash.it/800/605"> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="col-12 col-sm-4 col-md-3 spot"> |
||||
|
<div class="content"> |
||||
|
<a href="#"> |
||||
|
<div class="title">E.N.P.A.F.</div> |
||||
|
<img src="http://unsplash.it/800/604"> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="col-12 col-sm-4 col-md-3 spot"> |
||||
|
<div class="content"> |
||||
|
<a href="#"> |
||||
|
<div class="title">Federfarma</div> |
||||
|
<img src="http://unsplash.it/800/603"> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="col-12 col-sm-4 col-md-3 spot"> |
||||
|
<div class="content"> |
||||
|
<a href="#"> |
||||
|
<div class="title">Università di Salerno</div> |
||||
|
<img src="http://unsplash.it/800/602"> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="col-12 col-sm-4 col-md-3 spot"> |
||||
|
<div class="content"> |
||||
|
<a href="#"> |
||||
|
<div class="title">Storia dell'Ordine</div> |
||||
|
<img src="http://unsplash.it/800/601"> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
</div> |
</div> |
||||
|
@ -1,11 +1,85 @@ |
|||||
|
|
||||
<div class="col-12 col-sm-12 col-md-2 p-0"> |
<div class="col-12 col-sm-12 col-md-2 p-0"> |
||||
<div class="col-12 col-sm-3 col-md-12 banner"></div> |
|
||||
<div class="col-12 col-sm-3 col-md-12 banner"></div> |
|
||||
<div class="col-12 col-sm-3 col-md-12 banner"></div> |
|
||||
<div class="col-12 col-sm-3 col-md-12 banner"></div> |
|
||||
<div class="col-12 col-sm-3 col-md-12 banner"></div> |
|
||||
<div class="col-12 col-sm-3 col-md-12 banner"></div> |
|
||||
<div class="col-12 col-sm-3 col-md-12 banner"></div> |
|
||||
<div class="col-12 col-sm-3 col-md-12 banner"></div> |
|
||||
|
<div class="banner"> |
||||
|
<div class="content"> |
||||
|
<a href="#"> |
||||
|
<div class="title">Piazza pitagora</div> |
||||
|
<img src="http://unsplash.it/800/600"> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="banner"> |
||||
|
<div class="content"> |
||||
|
<a href="#"> |
||||
|
<div class="title">Dipartimento di Farmacia</div> |
||||
|
<img src="http://unsplash.it/800/608"> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="banner"> |
||||
|
<div class="content"> |
||||
|
<a href="#"> |
||||
|
<div class="title">Forum degli iscritti</div> |
||||
|
<img src="http://unsplash.it/800/607"> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="banner"> |
||||
|
<div class="content"> |
||||
|
<a href="#"> |
||||
|
<div class="title">F.O.F.I.</div> |
||||
|
<img src="http://unsplash.it/800/606"> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="banner"> |
||||
|
<div class="content"> |
||||
|
<a href="#"> |
||||
|
<div class="title">ASSO.FA.N.T.</div> |
||||
|
<img src="http://unsplash.it/800/605"> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="banner"> |
||||
|
<div class="content"> |
||||
|
<a href="#"> |
||||
|
<div class="title">E.N.P.A.F.</div> |
||||
|
<img src="http://unsplash.it/800/604"> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="banner"> |
||||
|
<div class="content"> |
||||
|
<a href="#"> |
||||
|
<div class="title">Federfarma</div> |
||||
|
<img src="http://unsplash.it/800/603"> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="banner"> |
||||
|
<div class="content"> |
||||
|
<a href="#"> |
||||
|
<div class="title">Università di Salerno</div> |
||||
|
<img src="http://unsplash.it/800/602"> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="banner"> |
||||
|
<div class="content"> |
||||
|
<a href="#"> |
||||
|
<div class="title">Storia dell'Ordine</div> |
||||
|
<img src="http://unsplash.it/800/601"> |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
</div> |
</div> |
||||
|
@ -0,0 +1 @@ |
|||||
|
../@google/maps/bin/run.js |
@ -0,0 +1,201 @@ |
|||||
|
Apache License |
||||
|
Version 2.0, January 2004 |
||||
|
http://www.apache.org/licenses/ |
||||
|
|
||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION |
||||
|
|
||||
|
1. Definitions. |
||||
|
|
||||
|
"License" shall mean the terms and conditions for use, reproduction, |
||||
|
and distribution as defined by Sections 1 through 9 of this document. |
||||
|
|
||||
|
"Licensor" shall mean the copyright owner or entity authorized by |
||||
|
the copyright owner that is granting the License. |
||||
|
|
||||
|
"Legal Entity" shall mean the union of the acting entity and all |
||||
|
other entities that control, are controlled by, or are under common |
||||
|
control with that entity. For the purposes of this definition, |
||||
|
"control" means (i) the power, direct or indirect, to cause the |
||||
|
direction or management of such entity, whether by contract or |
||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the |
||||
|
outstanding shares, or (iii) beneficial ownership of such entity. |
||||
|
|
||||
|
"You" (or "Your") shall mean an individual or Legal Entity |
||||
|
exercising permissions granted by this License. |
||||
|
|
||||
|
"Source" form shall mean the preferred form for making modifications, |
||||
|
including but not limited to software source code, documentation |
||||
|
source, and configuration files. |
||||
|
|
||||
|
"Object" form shall mean any form resulting from mechanical |
||||
|
transformation or translation of a Source form, including but |
||||
|
not limited to compiled object code, generated documentation, |
||||
|
and conversions to other media types. |
||||
|
|
||||
|
"Work" shall mean the work of authorship, whether in Source or |
||||
|
Object form, made available under the License, as indicated by a |
||||
|
copyright notice that is included in or attached to the work |
||||
|
(an example is provided in the Appendix below). |
||||
|
|
||||
|
"Derivative Works" shall mean any work, whether in Source or Object |
||||
|
form, that is based on (or derived from) the Work and for which the |
||||
|
editorial revisions, annotations, elaborations, or other modifications |
||||
|
represent, as a whole, an original work of authorship. For the purposes |
||||
|
of this License, Derivative Works shall not include works that remain |
||||
|
separable from, or merely link (or bind by name) to the interfaces of, |
||||
|
the Work and Derivative Works thereof. |
||||
|
|
||||
|
"Contribution" shall mean any work of authorship, including |
||||
|
the original version of the Work and any modifications or additions |
||||
|
to that Work or Derivative Works thereof, that is intentionally |
||||
|
submitted to Licensor for inclusion in the Work by the copyright owner |
||||
|
or by an individual or Legal Entity authorized to submit on behalf of |
||||
|
the copyright owner. For the purposes of this definition, "submitted" |
||||
|
means any form of electronic, verbal, or written communication sent |
||||
|
to the Licensor or its representatives, including but not limited to |
||||
|
communication on electronic mailing lists, source code control systems, |
||||
|
and issue tracking systems that are managed by, or on behalf of, the |
||||
|
Licensor for the purpose of discussing and improving the Work, but |
||||
|
excluding communication that is conspicuously marked or otherwise |
||||
|
designated in writing by the copyright owner as "Not a Contribution." |
||||
|
|
||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity |
||||
|
on behalf of whom a Contribution has been received by Licensor and |
||||
|
subsequently incorporated within the Work. |
||||
|
|
||||
|
2. Grant of Copyright License. Subject to the terms and conditions of |
||||
|
this License, each Contributor hereby grants to You a perpetual, |
||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
||||
|
copyright license to reproduce, prepare Derivative Works of, |
||||
|
publicly display, publicly perform, sublicense, and distribute the |
||||
|
Work and such Derivative Works in Source or Object form. |
||||
|
|
||||
|
3. Grant of Patent License. Subject to the terms and conditions of |
||||
|
this License, each Contributor hereby grants to You a perpetual, |
||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable |
||||
|
(except as stated in this section) patent license to make, have made, |
||||
|
use, offer to sell, sell, import, and otherwise transfer the Work, |
||||
|
where such license applies only to those patent claims licensable |
||||
|
by such Contributor that are necessarily infringed by their |
||||
|
Contribution(s) alone or by combination of their Contribution(s) |
||||
|
with the Work to which such Contribution(s) was submitted. If You |
||||
|
institute patent litigation against any entity (including a |
||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work |
||||
|
or a Contribution incorporated within the Work constitutes direct |
||||
|
or contributory patent infringement, then any patent licenses |
||||
|
granted to You under this License for that Work shall terminate |
||||
|
as of the date such litigation is filed. |
||||
|
|
||||
|
4. Redistribution. You may reproduce and distribute copies of the |
||||
|
Work or Derivative Works thereof in any medium, with or without |
||||
|
modifications, and in Source or Object form, provided that You |
||||
|
meet the following conditions: |
||||
|
|
||||
|
(a) You must give any other recipients of the Work or |
||||
|
Derivative Works a copy of this License; and |
||||
|
|
||||
|
(b) You must cause any modified files to carry prominent notices |
||||
|
stating that You changed the files; and |
||||
|
|
||||
|
(c) You must retain, in the Source form of any Derivative Works |
||||
|
that You distribute, all copyright, patent, trademark, and |
||||
|
attribution notices from the Source form of the Work, |
||||
|
excluding those notices that do not pertain to any part of |
||||
|
the Derivative Works; and |
||||
|
|
||||
|
(d) If the Work includes a "NOTICE" text file as part of its |
||||
|
distribution, then any Derivative Works that You distribute must |
||||
|
include a readable copy of the attribution notices contained |
||||
|
within such NOTICE file, excluding those notices that do not |
||||
|
pertain to any part of the Derivative Works, in at least one |
||||
|
of the following places: within a NOTICE text file distributed |
||||
|
as part of the Derivative Works; within the Source form or |
||||
|
documentation, if provided along with the Derivative Works; or, |
||||
|
within a display generated by the Derivative Works, if and |
||||
|
wherever such third-party notices normally appear. The contents |
||||
|
of the NOTICE file are for informational purposes only and |
||||
|
do not modify the License. You may add Your own attribution |
||||
|
notices within Derivative Works that You distribute, alongside |
||||
|
or as an addendum to the NOTICE text from the Work, provided |
||||
|
that such additional attribution notices cannot be construed |
||||
|
as modifying the License. |
||||
|
|
||||
|
You may add Your own copyright statement to Your modifications and |
||||
|
may provide additional or different license terms and conditions |
||||
|
for use, reproduction, or distribution of Your modifications, or |
||||
|
for any such Derivative Works as a whole, provided Your use, |
||||
|
reproduction, and distribution of the Work otherwise complies with |
||||
|
the conditions stated in this License. |
||||
|
|
||||
|
5. Submission of Contributions. Unless You explicitly state otherwise, |
||||
|
any Contribution intentionally submitted for inclusion in the Work |
||||
|
by You to the Licensor shall be under the terms and conditions of |
||||
|
this License, without any additional terms or conditions. |
||||
|
Notwithstanding the above, nothing herein shall supersede or modify |
||||
|
the terms of any separate license agreement you may have executed |
||||
|
with Licensor regarding such Contributions. |
||||
|
|
||||
|
6. Trademarks. This License does not grant permission to use the trade |
||||
|
names, trademarks, service marks, or product names of the Licensor, |
||||
|
except as required for reasonable and customary use in describing the |
||||
|
origin of the Work and reproducing the content of the NOTICE file. |
||||
|
|
||||
|
7. Disclaimer of Warranty. Unless required by applicable law or |
||||
|
agreed to in writing, Licensor provides the Work (and each |
||||
|
Contributor provides its Contributions) on an "AS IS" BASIS, |
||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
||||
|
implied, including, without limitation, any warranties or conditions |
||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A |
||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the |
||||
|
appropriateness of using or redistributing the Work and assume any |
||||
|
risks associated with Your exercise of permissions under this License. |
||||
|
|
||||
|
8. Limitation of Liability. In no event and under no legal theory, |
||||
|
whether in tort (including negligence), contract, or otherwise, |
||||
|
unless required by applicable law (such as deliberate and grossly |
||||
|
negligent acts) or agreed to in writing, shall any Contributor be |
||||
|
liable to You for damages, including any direct, indirect, special, |
||||
|
incidental, or consequential damages of any character arising as a |
||||
|
result of this License or out of the use or inability to use the |
||||
|
Work (including but not limited to damages for loss of goodwill, |
||||
|
work stoppage, computer failure or malfunction, or any and all |
||||
|
other commercial damages or losses), even if such Contributor |
||||
|
has been advised of the possibility of such damages. |
||||
|
|
||||
|
9. Accepting Warranty or Additional Liability. While redistributing |
||||
|
the Work or Derivative Works thereof, You may choose to offer, |
||||
|
and charge a fee for, acceptance of support, warranty, indemnity, |
||||
|
or other liability obligations and/or rights consistent with this |
||||
|
License. However, in accepting such obligations, You may act only |
||||
|
on Your own behalf and on Your sole responsibility, not on behalf |
||||
|
of any other Contributor, and only if You agree to indemnify, |
||||
|
defend, and hold each Contributor harmless for any liability |
||||
|
incurred by, or claims asserted against, such Contributor by reason |
||||
|
of your accepting any such warranty or additional liability. |
||||
|
|
||||
|
END OF TERMS AND CONDITIONS |
||||
|
|
||||
|
APPENDIX: How to apply the Apache License to your work. |
||||
|
|
||||
|
To apply the Apache License to your work, attach the following |
||||
|
boilerplate notice, with the fields enclosed by brackets "{}" |
||||
|
replaced with your own identifying information. (Don't include |
||||
|
the brackets!) The text should be enclosed in the appropriate |
||||
|
comment syntax for the file format. We also recommend that a |
||||
|
file or class name and description of purpose be included on the |
||||
|
same "printed page" as the copyright notice for easier |
||||
|
identification within third-party archives. |
||||
|
|
||||
|
Copyright {yyyy} {name of copyright owner} |
||||
|
|
||||
|
Licensed under the Apache License, Version 2.0 (the "License"); |
||||
|
you may not use this file except in compliance with the License. |
||||
|
You may obtain a copy of the License at |
||||
|
|
||||
|
http://www.apache.org/licenses/LICENSE-2.0 |
||||
|
|
||||
|
Unless required by applicable law or agreed to in writing, software |
||||
|
distributed under the License is distributed on an "AS IS" BASIS, |
||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
|
See the License for the specific language governing permissions and |
||||
|
limitations under the License. |
@ -0,0 +1,163 @@ |
|||||
|
Node.js Client for Google Maps Services |
||||
|
======================================= |
||||
|
|
||||
|
Use Node.js? Want to [geocode][Geocoding API] something? Looking |
||||
|
for [directions][Directions API]? |
||||
|
This library brings the [Google Maps API Web Services] to your Node.js |
||||
|
application.  |
||||
|
|
||||
|
The Node.js Client for Google Maps Services is a Node.js Client library |
||||
|
for the following Google Maps APIs: |
||||
|
|
||||
|
- [Directions API] |
||||
|
- [Distance Matrix API] |
||||
|
- [Elevation API] |
||||
|
- [Geocoding API] |
||||
|
- [Places API] |
||||
|
- [Roads API] |
||||
|
- [Time Zone API] |
||||
|
|
||||
|
Keep in mind that the same [terms and conditions](https://developers.google.com/maps/terms) |
||||
|
apply to usage of the APIs when they're accessed through this library. |
||||
|
|
||||
|
## Features |
||||
|
|
||||
|
- **Retry on Failure** Automatically retry when intermittent failures occur. |
||||
|
That is, when any of the retryable 5xx errors are returned from the API. |
||||
|
|
||||
|
- **Rate-limiting** Requests are rate-limited by the client, which helps |
||||
|
prevent reaching the server-enforced rate limit. |
||||
|
|
||||
|
## Quick Start |
||||
|
|
||||
|
$ npm install @google/maps |
||||
|
|
||||
|
**Note:** You'll need to have npm 2.7.0 or greater installed, since this library is hosted as a |
||||
|
[scoped package](https://docs.npmjs.com/getting-started/scoped-packages). |
||||
|
|
||||
|
Create a new client object by calling `createClient()` |
||||
|
|
||||
|
```js |
||||
|
var googleMapsClient = require('@google/maps').createClient({ |
||||
|
key: 'your API key here' |
||||
|
}); |
||||
|
``` |
||||
|
|
||||
|
Make requests to the Google Maps APIs by calling methods on the client object. |
||||
|
|
||||
|
```js |
||||
|
// Geocode an address. |
||||
|
googleMapsClient.geocode({ |
||||
|
address: '1600 Amphitheatre Parkway, Mountain View, CA' |
||||
|
}, function(err, response) { |
||||
|
if (!err) { |
||||
|
console.log(response.json.results); |
||||
|
} |
||||
|
}); |
||||
|
``` |
||||
|
|
||||
|
For more usage examples, check out [the tests](spec/e2e/). |
||||
|
|
||||
|
View the [reference documentation](https://googlemaps.github.io/google-maps-services-js/docs/) |
||||
|
|
||||
|
Additional documentation for the included web services is available at |
||||
|
https://developers.google.com/maps/. |
||||
|
|
||||
|
## API keys |
||||
|
|
||||
|
Each Google Maps Web Service request requires an API key or client ID. API keys |
||||
|
are freely available with a Google Account at |
||||
|
https://developers.google.com/console. The type of API key you need is a |
||||
|
**Server key**. |
||||
|
|
||||
|
To get an API key: |
||||
|
|
||||
|
1. Visit https://developers.google.com/console and log in with |
||||
|
a Google Account. |
||||
|
1. Select one of your existing projects, or create a new project. |
||||
|
1. Enable the API(s) you want to use. The Node.js Client for Google Maps Services |
||||
|
accesses the following APIs: |
||||
|
* Directions API |
||||
|
* Distance Matrix API |
||||
|
* Elevation API |
||||
|
* Geocoding API |
||||
|
* Places API |
||||
|
* Roads API |
||||
|
* Time Zone API |
||||
|
1. Create a new **Server key**. |
||||
|
1. If you'd like to restrict requests to a specific IP address, do so now. |
||||
|
|
||||
|
For guided help, follow the instructions for the [Directions API][directions-key]. You only need one API key, but |
||||
|
remember to enable all the APIs you need. |
||||
|
For even more information, see the guide to [API keys][apikey]. |
||||
|
|
||||
|
When you have an API key, you can create a client object: |
||||
|
|
||||
|
```js |
||||
|
var googleMapsClient = require('@google/maps').createClient({ |
||||
|
key: 'your API key here' |
||||
|
}); |
||||
|
``` |
||||
|
|
||||
|
### Client IDs |
||||
|
|
||||
|
Google Maps APIs Premium Plan customers can use their [client ID and secret][clientid] to authenticate, |
||||
|
instead of an API key. |
||||
|
|
||||
|
```js |
||||
|
var googleMapsClient = require('@google/maps').createClient({ |
||||
|
clientId: 'Add your client ID here', |
||||
|
clientSecret: 'Add your client secret here', |
||||
|
}); |
||||
|
``` |
||||
|
|
||||
|
**Important:** This key should be kept secret on your server. |
||||
|
|
||||
|
## Developing |
||||
|
|
||||
|
In order to run the end-to-end tests, you'll need to supply your API key via an |
||||
|
environment variable. |
||||
|
|
||||
|
$ export GOOGLE_MAPS_API_KEY=AIza-your-api-key |
||||
|
$ npm test |
||||
|
|
||||
|
## Support |
||||
|
|
||||
|
This library is community supported. We're comfortable enough with the |
||||
|
stability and features of the library that we want you to build real |
||||
|
production applications on it. We will try to support, through Stack |
||||
|
Overflow, the public surface of the library and maintain |
||||
|
backwards compatibility in the future; however, while the library is in |
||||
|
version 0.x, we reserve the right to make backwards-incompatible |
||||
|
changes. If we do remove some functionality (typically because better |
||||
|
functionality exists or if the feature proved infeasible), our intention |
||||
|
is to deprecate and give developers a year to update their code. |
||||
|
|
||||
|
If you find a bug, or have a feature suggestion, please |
||||
|
[log an issue][issues]. If you'd like to contribute, please read |
||||
|
[How to Contribute][contrib]. |
||||
|
|
||||
|
## Command-line Interface |
||||
|
|
||||
|
Installing via npm also provides the `googlemaps` command-line utility, |
||||
|
which can then be used to pipe JSON results to other command-line programs: |
||||
|
|
||||
|
``` |
||||
|
$ googlemaps directions --origin 'Sydney Town Hall' --destination 'Parramatta, NSW' |
||||
|
``` |
||||
|
|
||||
|
[apikey]: https://developers.google.com/maps/faq#keysystem |
||||
|
[clientid]: https://developers.google.com/maps/documentation/business/webservices/auth |
||||
|
|
||||
|
[Google Maps API Web Services]: https://developers.google.com/maps/documentation/webservices/ |
||||
|
[Directions API]: https://developers.google.com/maps/documentation/directions/ |
||||
|
[directions-key]: https://developers.google.com/maps/documentation/directions/get-api-key#key |
||||
|
[Distance Matrix API]: https://developers.google.com/maps/documentation/distancematrix/ |
||||
|
[Elevation API]: https://developers.google.com/maps/documentation/elevation/ |
||||
|
[Geocoding API]: https://developers.google.com/maps/documentation/geocoding/ |
||||
|
[Time Zone API]: https://developers.google.com/maps/documentation/timezone/ |
||||
|
[Roads API]: https://developers.google.com/maps/documentation/roads/ |
||||
|
[Places API]: https://developers.google.com/places/web-service/ |
||||
|
|
||||
|
[issues]: https://github.com/googlemaps/google-maps-services-js/issues |
||||
|
[contrib]: https://github.com/googlemaps/google-maps-services-js/blob/master/CONTRIBUTING.md |
@ -0,0 +1,28 @@ |
|||||
|
#!/usr/bin/env node
|
||||
|
|
||||
|
/** |
||||
|
* @license |
||||
|
* Copyright 2016 Google Inc. 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. |
||||
|
*/ |
||||
|
|
||||
|
var lib = require('@google/maps'); |
||||
|
var args = process.argv.slice(3); |
||||
|
var apiCall = lib.createClient()[process.argv[2]]; |
||||
|
|
||||
|
try { |
||||
|
apiCall(lib.cli.parseArgs(args), lib.cli.callback); |
||||
|
} catch (error) { |
||||
|
console.log("Error:", error.message); |
||||
|
} |
@ -0,0 +1,94 @@ |
|||||
|
/** |
||||
|
* @license |
||||
|
* Copyright 2016 Google Inc. 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. |
||||
|
*/; |
||||
|
|
||||
|
var utils = require('../internal/convert'); |
||||
|
var v = require('../internal/validate'); |
||||
|
|
||||
|
/** |
||||
|
* Makes a directions request. |
||||
|
* |
||||
|
* @name GoogleMapsClient#directions |
||||
|
* @function |
||||
|
* @param {Object} query |
||||
|
* @param {LatLng} query.origin |
||||
|
* @param {LatLng} query.destination |
||||
|
* @param {string} [query.mode] |
||||
|
* @param {LatLng[]} [query.waypoints] |
||||
|
* @param {boolean} [query.alternatives] |
||||
|
* @param {string[]} [query.avoid] |
||||
|
* @param {string} [query.language] |
||||
|
* @param {string} [query.units] |
||||
|
* @param {string} [query.region] |
||||
|
* @param {Date|number} [query.departure_time] |
||||
|
* @param {Date|number} [query.arrival_time] |
||||
|
* @param {string} [query.traffic_model] |
||||
|
* @param {string[]} [query.transit_mode] |
||||
|
* @param {string} [query.transit_routing_preference] |
||||
|
* @param {boolean} [query.optimize] |
||||
|
* @param {ResponseCallback} callback Callback function for handling the result |
||||
|
* @return {RequestHandle} |
||||
|
*/ |
||||
|
exports.directions = { |
||||
|
url: 'https://maps.googleapis.com/maps/api/directions/json', |
||||
|
validator: v.compose([ |
||||
|
v.mutuallyExclusiveProperties(['arrival_time', 'departure_time']), |
||||
|
v.object({ |
||||
|
origin: utils.latLng, |
||||
|
destination: utils.latLng, |
||||
|
mode: v.optional(v.oneOf([ |
||||
|
'driving', 'walking', 'bicycling', 'transit' |
||||
|
])), |
||||
|
waypoints: v.optional(utils.pipedArrayOf(utils.latLng)), |
||||
|
alternatives: v.optional(v.boolean), |
||||
|
avoid: v.optional(utils.pipedArrayOf(v.oneOf([ |
||||
|
'tolls', 'highways', 'ferries', 'indoor' |
||||
|
]))), |
||||
|
language: v.optional(v.string), |
||||
|
units: v.optional(v.oneOf(['metric', 'imperial'])), |
||||
|
region: v.optional(v.string), |
||||
|
departure_time: v.optional(utils.timeStamp), |
||||
|
arrival_time: v.optional(utils.timeStamp), |
||||
|
traffic_model: v.optional(v.oneOf([ |
||||
|
'best_guess', 'pessimistic', 'optimistic' |
||||
|
])), |
||||
|
transit_mode: v.optional(utils.pipedArrayOf(v.oneOf([ |
||||
|
'bus', 'subway', 'train', 'tram', 'rail' |
||||
|
]))), |
||||
|
transit_routing_preference: v.optional(v.oneOf([ |
||||
|
'less_walking', 'fewer_transfers' |
||||
|
])), |
||||
|
optimize: v.optional(v.boolean), |
||||
|
retryOptions: v.optional(utils.retryOptions), |
||||
|
timeout: v.optional(v.number) |
||||
|
}), |
||||
|
function(query) { |
||||
|
if (query.waypoints && query.optimize) { |
||||
|
query.waypoints = 'optimize:true|' + query.waypoints; |
||||
|
} |
||||
|
delete query.optimize; |
||||
|
|
||||
|
if (query.waypoints && query.mode === 'transit') { |
||||
|
throw new v.InvalidValueError('cannot specify waypoints with transit'); |
||||
|
} |
||||
|
|
||||
|
if (query.traffic_model && !query.departure_time) { |
||||
|
throw new v.InvalidValueError('traffic_model requires departure_time'); |
||||
|
} |
||||
|
return query; |
||||
|
} |
||||
|
]) |
||||
|
}; |
@ -0,0 +1,72 @@ |
|||||
|
/** |
||||
|
* @license |
||||
|
* Copyright 2016 Google Inc. 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. |
||||
|
*/; |
||||
|
|
||||
|
var utils = require('../internal/convert'); |
||||
|
var v = require('../internal/validate'); |
||||
|
|
||||
|
/** |
||||
|
* Makes a distance matrix request. |
||||
|
* |
||||
|
* @name GoogleMapsClient#distanceMatrix |
||||
|
* @function |
||||
|
* @param {Object} query |
||||
|
* @param {LatLng[]} query.origins |
||||
|
* @param {LatLng[]} query.destinations |
||||
|
* @param {string} [query.mode] |
||||
|
* @param {string} [query.language] |
||||
|
* @param {string[]} [query.avoid] |
||||
|
* @param {string} [query.units] |
||||
|
* @param {Date|number} [query.departure_time] |
||||
|
* @param {Date|number} [query.arrival_time] |
||||
|
* @param {string[]} [query.transit_mode] |
||||
|
* @param {string} [query.transit_routing_preference] |
||||
|
* @param {string} [query.traffic_model] |
||||
|
* @param {ResponseCallback} callback Callback function for handling the result |
||||
|
* @return {RequestHandle} |
||||
|
*/ |
||||
|
exports.distanceMatrix = { |
||||
|
url: 'https://maps.googleapis.com/maps/api/distancematrix/json', |
||||
|
validator: v.compose([ |
||||
|
v.mutuallyExclusiveProperties(['arrival_time', 'departure_time']), |
||||
|
v.object({ |
||||
|
origins: utils.pipedArrayOf(utils.latLng), |
||||
|
destinations: utils.pipedArrayOf(utils.latLng), |
||||
|
mode: v.optional(v.oneOf([ |
||||
|
'driving', 'walking', 'bicycling', 'transit' |
||||
|
])), |
||||
|
language: v.optional(v.string), |
||||
|
region: v.optional(v.string), |
||||
|
avoid: v.optional(utils.pipedArrayOf(v.oneOf([ |
||||
|
'tolls', 'highways', 'ferries', 'indoor' |
||||
|
]))), |
||||
|
units: v.optional(v.oneOf(['metric', 'imperial'])), |
||||
|
departure_time: v.optional(utils.timeStamp), |
||||
|
arrival_time: v.optional(utils.timeStamp), |
||||
|
transit_mode: v.optional(utils.pipedArrayOf(v.oneOf([ |
||||
|
'bus', 'subway', 'train', 'tram', 'rail' |
||||
|
]))), |
||||
|
transit_routing_preference: v.optional(v.oneOf([ |
||||
|
'less_walking', 'fewer_transfers' |
||||
|
])), |
||||
|
traffic_model: v.optional(v.oneOf([ |
||||
|
'best_guess', 'pessimistic', 'optimistic' |
||||
|
])), |
||||
|
retryOptions: v.optional(utils.retryOptions), |
||||
|
timeout: v.optional(v.number) |
||||
|
}) |
||||
|
]) |
||||
|
}; |
@ -0,0 +1,65 @@ |
|||||
|
/** |
||||
|
* @license |
||||
|
* Copyright 2016 Google Inc. 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. |
||||
|
*/; |
||||
|
|
||||
|
var utils = require('../internal/convert'); |
||||
|
var v = require('../internal/validate'); |
||||
|
|
||||
|
/** |
||||
|
* Makes an elevation request. |
||||
|
* |
||||
|
* @name GoogleMapsClient#elevation |
||||
|
* @function |
||||
|
* @param {Object} query |
||||
|
* @param {LatLng[]} query.locations |
||||
|
* @param {ResponseCallback} callback Callback function for handling the result |
||||
|
* @return {RequestHandle} |
||||
|
*/ |
||||
|
exports.elevation = { |
||||
|
url: 'https://maps.googleapis.com/maps/api/elevation/json', |
||||
|
validator: v.object({ |
||||
|
locations: utils.pipedArrayOf(utils.latLng), |
||||
|
retryOptions: v.optional(utils.retryOptions), |
||||
|
timeout: v.optional(v.number) |
||||
|
}) |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* Makes an elevation-along-path request. |
||||
|
* |
||||
|
* @name GoogleMapsClient#elevationAlongPath |
||||
|
* @function |
||||
|
* @param {Object} query |
||||
|
* @param {LatLng[]|string} query.path |
||||
|
* @param {number} query.samples |
||||
|
* @param {ResponseCallback} callback Callback function for handling the result |
||||
|
* @return {RequestHandle} |
||||
|
*/ |
||||
|
exports.elevationAlongPath = { |
||||
|
url: 'https://maps.googleapis.com/maps/api/elevation/json', |
||||
|
validator: v.object({ |
||||
|
path: function(path) { |
||||
|
if (typeof path == 'string') { |
||||
|
return 'enc:' + path; |
||||
|
} else { |
||||
|
return utils.pipedArrayOf(utils.latLng)(path); |
||||
|
} |
||||
|
}, |
||||
|
samples: v.number, |
||||
|
retryOptions: v.optional(utils.retryOptions), |
||||
|
timeout: v.optional(v.number) |
||||
|
}) |
||||
|
}; |
@ -0,0 +1,84 @@ |
|||||
|
/** |
||||
|
* @license |
||||
|
* Copyright 2016 Google Inc. 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. |
||||
|
*/; |
||||
|
|
||||
|
var utils = require('../internal/convert'); |
||||
|
var v = require('../internal/validate'); |
||||
|
|
||||
|
/** |
||||
|
* Makes a geocode request. |
||||
|
* |
||||
|
* @name GoogleMapsClient#geocode |
||||
|
* @function |
||||
|
* @param {Object} query |
||||
|
* @param {string} [query.address] |
||||
|
* @param {Object} [query.components] |
||||
|
* @param {Object} [query.bounds] |
||||
|
* @param {number} query.bounds.south |
||||
|
* @param {number} query.bounds.west |
||||
|
* @param {number} query.bounds.north |
||||
|
* @param {number} query.bounds.east |
||||
|
* @param {string} [query.region] |
||||
|
* @param {string} [query.language] |
||||
|
* @param {ResponseCallback} callback Callback function for handling the result |
||||
|
* @return {RequestHandle} |
||||
|
*/ |
||||
|
exports.geocode = { |
||||
|
url: 'https://maps.googleapis.com/maps/api/geocode/json', |
||||
|
validator: v.object({ |
||||
|
address: v.optional(v.string), |
||||
|
components: v.optional(utils.pipedKeyValues), |
||||
|
bounds: v.optional(utils.bounds), |
||||
|
region: v.optional(v.string), |
||||
|
language: v.optional(v.string), |
||||
|
retryOptions: v.optional(utils.retryOptions), |
||||
|
timeout: v.optional(v.number) |
||||
|
}) |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* Makes a reverse geocode request. |
||||
|
* |
||||
|
* @name GoogleMapsClient#reverseGeocode |
||||
|
* @function |
||||
|
* @param {Object} query |
||||
|
* @param {LatLng} [query.latlng] |
||||
|
* @param {string} [query.place_id] |
||||
|
* @param {string} [query.result_type] |
||||
|
* @param {string} [query.location_type] |
||||
|
* @param {string} [query.language] |
||||
|
* @param {ResponseCallback} callback Callback function for handling the result |
||||
|
* @return {RequestHandle} |
||||
|
*/ |
||||
|
exports.reverseGeocode = { |
||||
|
url: 'https://maps.googleapis.com/maps/api/geocode/json', |
||||
|
validator: v.compose([ |
||||
|
v.mutuallyExclusiveProperties(['place_id', 'latlng']), |
||||
|
v.mutuallyExclusiveProperties(['place_id', 'result_type']), |
||||
|
v.mutuallyExclusiveProperties(['place_id', 'location_type']), |
||||
|
v.object({ |
||||
|
latlng: v.optional(utils.latLng), |
||||
|
place_id: v.optional(v.string), |
||||
|
result_type: v.optional(utils.pipedArrayOf(v.string)), |
||||
|
location_type: v.optional(utils.pipedArrayOf(v.oneOf([ |
||||
|
'ROOFTOP', 'RANGE_INTERPOLATED', 'GEOMETRIC_CENTER', 'APPROXIMATE' |
||||
|
]))), |
||||
|
language: v.optional(v.string), |
||||
|
retryOptions: v.optional(utils.retryOptions), |
||||
|
timeout: v.optional(v.number) |
||||
|
}) |
||||
|
]) |
||||
|
}; |
@ -0,0 +1,76 @@ |
|||||
|
/** |
||||
|
* @license |
||||
|
* Copyright 2017 Google Inc. 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. |
||||
|
*/ |
||||
|
|
||||
|
var utils = require('../internal/convert'); |
||||
|
var v = require('../internal/validate'); |
||||
|
|
||||
|
/** |
||||
|
* Makes a geolocation request. |
||||
|
* |
||||
|
* For a detailed guide, see https://developers.google.com/maps/documentation/geolocation/intro
|
||||
|
* |
||||
|
* @name GoogleMapsClient#geolocate |
||||
|
* @function |
||||
|
* @param {Object} query |
||||
|
* @param {number} [query.homeMobileCountryCode] |
||||
|
* @param {number} [query.homeMobileNetworkCode] |
||||
|
* @param {string} [query.radioType] |
||||
|
* @param {string} [query.carrier] |
||||
|
* @param {boolean} [query.considerIp] |
||||
|
* @param {Object[]} [query.cellTowers] |
||||
|
* @param {Object[]} [query.wifiAccessPoints] |
||||
|
* @param {ResponseCallback} callback Callback function for handling the result |
||||
|
* @return {RequestHandle} |
||||
|
*/ |
||||
|
exports.geolocate = { |
||||
|
url: 'https://www.googleapis.com/geolocation/v1/geolocate', |
||||
|
options: { |
||||
|
method: 'POST', |
||||
|
headers: {'content-type': 'application/json;'}, |
||||
|
canRetry: function(response) { |
||||
|
return response.status === 403; |
||||
|
}, |
||||
|
isSuccessful: function(response) { |
||||
|
return response.status === 200 || response.status === 404; |
||||
|
} |
||||
|
}, |
||||
|
validator: v.object({ |
||||
|
homeMobileCountryCode: v.optional(v.number), |
||||
|
homeMobileNetworkCode: v.optional(v.number), |
||||
|
radioType: v.optional(v.string), |
||||
|
carrier: v.optional(v.string), |
||||
|
considerIp: v.optional(v.boolean), |
||||
|
cellTowers: v.optional(v.array(v.object({ |
||||
|
cellId: v.number, |
||||
|
locationAreaCode: v.number, |
||||
|
mobileCountryCode: v.number, |
||||
|
mobileNetworkCode: v.number, |
||||
|
age: v.optional(v.number), |
||||
|
signalStrength: v.optional(v.number), |
||||
|
timingAdvance: v.optional(v.number) |
||||
|
}))), |
||||
|
wifiAccessPoints: v.optional(v.array(v.object({ |
||||
|
macAddress: v.string, |
||||
|
signalStrength: v.optional(v.number), |
||||
|
age: v.optional(v.number), |
||||
|
channel: v.optional(v.number), |
||||
|
signalToNoiseRatio: v.optional(v.number) |
||||
|
}))), |
||||
|
retryOptions: v.optional(utils.retryOptions), |
||||
|
timeout: v.optional(v.number) |
||||
|
}) |
||||
|
}; |
@ -0,0 +1,233 @@ |
|||||
|
/** |
||||
|
* @license |
||||
|
* Copyright 2016 Google Inc. 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. |
||||
|
*/; |
||||
|
|
||||
|
var utils = require('../internal/convert'); |
||||
|
var v = require('../internal/validate'); |
||||
|
|
||||
|
/** |
||||
|
* Makes a places request. |
||||
|
* |
||||
|
* @name GoogleMapsClient#places |
||||
|
* @function |
||||
|
* @param {Object} query |
||||
|
* @param {string} query.query |
||||
|
* @param {string} [query.language] |
||||
|
* @param {LatLng} [query.location] |
||||
|
* @param {number} [query.radius] |
||||
|
* @param {number} [query.minprice] |
||||
|
* @param {number} [query.maxprice] |
||||
|
* @param {boolean} [query.opennow] |
||||
|
* @param {string} [query.type] |
||||
|
* @param {string} [query.pagetoken] |
||||
|
* @param {ResponseCallback} callback Callback function for handling the result |
||||
|
* @return {RequestHandle} |
||||
|
*/ |
||||
|
exports.places = { |
||||
|
url: 'https://maps.googleapis.com/maps/api/place/textsearch/json', |
||||
|
validator: v.object({ |
||||
|
query: v.optional(v.string), |
||||
|
language: v.optional(v.string), |
||||
|
location: v.optional(utils.latLng), |
||||
|
radius: v.optional(v.number), |
||||
|
minprice: v.optional(v.number), |
||||
|
maxprice: v.optional(v.number), |
||||
|
opennow: v.optional(v.boolean), |
||||
|
type: v.optional(v.string), |
||||
|
pagetoken: v.optional(v.string), |
||||
|
retryOptions: v.optional(utils.retryOptions), |
||||
|
timeout: v.optional(v.number) |
||||
|
}) |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* Makes a nearby places request. |
||||
|
* |
||||
|
* @name GoogleMapsClient#placesNearby |
||||
|
* @function |
||||
|
* @param {Object} query |
||||
|
* @param {LatLng} query.location |
||||
|
* @param {string} [query.language] |
||||
|
* @param {number} [query.radius] |
||||
|
* @param {string} [query.keyword] |
||||
|
* @param {number} [query.minprice] |
||||
|
* @param {number} [query.maxprice] |
||||
|
* @param {string} [query.name] |
||||
|
* @param {boolean} [query.opennow] |
||||
|
* @param {string} [query.rankby] Either 'prominence' or 'distance' |
||||
|
* @param {string} [query.type] |
||||
|
* @param {string} [query.pagetoken] |
||||
|
* @param {ResponseCallback} callback Callback function for handling the result |
||||
|
* @return {RequestHandle} |
||||
|
*/ |
||||
|
exports.placesNearby = { |
||||
|
url: 'https://maps.googleapis.com/maps/api/place/nearbysearch/json', |
||||
|
validator: v.object({ |
||||
|
location: utils.latLng, |
||||
|
language: v.optional(v.string), |
||||
|
radius: v.optional(v.number), |
||||
|
keyword: v.optional(v.string), |
||||
|
minprice: v.optional(v.number), |
||||
|
maxprice: v.optional(v.number), |
||||
|
name: v.optional(v.string), |
||||
|
opennow: v.optional(v.boolean), |
||||
|
rankby: v.optional(v.oneOf(['prominence', 'distance'])), |
||||
|
type: v.optional(v.string), |
||||
|
pagetoken: v.optional(v.string), |
||||
|
retryOptions: v.optional(utils.retryOptions), |
||||
|
timeout: v.optional(v.number) |
||||
|
}) |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* Makes a places radar search request. |
||||
|
* |
||||
|
* @name GoogleMapsClient#placesRadar |
||||
|
* @function |
||||
|
* @param {Object} query |
||||
|
* @param {LatLng} query.location |
||||
|
* @param {number} query.radius |
||||
|
* @param {string} [query.language] |
||||
|
* @param {string} [query.keyword] |
||||
|
* @param {number} [query.minprice] |
||||
|
* @param {number} [query.maxprice] |
||||
|
* @param {string} [query.name] |
||||
|
* @param {boolean} [query.opennow] |
||||
|
* @param {string} [query.type] |
||||
|
* @param {ResponseCallback} callback Callback function for handling the result |
||||
|
* @return {RequestHandle} |
||||
|
*/ |
||||
|
exports.placesRadar = { |
||||
|
url: 'https://maps.googleapis.com/maps/api/place/radarsearch/json', |
||||
|
validator: v.object({ |
||||
|
location: utils.latLng, |
||||
|
radius: v.number, |
||||
|
language: v.optional(v.string), |
||||
|
keyword: v.optional(v.string), |
||||
|
minprice: v.optional(v.number), |
||||
|
maxprice: v.optional(v.number), |
||||
|
name: v.optional(v.string), |
||||
|
opennow: v.optional(v.boolean), |
||||
|
type: v.optional(v.string), |
||||
|
retryOptions: v.optional(utils.retryOptions), |
||||
|
timeout: v.optional(v.number) |
||||
|
}) |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* Makes a place detail request. |
||||
|
* |
||||
|
* @name GoogleMapsClient#place |
||||
|
* @function |
||||
|
* @param {Object} query |
||||
|
* @param {string} query.placeid |
||||
|
* @param {string} [query.language] |
||||
|
* @param {ResponseCallback} callback Callback function for handling the result |
||||
|
* @return {RequestHandle} |
||||
|
*/ |
||||
|
exports.place = { |
||||
|
url: 'https://maps.googleapis.com/maps/api/place/details/json', |
||||
|
validator: v.object({ |
||||
|
placeid: v.string, |
||||
|
language: v.optional(v.string), |
||||
|
retryOptions: v.optional(utils.retryOptions), |
||||
|
timeout: v.optional(v.number) |
||||
|
}) |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* Makes a place photos request. |
||||
|
* |
||||
|
* @name GoogleMapsClient#placesPhoto |
||||
|
* @function |
||||
|
* @param {Object} query |
||||
|
* @param {string} query.photoreference |
||||
|
* @param {number} [query.maxwidth] |
||||
|
* @param {number} [query.maxheight] |
||||
|
* @param {ResponseCallback} callback Callback function for handling the result |
||||
|
* @return {RequestHandle} |
||||
|
*/ |
||||
|
exports.placesPhoto = { |
||||
|
url: 'https://maps.googleapis.com/maps/api/place/photo', |
||||
|
validator: v.object({ |
||||
|
photoreference: v.string, |
||||
|
maxwidth: v.optional(v.number), |
||||
|
maxheight: v.optional(v.number), |
||||
|
retryOptions: v.optional(utils.retryOptions), |
||||
|
timeout: v.optional(v.number) |
||||
|
}) |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* Makes a places autocomplete request. |
||||
|
* |
||||
|
* @name GoogleMapsClient#placesAutoComplete |
||||
|
* @function |
||||
|
* @param {Object} query |
||||
|
* @param {string} query.input |
||||
|
* @param {number} [query.offset] |
||||
|
* @param {LatLng} [query.location] |
||||
|
* @param {string} [query.language] |
||||
|
* @param {number} [query.radius] |
||||
|
* @param {string} [query.types] |
||||
|
* @param {Array<string>} [query.components] |
||||
|
* @param {boolean} [query.strictbounds] |
||||
|
* @param {ResponseCallback} callback Callback function for handling the result |
||||
|
* @return {RequestHandle} |
||||
|
*/ |
||||
|
exports.placesAutoComplete = { |
||||
|
url: 'https://maps.googleapis.com/maps/api/place/autocomplete/json', |
||||
|
validator: v.object({ |
||||
|
input: v.string, |
||||
|
offset: v.optional(v.number), |
||||
|
location: v.optional(utils.latLng), |
||||
|
language: v.optional(v.string), |
||||
|
radius: v.optional(v.number), |
||||
|
types: v.optional(v.oneOf(['geocode', 'address', 'establishment', '(regions)', '(cities)'])), |
||||
|
components: v.optional(utils.pipedKeyValues), |
||||
|
strictbounds: v.optional(v.boolean), |
||||
|
retryOptions: v.optional(utils.retryOptions), |
||||
|
timeout: v.optional(v.number) |
||||
|
}) |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Makes a places query autocomplete request. |
||||
|
* |
||||
|
* @name GoogleMapsClient#placesQueryAutoComplete |
||||
|
* @function |
||||
|
* @param {Object} query |
||||
|
* @param {string} query.input |
||||
|
* @param {number} [query.offset] |
||||
|
* @param {LatLng} [query.location] |
||||
|
* @param {string} [query.language] |
||||
|
* @param {number} [query.radius] |
||||
|
* @param {ResponseCallback} callback Callback function for handling the result |
||||
|
* @return {RequestHandle} |
||||
|
*/ |
||||
|
exports.placesQueryAutoComplete = { |
||||
|
url: 'https://maps.googleapis.com/maps/api/place/queryautocomplete/json', |
||||
|
validator: v.object({ |
||||
|
input: v.string, |
||||
|
offset: v.optional(v.number), |
||||
|
location: v.optional(utils.latLng), |
||||
|
language: v.optional(v.string), |
||||
|
radius: v.optional(v.number), |
||||
|
retryOptions: v.optional(utils.retryOptions), |
||||
|
timeout: v.optional(v.number) |
||||
|
}) |
||||
|
}; |
@ -0,0 +1,106 @@ |
|||||
|
/** |
||||
|
* @license |
||||
|
* Copyright 2016 Google Inc. 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. |
||||
|
*/; |
||||
|
|
||||
|
var utils = require('../internal/convert'); |
||||
|
var v = require('../internal/validate'); |
||||
|
|
||||
|
/** |
||||
|
* Makes a snap-to-roads request. |
||||
|
* |
||||
|
* @name GoogleMapsClient#snapToRoads |
||||
|
* @function |
||||
|
* @param {Object} query |
||||
|
* @param {LatLng[]} query.path |
||||
|
* @param {boolean} [query.interpolate] |
||||
|
* @param {ResponseCallback} callback Callback function for handling the result |
||||
|
* @return {RequestHandle} |
||||
|
*/ |
||||
|
exports.snapToRoads = { |
||||
|
url: 'https://roads.googleapis.com/v1/snapToRoads', |
||||
|
supportsClientId: false, |
||||
|
validator: v.object({ |
||||
|
path: utils.pipedArrayOf(utils.latLng), |
||||
|
interpolate: v.optional(v.boolean), |
||||
|
retryOptions: v.optional(utils.retryOptions), |
||||
|
timeout: v.optional(v.number) |
||||
|
}) |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* Makes a nearest roads request. |
||||
|
* |
||||
|
* @name GoogleMapsClient#nearestRoads |
||||
|
* @function |
||||
|
* @param {Object} query |
||||
|
* @param {LatLng[]} query.points |
||||
|
* @param {ResponseCallback} callback Callback function for handling the result |
||||
|
* @return {RequestHandle} |
||||
|
*/ |
||||
|
exports.nearestRoads = { |
||||
|
url: 'https://roads.googleapis.com/v1/nearestRoads', |
||||
|
supportsClientId: false, |
||||
|
validator: v.object({ |
||||
|
points: utils.pipedArrayOf(utils.latLng), |
||||
|
retryOptions: v.optional(utils.retryOptions), |
||||
|
timeout: v.optional(v.number) |
||||
|
}) |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* Makes a speed-limits request for a place ID. For speed-limits |
||||
|
* requests using a path parameter, use the snappedSpeedLimits method. |
||||
|
* |
||||
|
* @name GoogleMapsClient#speedLimits |
||||
|
* @function |
||||
|
* @param {Object} query |
||||
|
* @param {string[]} query.placeId |
||||
|
* @param {string} [query.units] Either 'KPH' or 'MPH' |
||||
|
* @param {ResponseCallback} callback Callback function for handling the result |
||||
|
* @return {RequestHandle} |
||||
|
*/ |
||||
|
exports.speedLimits = { |
||||
|
url: 'https://roads.googleapis.com/v1/speedLimits', |
||||
|
supportsClientId: false, |
||||
|
validator: v.object({ |
||||
|
placeId: v.array(v.string), |
||||
|
units: v.optional(v.oneOf(['KPH', 'MPH'])), |
||||
|
retryOptions: v.optional(utils.retryOptions), |
||||
|
timeout: v.optional(v.number) |
||||
|
}) |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* Makes a speed-limits request for a path. |
||||
|
* |
||||
|
* @name GoogleMapsClient#snappedSpeedLimits |
||||
|
* @function |
||||
|
* @param {Object} query |
||||
|
* @param {LatLng[]} query.path |
||||
|
* @param {string} [query.units] Either 'KPH' or 'MPH' |
||||
|
* @param {ResponseCallback} callback Callback function for handling the result |
||||
|
* @return {RequestHandle} |
||||
|
*/ |
||||
|
exports.snappedSpeedLimits = { |
||||
|
url: 'https://roads.googleapis.com/v1/speedLimits', |
||||
|
supportsClientId: false, |
||||
|
validator: v.object({ |
||||
|
path: utils.pipedArrayOf(utils.latLng), |
||||
|
units: v.optional(v.oneOf(['KPH', 'MPH'])), |
||||
|
retryOptions: v.optional(utils.retryOptions), |
||||
|
timeout: v.optional(v.number) |
||||
|
}) |
||||
|
}; |
@ -0,0 +1,42 @@ |
|||||
|
/** |
||||
|
* @license |
||||
|
* Copyright 2016 Google Inc. 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. |
||||
|
*/; |
||||
|
|
||||
|
var utils = require('../internal/convert'); |
||||
|
var v = require('../internal/validate'); |
||||
|
|
||||
|
/** |
||||
|
* Makes a timezone request. |
||||
|
* |
||||
|
* @name GoogleMapsClient#timezone |
||||
|
* @function |
||||
|
* @param {Object} query |
||||
|
* @param {LatLng} query.location |
||||
|
* @param {Date|number} [query.timestamp] |
||||
|
* @param {string} [query.language] |
||||
|
* @param {ResponseCallback} callback Callback function for handling the result |
||||
|
* @return {RequestHandle} |
||||
|
*/ |
||||
|
exports.timezone = { |
||||
|
url: 'https://maps.googleapis.com/maps/api/timezone/json', |
||||
|
validator: v.object({ |
||||
|
location: utils.latLng, |
||||
|
timestamp: utils.timeStamp, |
||||
|
language: v.optional(v.string), |
||||
|
retryOptions: v.optional(utils.retryOptions), |
||||
|
timeout: v.optional(v.number) |
||||
|
}) |
||||
|
}; |
@ -0,0 +1,106 @@ |
|||||
|
/** |
||||
|
* @license |
||||
|
* Copyright 2016 Google Inc. 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. |
||||
|
*/ |
||||
|
|
||||
|
/** |
||||
|
* Google Maps Service module. |
||||
|
* @module @google/maps |
||||
|
*/ |
||||
|
|
||||
|
/** |
||||
|
* Creates a Google Maps client. The client object contains all the API methods. |
||||
|
* |
||||
|
* @param {Object} options |
||||
|
* @param {string} options.key API key (required, unless clientID and |
||||
|
* clientSecret provided). |
||||
|
* @param {string=} options.clientId Maps API for Work client ID. |
||||
|
* @param {string=} options.clientSecret Maps API for Work client secret (a.k.a. |
||||
|
* private key). |
||||
|
* @param {string=} options.channel Maps API for Work channel. |
||||
|
* @param {number=} options.timeout Timeout in milliseconds. |
||||
|
* (Default: 60 * 1000 ms) |
||||
|
* @param {string=} options.language Default language for all queries. |
||||
|
See https://developers.google.com/maps/faq#languagesupport
|
||||
|
* @param {number=} options.rate.limit Controls rate-limiting of requests. |
||||
|
* Maximum number of requests per period. (Default: 10) |
||||
|
* @param {number=} options.rate.period Period for rate limit, in milliseconds. |
||||
|
* (Default: 1000 ms) |
||||
|
* @param {number=} options.retryOptions.interval If a transient server error |
||||
|
* occurs, how long to wait before retrying the request, in milliseconds. |
||||
|
* (Default: 500 ms) |
||||
|
* @param {Function=} options.Promise - Promise constructor (optional). |
||||
|
* @return {GoogleMapsClient} The client object containing all API methods. |
||||
|
*/ |
||||
|
exports.createClient = function(options) { |
||||
|
|
||||
|
options = options || {}; |
||||
|
var makeApiCall = require('./internal/make-api-call').inject(options); |
||||
|
var deprecate = require('util').deprecate; |
||||
|
|
||||
|
var makeApiMethod = function(apiConfig) { |
||||
|
return function(query, callback, customParams) { |
||||
|
query = apiConfig.validator(query); |
||||
|
query.supportsClientId = apiConfig.supportsClientId !== false; |
||||
|
query.options = apiConfig.options; |
||||
|
if (options.language && !query.language) { |
||||
|
query.language = options.language; |
||||
|
} |
||||
|
// Merge query and customParams.
|
||||
|
var finalQuery = {}; |
||||
|
customParams = customParams || {}; |
||||
|
[customParams, query].map(function(obj) { |
||||
|
Object.keys(obj).sort().map(function(key) { |
||||
|
finalQuery[key] = obj[key]; |
||||
|
}); |
||||
|
}); |
||||
|
return makeApiCall(apiConfig.url, finalQuery, callback); |
||||
|
}; |
||||
|
}; |
||||
|
|
||||
|
var geocode = require('./apis/geocode'); |
||||
|
var geolocation = require('./apis/geolocation'); |
||||
|
var timezone = require('./apis/timezone'); |
||||
|
var directions = require('./apis/directions'); |
||||
|
var distanceMatrix = require('./apis/distance-matrix'); |
||||
|
var elevation = require('./apis/elevation'); |
||||
|
var roads = require('./apis/roads'); |
||||
|
var places = require('./apis/places'); |
||||
|
|
||||
|
return { |
||||
|
directions: makeApiMethod(directions.directions), |
||||
|
distanceMatrix: makeApiMethod(distanceMatrix.distanceMatrix), |
||||
|
elevation: makeApiMethod(elevation.elevation), |
||||
|
elevationAlongPath: makeApiMethod(elevation.elevationAlongPath), |
||||
|
geocode: makeApiMethod(geocode.geocode), |
||||
|
geolocate: makeApiMethod(geolocation.geolocate), |
||||
|
reverseGeocode: makeApiMethod(geocode.reverseGeocode), |
||||
|
places: makeApiMethod(places.places), |
||||
|
placesNearby: makeApiMethod(places.placesNearby), |
||||
|
placesRadar: deprecate(makeApiMethod(places.placesRadar), 'placesRadar is deprecated, see http://goo.gl/BGiumE'), |
||||
|
place: makeApiMethod(places.place), |
||||
|
placesPhoto: makeApiMethod(places.placesPhoto), |
||||
|
placesAutoComplete: makeApiMethod(places.placesAutoComplete), |
||||
|
placesQueryAutoComplete: makeApiMethod(places.placesQueryAutoComplete), |
||||
|
snapToRoads: makeApiMethod(roads.snapToRoads), |
||||
|
nearestRoads: makeApiMethod(roads.nearestRoads), |
||||
|
speedLimits: makeApiMethod(roads.speedLimits), |
||||
|
snappedSpeedLimits: makeApiMethod(roads.snappedSpeedLimits), |
||||
|
timezone: makeApiMethod(timezone.timezone) |
||||
|
}; |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
exports.cli = require('./internal/cli'); |
@ -0,0 +1,54 @@ |
|||||
|
/** |
||||
|
* @license |
||||
|
* Copyright 2016 Google Inc. 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. |
||||
|
*/ |
||||
|
|
||||
|
exports.inject = function(wait) { |
||||
|
var Task = require('./task'); |
||||
|
|
||||
|
return { |
||||
|
/** |
||||
|
* Repeatedly calls the 'do' function, until its result passes the 'until' |
||||
|
* predicate, or timeout. The 'do' function is retried with exponential |
||||
|
* backoff. |
||||
|
* |
||||
|
* @param {function(): Task<T>} options.do Starts the task to try |
||||
|
* repeatedly. |
||||
|
* @param {function(T): boolean} options.until A predicate that checks |
||||
|
* whether the result of options.do was successful. |
||||
|
* @return {Task<T>} |
||||
|
* @template T |
||||
|
*/ |
||||
|
attempt: function(options) { |
||||
|
var doSomething = options['do']; |
||||
|
var isSuccessful = options.until; |
||||
|
var interval = options.interval || 500; |
||||
|
var increment = options.increment || 1.5; |
||||
|
var jitter = options.jitter || 0.5; |
||||
|
|
||||
|
return Task.withValue().thenDo(function loop() { |
||||
|
return doSomething().thenDo(function(result) { |
||||
|
if (isSuccessful(result)) { |
||||
|
return Task.withValue(result); |
||||
|
} |
||||
|
|
||||
|
var delay = interval * (1 + jitter * (2 * Math.random() - 1)); |
||||
|
interval *= increment; |
||||
|
return wait(delay).thenDo(loop); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
}; |
||||
|
}; |
@ -0,0 +1,40 @@ |
|||||
|
/** |
||||
|
* @license |
||||
|
* Copyright 2016 Google Inc. 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. |
||||
|
*/ |
||||
|
|
||||
|
exports.create = function(size) { |
||||
|
var items = []; |
||||
|
var current = 0; |
||||
|
|
||||
|
return { |
||||
|
/** |
||||
|
* Inserts an item into the circular buffer. The new item will have index 0, |
||||
|
* and all other items will have their index incremented. |
||||
|
*/ |
||||
|
insert: function(item) { |
||||
|
current = (current + 1) % size; |
||||
|
items[current] = item; |
||||
|
}, |
||||
|
/** |
||||
|
* Returns the i-th item from the buffer. i=0 is the most-recently-inserted |
||||
|
* item. i=1 is the second-most-recently-inserted item. Returns undefined if |
||||
|
* i+1 items have not yet been inserted. |
||||
|
*/ |
||||
|
item: function(i) { |
||||
|
return items[(current - i + size) % size]; |
||||
|
} |
||||
|
}; |
||||
|
}; |
@ -0,0 +1,39 @@ |
|||||
|
/** |
||||
|
* @license |
||||
|
* Copyright 2016 Google Inc. 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. |
||||
|
*/ |
||||
|
|
||||
|
|
||||
|
exports.parseArgs = function(argv) { |
||||
|
var parsed = {}; |
||||
|
var argv = argv || process.argv.slice(2); |
||||
|
for (var i = 0; i < argv.length; i += 2) { |
||||
|
var value = argv[i + 1]; |
||||
|
try { |
||||
|
value = JSON.parse(value); |
||||
|
} catch (e) { |
||||
|
} |
||||
|
parsed[argv[i].replace(/^-*/g, '')] = value; |
||||
|
} |
||||
|
return parsed; |
||||
|
}; |
||||
|
|
||||
|
exports.callback = function(error, response) { |
||||
|
if (error) { |
||||
|
console.log("Error:", error.message != undefined ? error.message : error); |
||||
|
} else { |
||||
|
console.log(JSON.stringify(response.json, null, 4)); |
||||
|
} |
||||
|
}; |
@ -0,0 +1,90 @@ |
|||||
|
/** |
||||
|
* @license |
||||
|
* Copyright 2016 Google Inc. 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. |
||||
|
*/ |
||||
|
|
||||
|
var v = require('./validate'); |
||||
|
|
||||
|
var asArray = function(arg) { |
||||
|
return Array.isArray(arg) ? arg : [arg]; |
||||
|
}; |
||||
|
|
||||
|
exports.pipedKeyValues = function(arg) { |
||||
|
if (!arg || typeof arg !== 'object') { |
||||
|
throw new v.InvalidValueError('not an Object'); |
||||
|
} |
||||
|
return Object.keys(arg).sort().map(function(key) { |
||||
|
return key + ':' + arg[key]; |
||||
|
}).join('|'); |
||||
|
}; |
||||
|
|
||||
|
exports.locations = function(arg) { |
||||
|
if (Array.isArray(arg) && arg.length == 2 && typeof arg[0] == 'number' && typeof arg[1] == 'number') { |
||||
|
arg = [arg]; |
||||
|
} |
||||
|
return asArray(arg).map(exports.latLng).join('|'); |
||||
|
}; |
||||
|
|
||||
|
exports.pipedArrayOf = function(validateItem) { |
||||
|
var validateArray = v.array(validateItem); |
||||
|
return function(value) { |
||||
|
value = validateArray(asArray(value)); |
||||
|
return value.join('|'); |
||||
|
}; |
||||
|
}; |
||||
|
|
||||
|
exports.latLng = function(arg) { |
||||
|
if (!arg) { |
||||
|
throw new v.InvalidValueError(); |
||||
|
} else if (arg.lat != undefined && arg.lng != undefined) { |
||||
|
arg = [arg.lat, arg.lng]; |
||||
|
} else if (arg.latitude != undefined && arg.longitude != undefined) { |
||||
|
arg = [arg.latitude, arg.longitude]; |
||||
|
} |
||||
|
return asArray(arg).join(','); |
||||
|
}; |
||||
|
|
||||
|
var validateBounds = v.object({ |
||||
|
south: v.number, |
||||
|
west: v.number, |
||||
|
north: v.number, |
||||
|
east: v.number |
||||
|
}); |
||||
|
|
||||
|
exports.bounds = function(arg) { |
||||
|
arg = validateBounds(arg); |
||||
|
return arg.south + ',' + arg.west + '|' + arg.north + ',' + arg.east; |
||||
|
}; |
||||
|
|
||||
|
exports.timeStamp = function(arg) { |
||||
|
if (arg == undefined) { |
||||
|
arg = new Date(); |
||||
|
} |
||||
|
if (arg.getTime) { |
||||
|
arg = arg.getTime(); |
||||
|
// NOTE: Unix time is seconds past epoch.
|
||||
|
return Math.round(arg / 1000); |
||||
|
} |
||||
|
|
||||
|
// Otherwise assume arg is Unix time
|
||||
|
return arg; |
||||
|
}; |
||||
|
|
||||
|
exports.retryOptions = v.object({ |
||||
|
timeout: v.optional(v.number), |
||||
|
interval: v.optional(v.number), |
||||
|
increment: v.optional(v.number), |
||||
|
jitter: v.optional(v.number) |
||||
|
}); |
@ -0,0 +1,221 @@ |
|||||
|
/** |
||||
|
* @license |
||||
|
* Copyright 2016 Google Inc. 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. |
||||
|
*/ |
||||
|
|
||||
|
var url = require('url'); |
||||
|
var Task = require('./task'); |
||||
|
|
||||
|
exports.inject = function(options) { |
||||
|
|
||||
|
var key = options.key || process.env.GOOGLE_MAPS_API_KEY; |
||||
|
var channel = options.channel; |
||||
|
var clientId = options.clientId || process.env.GOOGLE_MAPS_API_CLIENT_ID; |
||||
|
var clientSecret = options.clientSecret || process.env.GOOGLE_MAPS_API_CLIENT_SECRET; |
||||
|
|
||||
|
var rate = options.rate || {}; |
||||
|
var rateLimit = rate.limit || 10; // 10 requests per ratePeriod.
|
||||
|
var ratePeriod = rate.period || 1000; // 1 second.
|
||||
|
|
||||
|
var makeUrlRequest = options.makeUrlRequest || require('./make-url-request'); |
||||
|
var mySetTimeout = options.setTimeout || setTimeout; |
||||
|
var myClearTimeout = options.clearTimeout || clearTimeout; |
||||
|
var getTime = options.getTime || function() {return new Date().getTime();}; |
||||
|
var wait = require('./wait').inject(mySetTimeout, myClearTimeout); |
||||
|
var attempt = require('./attempt').inject(wait).attempt; |
||||
|
var ThrottledQueue = require('./throttled-queue').inject(wait, getTime); |
||||
|
var requestQueue = ThrottledQueue.create(rateLimit, ratePeriod); |
||||
|
|
||||
|
/** |
||||
|
* Makes an API request using the injected makeUrlRequest. |
||||
|
* |
||||
|
* Inserts the API key (or client ID and signature) into the query |
||||
|
* parameters. Retries requests when the status code requires it. |
||||
|
* Parses the response body as JSON. |
||||
|
* |
||||
|
* The callback is given either an error or a response. The response |
||||
|
* is an object with the following entries: |
||||
|
* { |
||||
|
* status: number, |
||||
|
* body: string, |
||||
|
* json: Object |
||||
|
* } |
||||
|
* |
||||
|
* @param {string} path |
||||
|
* @param {Object} query This function mutates the query object. |
||||
|
* @param {Function} callback |
||||
|
* @return {{ |
||||
|
* cancel: function(), |
||||
|
* finally: function(function()), |
||||
|
* asPromise: function(): Promise |
||||
|
* }} |
||||
|
*/ |
||||
|
return function(path, query, callback) { |
||||
|
|
||||
|
callback = callback || function() {}; |
||||
|
|
||||
|
var retryOptions = query.retryOptions || options.retryOptions || {}; |
||||
|
delete query.retryOptions; |
||||
|
|
||||
|
var timeout = query.timeout || options.timeout || 60 * 1000; |
||||
|
delete query.timeout; |
||||
|
|
||||
|
var useClientId = query.supportsClientId && clientId && clientSecret; |
||||
|
delete query.supportsClientId; |
||||
|
|
||||
|
var queryOptions = query.options || {}; |
||||
|
delete query.options; |
||||
|
|
||||
|
var isPost = queryOptions.method === 'POST' |
||||
|
var requestUrl = formatRequestUrl(path, isPost ? {} : query, useClientId); |
||||
|
|
||||
|
if (isPost) { |
||||
|
queryOptions.body = query; |
||||
|
} |
||||
|
|
||||
|
// Determines whether a response indicates a retriable error.
|
||||
|
var canRetry = queryOptions.canRetry || function(response) { |
||||
|
return ( |
||||
|
response == null |
||||
|
|| response.status === 500 |
||||
|
|| response.status === 503 |
||||
|
|| response.status === 504 |
||||
|
|| (response.json && ( |
||||
|
response.json.status === 'OVER_QUERY_LIMIT' || |
||||
|
response.json.status === 'RESOURCE_EXHAUSTED'))); |
||||
|
}; |
||||
|
delete queryOptions.canRetry; |
||||
|
|
||||
|
// Determines whether a response indicates success.
|
||||
|
var isSuccessful = queryOptions.isSuccessful || function(response) { |
||||
|
return response.status === 200 && ( |
||||
|
response.json == undefined || |
||||
|
response.json.status === undefined || |
||||
|
response.json.status === 'OK' || |
||||
|
response.json.status === 'ZERO_RESULTS'); |
||||
|
}; |
||||
|
delete queryOptions.isSuccessful; |
||||
|
|
||||
|
function rateLimitedGet() { |
||||
|
return requestQueue.add(function() { |
||||
|
return Task.start(function(resolve, reject) { |
||||
|
return makeUrlRequest(requestUrl, resolve, reject, queryOptions); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
var timeoutTask = wait(timeout).thenDo(function() { |
||||
|
throw 'timeout'; |
||||
|
}); |
||||
|
var requestTask = attempt({ |
||||
|
'do': rateLimitedGet, |
||||
|
until: function(response) { return !canRetry(response); }, |
||||
|
interval: retryOptions.interval, |
||||
|
increment: retryOptions.increment, |
||||
|
jitter: retryOptions.jitter |
||||
|
}); |
||||
|
|
||||
|
var task = |
||||
|
Task.race([timeoutTask, requestTask]) |
||||
|
.thenDo(function(response) { |
||||
|
// We add the request url and the original query to the response
|
||||
|
// to be able to use them when debugging errors.
|
||||
|
response.requestUrl = requestUrl; |
||||
|
response.query = query; |
||||
|
|
||||
|
if (isSuccessful(response)) { |
||||
|
return Task.withValue(response); |
||||
|
} else { |
||||
|
return Task.withError(response); |
||||
|
} |
||||
|
}) |
||||
|
.thenDo( |
||||
|
function(response) { callback(null, response); }, |
||||
|
function(err) { callback(err); }); |
||||
|
|
||||
|
if (options.Promise) { |
||||
|
var originalCallback = callback; |
||||
|
var promise = new options.Promise(function(resolve, reject) { |
||||
|
callback = function(err, result) { |
||||
|
if (err != null) { |
||||
|
reject(err); |
||||
|
} else { |
||||
|
resolve(result); |
||||
|
} |
||||
|
originalCallback(err, result); |
||||
|
}; |
||||
|
}); |
||||
|
task.asPromise = function() { return promise; }; |
||||
|
} |
||||
|
|
||||
|
delete task.thenDo; |
||||
|
return task; |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* Adds auth information to the query, and formats it into a URL. |
||||
|
* @param {string} path |
||||
|
* @param {Object} query |
||||
|
* @param {boolean} useClientId |
||||
|
* @return {string} The formatted URL. |
||||
|
*/ |
||||
|
function formatRequestUrl(path, query, useClientId) { |
||||
|
if (channel) { |
||||
|
query.channel = channel; |
||||
|
} |
||||
|
if (useClientId) { |
||||
|
query.client = clientId; |
||||
|
} else if (key && key.indexOf('AIza') == 0) { |
||||
|
query.key = key; |
||||
|
} else { |
||||
|
throw 'Missing either a valid API key, or a client ID and secret'; |
||||
|
} |
||||
|
|
||||
|
var requestUrl = url.format({pathname: path, query: query}); |
||||
|
|
||||
|
// When using client ID, generate and append the signature param.
|
||||
|
if (useClientId) { |
||||
|
var secret = new Buffer(clientSecret, 'base64'); |
||||
|
var payload = url.parse(requestUrl).path; |
||||
|
var signature = computeSignature(secret, payload); |
||||
|
requestUrl += '&signature=' + encodeURIComponent(signature); |
||||
|
} |
||||
|
|
||||
|
return requestUrl; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param {string} secret |
||||
|
* @param {string} payload |
||||
|
* @return {string} |
||||
|
*/ |
||||
|
function computeSignature(secret, payload) { |
||||
|
var signature = |
||||
|
new Buffer( |
||||
|
require('crypto') |
||||
|
.createHmac('sha1', secret) |
||||
|
.update(payload) |
||||
|
.digest('base64')) |
||||
|
.toString() |
||||
|
.replace(/\+/g, '-') |
||||
|
.replace(/\//g, '_') |
||||
|
.replace(/=+$/, ''); |
||||
|
while (signature.length % 4) { |
||||
|
signature += '='; |
||||
|
} |
||||
|
return signature; |
||||
|
} |
||||
|
|
||||
|
}; |
@ -0,0 +1,109 @@ |
|||||
|
/** |
||||
|
* @license |
||||
|
* Copyright 2016 Google Inc. 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. |
||||
|
*/ |
||||
|
|
||||
|
var https = require('https'); |
||||
|
var parse = require('url').parse; |
||||
|
var version = require('../version'); |
||||
|
|
||||
|
|
||||
|
// add keep-alive header to speed up request
|
||||
|
var agent = new https.Agent({ keepAlive: true }); |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Makes a secure HTTP GET request for the given URL. |
||||
|
* |
||||
|
* Calls the callback with two parameters (err, response). If there was an |
||||
|
* error, response should be null. If there was no error, err should be null, |
||||
|
* and response should be an object with these properties |
||||
|
* { |
||||
|
* status: number, |
||||
|
* headers: Object, |
||||
|
* json: Object |
||||
|
* } |
||||
|
* |
||||
|
* Returns a function that cancels the request. |
||||
|
* |
||||
|
* @param {string} url |
||||
|
* @param {function(ClientResponse)} onSuccess |
||||
|
* @param {function(?)} onError |
||||
|
* @param {Object} options |
||||
|
* @return {function()} |
||||
|
*/ |
||||
|
module.exports = function makeUrlRequest(url, onSuccess, onError, options) { |
||||
|
|
||||
|
var requestOptions = parse(url); |
||||
|
var body; |
||||
|
|
||||
|
// Allow each API to provide some of the request options such as the
|
||||
|
// HTTP method, headers, etc.
|
||||
|
if (options) { |
||||
|
for (var k in options) { |
||||
|
if (k === 'body') { |
||||
|
body = options[k]; |
||||
|
} else { |
||||
|
requestOptions[k] = options[k]; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
requestOptions.headers = requestOptions.headers || {}; |
||||
|
requestOptions.headers['User-Agent'] = 'GoogleGeoApiClientJS/' + version; |
||||
|
|
||||
|
var request = https.request(requestOptions, function(response) { |
||||
|
|
||||
|
response.on('error', function(error) { |
||||
|
onError(error); |
||||
|
}); |
||||
|
|
||||
|
if (response.statusCode === 302) { |
||||
|
// Handle redirect.
|
||||
|
var url = response.headers['location']; |
||||
|
makeUrlRequest(url, onSuccess, onError, options); |
||||
|
} else if (response.headers['content-type'] == 'application/json; charset=UTF-8') { |
||||
|
// Handle JSON.
|
||||
|
var data = []; |
||||
|
response.on('data', function(chunk) { |
||||
|
data.push(chunk); |
||||
|
}); |
||||
|
response.on('end', function() { |
||||
|
onSuccess({ |
||||
|
status: response.statusCode, |
||||
|
headers: response.headers, |
||||
|
json: JSON.parse(Buffer.concat(data).toString()) |
||||
|
}) |
||||
|
}); |
||||
|
} else { |
||||
|
// Fallback is for binary data, namely places photo download,
|
||||
|
// so just provide the response stream. Also provide the same
|
||||
|
// consistent name for status checking as per JSON responses.
|
||||
|
response.status = response.statusCode; |
||||
|
onSuccess(response); |
||||
|
} |
||||
|
|
||||
|
}).on('error', function(error) { |
||||
|
onError(error); |
||||
|
}); |
||||
|
|
||||
|
if (body) { |
||||
|
request.write(JSON.stringify(body)); |
||||
|
} |
||||
|
|
||||
|
request.end(); |
||||
|
|
||||
|
return function cancel() { request.abort(); }; |
||||
|
}; |
@ -0,0 +1,269 @@ |
|||||
|
/** |
||||
|
* @license |
||||
|
* Copyright 2016 Google Inc. 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. |
||||
|
*/ |
||||
|
|
||||
|
// This is a utility class that makes it easier to work with asynchronous tasks.
|
||||
|
// Here's why I don't just use Promises:
|
||||
|
// (a) I don't want to depend on a Promise implementation.
|
||||
|
// (b) Promises aren't cancellable (yet?), and I want cancellability.
|
||||
|
//
|
||||
|
// This is very stripped down, compared to Promises.
|
||||
|
// (a) You can only call .thenDo() once. Because there's only one party waiting
|
||||
|
// on the result of a task, cancelling always propagates backwards.
|
||||
|
// (b) The argument to .thenDo() must return either undefined or a Task. I don't
|
||||
|
// promote values to Tasks, like what happens with Promises.
|
||||
|
|
||||
|
var Task = exports; |
||||
|
|
||||
|
/** |
||||
|
* Creates a Task. |
||||
|
* |
||||
|
* The `doSomething` function is called immediately, so that it can start |
||||
|
* whatever work is part of this task. |
||||
|
* |
||||
|
* The `doSomething` function is given a resolve function and a reject function, |
||||
|
* and it should call one of them when the task is finished, to report its |
||||
|
* result. |
||||
|
* |
||||
|
* The `doSomething` function can optionally return a cancel function. This will |
||||
|
* be called if the task is cancelled. |
||||
|
* |
||||
|
* @param {function(function(T), function(?)): function()} doSomething |
||||
|
* @return {Task<T>} |
||||
|
* @template T |
||||
|
*/ |
||||
|
Task.start = function(doSomething) { |
||||
|
var me = {}; |
||||
|
|
||||
|
// onFinish should be called as soon as both finished and onFinish are
|
||||
|
// defined. It should be called by the piece of code that just defined either
|
||||
|
// finished or onFinish.
|
||||
|
var finished; |
||||
|
var onFinish; |
||||
|
var cleaners = []; |
||||
|
|
||||
|
function finish(err, result) { |
||||
|
if (!finished) { |
||||
|
finished = {err: err, result: result}; |
||||
|
|
||||
|
if (onFinish) { |
||||
|
onFinish(); |
||||
|
// To prevent memory leaks, delete our reference to onFinish after
|
||||
|
// calling it.
|
||||
|
onFinish = function() {}; |
||||
|
} |
||||
|
|
||||
|
var cleanup; |
||||
|
while (cleanup = cleaners.pop()) { |
||||
|
cleanup(); |
||||
|
} |
||||
|
|
||||
|
if (err === 'cancelled') { |
||||
|
if (abort) abort(); |
||||
|
} |
||||
|
|
||||
|
abort = null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
try { |
||||
|
// doSomething must be called immediately.
|
||||
|
var abort = doSomething( |
||||
|
function(result) { finish(null, result); }, |
||||
|
function(err) { finish(err, null); }); |
||||
|
} catch (err) { |
||||
|
finish(err, null); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Cancels the task (unless the task has already finished, in which case |
||||
|
* this call is ignored). |
||||
|
* |
||||
|
* Subsequent tasks created with #thenDo will not be started. However, clean- |
||||
|
* up code added with #finished will run. |
||||
|
*/ |
||||
|
me.cancel = function() { |
||||
|
finish('cancelled', null); |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* Sets the listener that will be called with the result of this task, when |
||||
|
* finished. This function can be called at most once. |
||||
|
* |
||||
|
* @param {function(?, T)} callback |
||||
|
*/ |
||||
|
function setListener(callback) { |
||||
|
if (onFinish) { |
||||
|
throw new Error('thenDo/finally called more than once'); |
||||
|
} |
||||
|
if (finished) { |
||||
|
onFinish = function() {}; |
||||
|
callback(finished.err, finished.result); |
||||
|
} else { |
||||
|
onFinish = function() { |
||||
|
callback(finished.err, finished.result); |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Creates and returns a composite task, consisting of this task and a |
||||
|
* subsequent task. |
||||
|
* |
||||
|
* @param {function(T): ?Task<U>} onResolve A function that will |
||||
|
* create a subsequent task. This function will be called |
||||
|
* asynchronously, with the result of this task, when it |
||||
|
* finishes. The return value must be a Task, or null/undefined. |
||||
|
* @param {function(?): ?Task<U>} onReject A function that will |
||||
|
* create a subsequent task. This function will be called |
||||
|
* asynchronously, with the error produced by this task, when it |
||||
|
* finishes. The return value must be a Task, or null/undefined. |
||||
|
* @return {Task<U>} The composite task. Cancelling the composite task cancels |
||||
|
* either this task or the subsequent task, depending on whether this |
||||
|
* task is finished. |
||||
|
* @template U |
||||
|
*/ |
||||
|
me.thenDo = function(onResolve, onReject) { |
||||
|
return compose(me, setListener, onResolve, onReject); |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* Registers a cleanup function, that will be run when the task finishes, |
||||
|
* regardless of error or cancellation. |
||||
|
* |
||||
|
* @param {function()} cleanup |
||||
|
* @return {THIS} |
||||
|
*/ |
||||
|
me.finally = function(cleanup) { |
||||
|
if (!finished) { |
||||
|
cleaners.push(function() { |
||||
|
process.nextTick(cleanup); |
||||
|
}); |
||||
|
} else { |
||||
|
process.nextTick(cleanup); |
||||
|
} |
||||
|
return me; |
||||
|
}; |
||||
|
|
||||
|
return me; |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* Creates a Task with the given result. |
||||
|
*/ |
||||
|
Task.withValue = function(result) { |
||||
|
return Task.start(function(resolve) { |
||||
|
resolve(result); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* Creates a Task with the given error. |
||||
|
*/ |
||||
|
Task.withError = function(err) { |
||||
|
return Task.start(function(resolve, reject) { |
||||
|
reject(err); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* Returns a new task that races the given tasks. Eventually finishes with the |
||||
|
* result or error of whichever task finishes first. If any task is cancelled, |
||||
|
* all of the tasks are cancelled. |
||||
|
* |
||||
|
* @param {Array<Task<T>>} tasks |
||||
|
* @return {Task<T>} |
||||
|
* @template T |
||||
|
*/ |
||||
|
Task.race = function(tasks) { |
||||
|
return Task.start(function(resolve, reject) { |
||||
|
function cancelAll() { |
||||
|
tasks.forEach(function(task) { |
||||
|
task.cancel(); |
||||
|
}); |
||||
|
} |
||||
|
tasks.forEach(function(task) { |
||||
|
task.finally(cancelAll).thenDo(resolve, reject); |
||||
|
}); |
||||
|
return cancelAll; |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* Creates a composite task, which uses the output of the first task to create |
||||
|
* a subsequent task, and represents the two tasks together. |
||||
|
* |
||||
|
* This function is internal-only. It is used by Task.thenDo(). |
||||
|
* |
||||
|
* @param {Task<T>} firstTask |
||||
|
* @param {function(function(?, T))} whenFirstTaskFinishes The private |
||||
|
* setListener method on the firstTask. |
||||
|
* @param {function(T): Task<U>} onResolve |
||||
|
* @param {function(?): Task<U>} onReject |
||||
|
* @return {Task<U>} |
||||
|
* @template T, U |
||||
|
*/ |
||||
|
function compose(firstTask, whenFirstTaskFinishes, onResolve, onReject) { |
||||
|
return Task.start(function(resolve, reject) { |
||||
|
var cancelled; |
||||
|
var currentTask = firstTask; |
||||
|
|
||||
|
whenFirstTaskFinishes(function(err, result) { |
||||
|
currentTask = null; |
||||
|
// createSubsequentTask must be called asynchronously.
|
||||
|
process.nextTick(function() { |
||||
|
if (cancelled || err === 'cancelled') { |
||||
|
return reject('cancelled'); |
||||
|
} |
||||
|
|
||||
|
// Start the subsequent task.
|
||||
|
if (err == null) { |
||||
|
if (!onResolve) { |
||||
|
return resolve(result); |
||||
|
} |
||||
|
try { |
||||
|
currentTask = onResolve(result); |
||||
|
} catch (caughtErr) { |
||||
|
return reject(caughtErr); |
||||
|
} |
||||
|
} else { |
||||
|
if (!onReject) { |
||||
|
return reject(err); |
||||
|
} |
||||
|
try { |
||||
|
currentTask = onReject(err); |
||||
|
} catch (caughtErr) { |
||||
|
return reject(caughtErr); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Was a subsequent task returned?
|
||||
|
if (!currentTask) { |
||||
|
return resolve(undefined); |
||||
|
} |
||||
|
|
||||
|
currentTask.thenDo(resolve, reject); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
return function cancelCompositeTask() { |
||||
|
cancelled = true; |
||||
|
if (currentTask) { |
||||
|
currentTask.cancel(); |
||||
|
} |
||||
|
}; |
||||
|
}); |
||||
|
} |
@ -0,0 +1,74 @@ |
|||||
|
/** |
||||
|
* @license |
||||
|
* Copyright 2016 Google Inc. 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. |
||||
|
*/ |
||||
|
|
||||
|
var CircularBuffer = require('./circular-buffer'); |
||||
|
var Task = require('./task'); |
||||
|
|
||||
|
exports.inject = function(wait, getTime) { |
||||
|
return { |
||||
|
/** |
||||
|
* Creates a ThrottledQueue. The queue stores tasks, which will be executed |
||||
|
* asynchronously, at a controlled rate. |
||||
|
* |
||||
|
* @param {number} limit The maximum number of tasks that can be executed |
||||
|
* over one period. |
||||
|
* @param {number} period The time period (ms) over which limit is |
||||
|
* enforceable. |
||||
|
* @return {ThrottledQueue} |
||||
|
*/ |
||||
|
create: function(limit, period) { |
||||
|
var me = {}; |
||||
|
var queue = Task.withValue(); |
||||
|
var recentTimes = CircularBuffer.create(limit); |
||||
|
|
||||
|
/** |
||||
|
* Adds a task to the work queue. |
||||
|
* |
||||
|
* @param {function(): Task<T>} doSomething Starts the task. This function |
||||
|
* will be called when the rate limit allows. |
||||
|
* @return {Task<T>} The delayed task. |
||||
|
* @template T |
||||
|
*/ |
||||
|
me.add = function(doSomething) { |
||||
|
// Return a separate task from the queue, so that cancelling a task
|
||||
|
// doesn't propagate back and cancel the whole queue.
|
||||
|
var waitForMyTurn = Task |
||||
|
.start(function(resolve) { |
||||
|
queue.finally(resolve); |
||||
|
}) |
||||
|
.thenDo(function() { |
||||
|
var lastTime = recentTimes.item(limit - 1); |
||||
|
if (lastTime == undefined) return; |
||||
|
return wait(Math.max(lastTime + period - getTime(), 0)); |
||||
|
}) |
||||
|
.thenDo(function() { |
||||
|
recentTimes.insert(getTime()); |
||||
|
}); |
||||
|
|
||||
|
queue = queue.thenDo(function() { |
||||
|
return Task.start(function(resolve) { |
||||
|
waitForMyTurn.finally(resolve); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
return waitForMyTurn.thenDo(doSomething); |
||||
|
}; |
||||
|
|
||||
|
return me; |
||||
|
} |
||||
|
}; |
||||
|
}; |
@ -0,0 +1,175 @@ |
|||||
|
/** |
||||
|
* @license |
||||
|
* Copyright 2016 Google Inc. 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. |
||||
|
*/ |
||||
|
|
||||
|
var Validate = exports; |
||||
|
|
||||
|
function InvalidValueError(message) { |
||||
|
this.message = message; |
||||
|
this.name = 'InvalidValueError'; |
||||
|
Error.captureStackTrace(this, InvalidValueError); |
||||
|
} |
||||
|
InvalidValueError.prototype = Object.create(Error.prototype); |
||||
|
InvalidValueError.prototype.constructor = InvalidValueError; |
||||
|
|
||||
|
InvalidValueError.prepend = function(message, error) { |
||||
|
if (error instanceof InvalidValueError) { |
||||
|
return new InvalidValueError(message + ': ' + error.message); |
||||
|
} |
||||
|
return error; |
||||
|
}; |
||||
|
|
||||
|
Validate.InvalidValueError = InvalidValueError; |
||||
|
|
||||
|
Validate.acceptAll = function(value) { |
||||
|
return value; |
||||
|
}; |
||||
|
|
||||
|
Validate.optional = function(validator) { |
||||
|
return function(value) { |
||||
|
return (value == undefined) ? value : validator(value); |
||||
|
}; |
||||
|
}; |
||||
|
|
||||
|
Validate.that = function(predicate, message) { |
||||
|
return function(value) { |
||||
|
if (predicate(value)) return value; |
||||
|
throw new InvalidValueError(message); |
||||
|
}; |
||||
|
}; |
||||
|
|
||||
|
Validate.number = Validate.that(function(value) { |
||||
|
return typeof value === 'number'; |
||||
|
}, 'not a number'); |
||||
|
|
||||
|
Validate.string = Validate.that(function(value) { |
||||
|
return typeof value === 'string'; |
||||
|
}, 'not a string'); |
||||
|
|
||||
|
Validate.object = function(propertyValidators) { |
||||
|
return function(object) { |
||||
|
var result = {}; |
||||
|
|
||||
|
if (!object || typeof object !== 'object') { |
||||
|
throw new InvalidValueError('not an Object'); |
||||
|
} |
||||
|
|
||||
|
// Validate all properties.
|
||||
|
for (key in propertyValidators) { |
||||
|
var validator = propertyValidators[key]; |
||||
|
try { |
||||
|
var valid = validator(object[key]); |
||||
|
} catch (error) { |
||||
|
if (key in object) { |
||||
|
throw InvalidValueError.prepend('in property "' + key + '"', error); |
||||
|
} else { |
||||
|
throw new InvalidValueError('missing property "' + key + '"'); |
||||
|
} |
||||
|
} |
||||
|
if (valid !== undefined) { |
||||
|
result[key] = valid; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Check for unexpected properties.
|
||||
|
for (var key in object) { |
||||
|
if (!propertyValidators[key]) { |
||||
|
throw new InvalidValueError('unexpected property "' + key + '"'); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return result; |
||||
|
}; |
||||
|
}; |
||||
|
|
||||
|
Validate.array = function(validator) { |
||||
|
return function(array) { |
||||
|
var result = []; |
||||
|
|
||||
|
if (Object.prototype.toString.call(array) !== '[object Array]') { |
||||
|
throw new InvalidValueError('not an Array'); |
||||
|
} |
||||
|
|
||||
|
for (var i = 0; i < array.length; ++i) { |
||||
|
try { |
||||
|
result[i] = validator(array[i]); |
||||
|
} catch (error) { |
||||
|
throw InvalidValueError.prepend('at index ' + i, error); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return result; |
||||
|
}; |
||||
|
}; |
||||
|
|
||||
|
Validate.oneOf = function(names) { |
||||
|
var myObject = {}; |
||||
|
var quotedNames = []; |
||||
|
names.forEach(function(name) { |
||||
|
myObject[name] = true; |
||||
|
quotedNames.push('"' + name + '"'); |
||||
|
}); |
||||
|
|
||||
|
return function(value) { |
||||
|
if (myObject[value]) return value; |
||||
|
throw new InvalidValueError('not one of ' + quotedNames.join(', ')); |
||||
|
}; |
||||
|
}; |
||||
|
|
||||
|
Validate.mutuallyExclusiveProperties = function(names) { |
||||
|
return function(value) { |
||||
|
if (!value) return value; |
||||
|
|
||||
|
var present = []; |
||||
|
names.forEach(function(name) { |
||||
|
if (name in value) { |
||||
|
present.push('"' + name + '"'); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
if (present.length > 1) { |
||||
|
throw new InvalidValueError( |
||||
|
'cannot specify properties ' |
||||
|
+ present.slice(0, -1).join(', ') |
||||
|
+ ' and ' |
||||
|
+ present.slice(-1) |
||||
|
+ ' together'); |
||||
|
} |
||||
|
|
||||
|
return value; |
||||
|
}; |
||||
|
}; |
||||
|
|
||||
|
Validate.compose = function(validators) { |
||||
|
return function(value) { |
||||
|
validators.forEach(function(validate) { |
||||
|
value = validate(value); |
||||
|
}); |
||||
|
return value; |
||||
|
}; |
||||
|
}; |
||||
|
|
||||
|
Validate.boolean = Validate.compose([ |
||||
|
Validate.that(function(value) { |
||||
|
return typeof value === 'boolean'; |
||||
|
}, 'not a boolean'), |
||||
|
function(value) { |
||||
|
// In each API, boolean fields default to false, and the presence of
|
||||
|
// a querystring value indicates true, so we omit the value if
|
||||
|
// explicitly set to false.
|
||||
|
return value ? value : undefined; |
||||
|
} |
||||
|
]); |
@ -0,0 +1,34 @@ |
|||||
|
/** |
||||
|
* @license |
||||
|
* Copyright 2016 Google Inc. 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. |
||||
|
*/ |
||||
|
|
||||
|
var Task = require('./task'); |
||||
|
|
||||
|
exports.inject = function(setTimeout, clearTimeout) { |
||||
|
/** |
||||
|
* Returns a task that waits for the given delay. |
||||
|
* @param {number} delayMs |
||||
|
* @return {Task<undefined>} |
||||
|
*/ |
||||
|
return function wait(delayMs) { |
||||
|
return Task.start(function(resolve) { |
||||
|
var id = setTimeout(resolve, delayMs); |
||||
|
return function cancel() { |
||||
|
clearTimeout(id); |
||||
|
}; |
||||
|
}); |
||||
|
} |
||||
|
}; |
@ -0,0 +1 @@ |
|||||
|
module.exports = '0.0.1'; |
@ -0,0 +1,85 @@ |
|||||
|
{ |
||||
|
"_from": "@google/maps", |
||||
|
"_id": "@google/maps@0.4.5", |
||||
|
"_inBundle": false, |
||||
|
"_integrity": "sha1-cuuc+OfelEYZJF0Pjz+WlXHqhNg=", |
||||
|
"_location": "/@google/maps", |
||||
|
"_phantomChildren": {}, |
||||
|
"_requested": { |
||||
|
"type": "tag", |
||||
|
"registry": true, |
||||
|
"raw": "@google/maps", |
||||
|
"name": "@google/maps", |
||||
|
"escapedName": "@google%2fmaps", |
||||
|
"scope": "@google", |
||||
|
"rawSpec": "", |
||||
|
"saveSpec": null, |
||||
|
"fetchSpec": "latest" |
||||
|
}, |
||||
|
"_requiredBy": [ |
||||
|
"#USER", |
||||
|
"/" |
||||
|
], |
||||
|
"_resolved": "https://registry.npmjs.org/@google/maps/-/maps-0.4.5.tgz", |
||||
|
"_shasum": "72eb9cf8e7de944619245d0f8f3f969571ea84d8", |
||||
|
"_spec": "@google/maps", |
||||
|
"_where": "/var/www/htdocs/ordine", |
||||
|
"author": { |
||||
|
"name": "Google Inc." |
||||
|
}, |
||||
|
"bin": { |
||||
|
"googlemaps": "bin/run.js" |
||||
|
}, |
||||
|
"bugs": { |
||||
|
"url": "https://github.com/googlemaps/google-maps-services-js/issues" |
||||
|
}, |
||||
|
"bundleDependencies": false, |
||||
|
"contributors": [ |
||||
|
{ |
||||
|
"name": "Stephen Farrar", |
||||
|
"email": "step@google.com" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "Stephen McDonald", |
||||
|
"email": "stephenmcd@google.com" |
||||
|
} |
||||
|
], |
||||
|
"deprecated": false, |
||||
|
"description": "Node.js client library for Google Maps API Web Services", |
||||
|
"devDependencies": { |
||||
|
"jasmine": ">=2.3.2 <2.5.0", |
||||
|
"jsdoc": "^3.4.0", |
||||
|
"priorityqueuejs": "^1.0.0", |
||||
|
"q": "^1.4.1" |
||||
|
}, |
||||
|
"files": [ |
||||
|
"lib", |
||||
|
"bin" |
||||
|
], |
||||
|
"homepage": "https://github.com/googlemaps/google-maps-services-js", |
||||
|
"keywords": [ |
||||
|
"google", |
||||
|
"maps", |
||||
|
"googlemaps", |
||||
|
"geo", |
||||
|
"geocode", |
||||
|
"timezone", |
||||
|
"api", |
||||
|
"client", |
||||
|
"roads", |
||||
|
"directions", |
||||
|
"navigation" |
||||
|
], |
||||
|
"license": "Apache-2.0", |
||||
|
"main": "./lib", |
||||
|
"name": "@google/maps", |
||||
|
"repository": { |
||||
|
"type": "git", |
||||
|
"url": "git+https://github.com/googlemaps/google-maps-services-js.git" |
||||
|
}, |
||||
|
"scripts": { |
||||
|
"jsdoc": "jsdoc -c docs/conf.json", |
||||
|
"test": "jasmine && jasmine spec/e2e/*.js" |
||||
|
}, |
||||
|
"version": "0.4.5" |
||||
|
} |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,91 @@ |
|||||
|
.banner, |
||||
|
.spot{ |
||||
|
|
||||
|
height: 150px; |
||||
|
border-radius: 3px;//0px 0px 3px 3px ; |
||||
|
position: relative; |
||||
|
padding: 5px; |
||||
|
|
||||
|
.content{ |
||||
|
background: $light-grey; |
||||
|
position: relative; |
||||
|
height: 100%; |
||||
|
overflow: hidden; |
||||
|
border-radius: 3px;//0px 0px 3px 3px ; |
||||
|
|
||||
|
.title{ |
||||
|
position: absolute; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
font-size: $font-10; |
||||
|
text-align: left; |
||||
|
padding: 4px; |
||||
|
background: rgba(0,0,0,0.5); |
||||
|
color: white; |
||||
|
width: 100%; |
||||
|
z-index: 1; |
||||
|
text-transform: uppercase; |
||||
|
} |
||||
|
|
||||
|
img{ |
||||
|
position: absolute; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
object-fit: cover; |
||||
|
object-position: center; |
||||
|
transition: .4s; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
&:hover{ |
||||
|
.content{ |
||||
|
img{ |
||||
|
transform: scale(1.2); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
.banner{ |
||||
|
height: 90px; |
||||
|
margin-bottom: 4px; |
||||
|
padding: 0; |
||||
|
} |
||||
|
|
||||
|
.contacts{ |
||||
|
padding: 15px 25px; |
||||
|
font-size: $font-12; |
||||
|
.fa{ |
||||
|
color: $green; |
||||
|
width: 25px; |
||||
|
font-size: $font-16; |
||||
|
height: 25px; |
||||
|
} |
||||
|
b{ |
||||
|
color: $green; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.last-news{ |
||||
|
font-size: $font-12; |
||||
|
.item{ |
||||
|
border-bottom: 1px solid $light-grey; |
||||
|
padding: 8px 10px; |
||||
|
.date{ |
||||
|
color: $red; |
||||
|
} |
||||
|
a{ |
||||
|
color: $dark-grey; |
||||
|
text-decoration: none; |
||||
|
transition: .4s; |
||||
|
&:hover{ |
||||
|
color: black; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
Loading…
Reference in new issue