├── .versions ├── LICENSE.md ├── README.md ├── google-maps-tests.js ├── google-maps.html ├── google-maps.js └── package.js /.versions: -------------------------------------------------------------------------------- 1 | babel-compiler@5.8.24_1 2 | babel-runtime@0.1.4 3 | base64@1.0.4 4 | binary-heap@1.0.4 5 | blaze@2.1.3 6 | blaze-tools@1.0.4 7 | boilerplate-generator@1.0.4 8 | caching-compiler@1.0.0 9 | caching-html-compiler@1.0.2 10 | callback-hook@1.0.4 11 | check@1.0.6 12 | dburles:google-maps@1.1.5 13 | ddp@1.2.2 14 | ddp-client@1.2.1 15 | ddp-common@1.2.1 16 | ddp-server@1.2.1 17 | deps@1.0.9 18 | diff-sequence@1.0.1 19 | ecmascript@0.1.5 20 | ecmascript-collections@0.1.6 21 | ejson@1.0.7 22 | geojson-utils@1.0.4 23 | html-tools@1.0.5 24 | htmljs@1.0.5 25 | id-map@1.0.4 26 | jquery@1.11.4 27 | local-test:dburles:google-maps@1.1.5 28 | logging@1.0.8 29 | meteor@1.1.9 30 | minifiers@1.1.7 31 | minimongo@1.0.10 32 | mongo@1.1.2 33 | mongo-id@1.0.1 34 | npm-mongo@1.4.39_1 35 | observe-sequence@1.0.7 36 | ordered-dict@1.0.4 37 | promise@0.5.0 38 | random@1.0.4 39 | reactive-var@1.0.6 40 | retry@1.0.4 41 | routepolicy@1.0.6 42 | spacebars@1.0.7 43 | spacebars-compiler@1.0.7 44 | templating@1.1.4 45 | templating-tools@1.0.0 46 | tinytest@1.0.6 47 | tracker@1.0.9 48 | ui@1.0.8 49 | underscore@1.0.4 50 | webapp@1.2.2 51 | webapp-hashing@1.0.5 52 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2015 David Burles 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Meteor Google Maps 2 | ================== 3 | 4 | [![Join the chat at https://gitter.im/dburles/meteor-google-maps](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/dburles/meteor-google-maps?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 5 | 6 | Latest version of the [Google Maps Javascript API](https://developers.google.com/maps/documentation/javascript/tutorial) with an interface designed for Meteor. 7 | 8 | - Supports multiple map instances 9 | - Ability to only load the API when it's required 10 | - Provides callbacks for individual maps when they render 11 | - API key + libraries 12 | - StreetViewPanorama support 13 | 14 | ## Table of Contents 15 | 16 | - [Installation](https://github.com/dburles/meteor-google-maps#installation) 17 | - [Examples](https://github.com/dburles/meteor-google-maps#examples) 18 | - [Usage Overview](https://github.com/dburles/meteor-google-maps#usage-overview) 19 | - [API](https://github.com/dburles/meteor-google-maps#api) 20 | - [Blaze Template](https://github.com/dburles/meteor-google-maps#blaze-template) 21 | - [create](https://github.com/dburles/meteor-google-maps#create) 22 | - [load](https://github.com/dburles/meteor-google-maps#load) 23 | - [loadUtilityLibrary](https://github.com/dburles/meteor-google-maps#loadutilitylibrary) 24 | - [loaded](https://github.com/dburles/meteor-google-maps#loaded) 25 | - [ready](https://github.com/dburles/meteor-google-maps#ready) 26 | - [initialize](https://github.com/dburles/meteor-google-maps#initialize) 27 | - [Mobile Platforms](https://github.com/dburles/meteor-google-maps#mobile-platforms) 28 | - [License](https://github.com/dburles/meteor-google-maps#license) 29 | 30 | ## Note 31 | 32 | The maps API is *client-side only*. Server side support may be added soon. 33 | 34 | ## Installation 35 | 36 | ```sh 37 | $ meteor add dburles:google-maps 38 | ``` 39 | 40 | Alternatively if you wish to add the package from within another package and have `GoogleMaps` available outside of package scope, use [api.imply](http://docs.meteor.com/#/full/pack_api_imply) in your `package.js`. 41 | 42 | ## Examples 43 | 44 | [Reactive geolocation](http://meteorcapture.com/reactive-geolocation-with-google-maps) 45 | 46 | [How to create a reactive Google map](http://meteorcapture.com/how-to-create-a-reactive-google-map) 47 | 48 | [React example](https://github.com/dburles/meteor-google-maps-react-example) 49 | 50 | [Demo project for the examples below](https://github.com/dburles/meteor-google-maps-demo) 51 | 52 | ## Usage Overview 53 | 54 | Call the `load` method to load the maps API. 55 | 56 | ```js 57 | if (Meteor.isClient) { 58 | Meteor.startup(function() { 59 | GoogleMaps.load(); 60 | }); 61 | } 62 | ``` 63 | 64 | If you prefer to load the maps API only once it's required, you may do so from within a Template `onRendered` hook. 65 | 66 | ```js 67 | Template.contact.onRendered(function() { 68 | GoogleMaps.load(); 69 | }); 70 | ``` 71 | 72 | Wrap the map template to set the width and height. 73 | 74 | ```html 75 | 76 |
77 | {{> googleMap name="exampleMap" options=exampleMapOptions}} 78 |
79 | 80 | ``` 81 | 82 | ```css 83 | .map-container { 84 | width: 800px; 85 | max-width: 100%; 86 | height: 500px; 87 | } 88 | ``` 89 | 90 | Pass through the map initialization options by creating a template helper. This will only run once. 91 | 92 | ```js 93 | Template.body.helpers({ 94 | exampleMapOptions: function() { 95 | // Make sure the maps API has loaded 96 | if (GoogleMaps.loaded()) { 97 | // Map initialization options 98 | return { 99 | center: new google.maps.LatLng(-37.8136, 144.9631), 100 | zoom: 8 101 | }; 102 | } 103 | } 104 | }); 105 | ``` 106 | 107 | Place the `ready` callback within the template `onCreated` callback. This is also where you handle map events and reactive updates. 108 | 109 | ```js 110 | Template.body.onCreated(function() { 111 | // We can use the `ready` callback to interact with the map API once the map is ready. 112 | GoogleMaps.ready('exampleMap', function(map) { 113 | // Add a marker to the map once it's ready 114 | var marker = new google.maps.Marker({ 115 | position: map.options.center, 116 | map: map.instance 117 | }); 118 | }); 119 | }); 120 | ``` 121 | 122 | Access a map instance any time by using the `maps` object. 123 | 124 | ```js 125 | GoogleMaps.maps.exampleMap.instance 126 | ``` 127 | 128 | ## API 129 | 130 | ### Blaze Template 131 | 132 | `{{> googleMap [type=String] name=String options=Object}}` 133 | 134 | - type (Optional) 135 | - Currently supported types: Map, StreetViewPanorama (defaults to 'Map') 136 | - name 137 | - Provide a name to reference this map 138 | - options 139 | - Map initialization options 140 | 141 | ### create 142 | 143 | `GoogleMaps.create({object})` 144 | 145 | An alternative to using the `googleMap` Blaze template. Call this function to create a new map instance and attach it to a DOM element. 146 | 147 | Options: 148 | 149 | - `name` - Name to reference this map. 150 | - `element` - A DOM element to attach the map to. 151 | - `options` - The map options. 152 | - `type` (optional) - Map or StreetViewPanorama. Defaults to Map. 153 | 154 | Example: 155 | 156 | ```js 157 | GoogleMaps.create({ 158 | name: 'exampleMap', 159 | element: document.getElementById('exampleMap'), 160 | options: { 161 | center: new google.maps.LatLng(-37.8136, 144.9631), 162 | zoom: 8 163 | } 164 | }); 165 | ``` 166 | 167 | ### load 168 | 169 | `GoogleMaps.load([options])` 170 | 171 | Loads the map API. Options passed in are automatically appended to the maps url. 172 | By default `v3.exp` will be loaded. For full documentation on these options see https://developers.google.com/maps/documentation/javascript/tutorial#Loading_the_Maps_API 173 | 174 | Example: 175 | 176 | ```js 177 | GoogleMaps.load({ v: '3', key: '12345', libraries: 'geometry,places' }); 178 | ``` 179 | 180 | ### loadUtilityLibrary 181 | 182 | `GoogleMaps.loadUtilityLibrary('/path/to/library.js')` 183 | 184 | A method to ease loading external [utility libraries](https://code.google.com/p/google-maps-utility-library-v3/wiki/Libraries). These libraries will load once the Google Maps API has initialized. 185 | 186 | ### loaded 187 | 188 | `GoogleMaps.loaded()` 189 | 190 | Reactive method which returns `true` once the maps API has loaded, or after manually calling `GoogleMaps.initialize()` (See further down). 191 | 192 | ### ready 193 | 194 | `GoogleMaps.ready('name', callback)` 195 | 196 | Runs once the specified map has rendered. 197 | 198 | - `name` *String* 199 | - `callback` *Function* 200 | 201 | Example: 202 | 203 | ```js 204 | GoogleMaps.ready('exampleMap', function(map) { 205 | // map.instance, map.options 206 | }); 207 | ``` 208 | 209 | The callback function returns an object containing two properties: 210 | 211 | - instance 212 | - The Google map instance 213 | - options 214 | - The options passed through from the Template helper (see Usage Overview above) 215 | 216 | You can also access this object directly by name: 217 | 218 | ```js 219 | GoogleMaps.maps.exampleMap 220 | ``` 221 | 222 | ### initialize 223 | 224 | `GoogleMaps.initialize()` 225 | 226 | This function is passed into the Google maps URL as the callback parameter when calling `GoogleMaps.load()`. 227 | In the case where the maps library has already been loaded by some other means, calling `GoogleMaps.initialize()` will set `GoogleMaps.loaded()` to `true`. 228 | 229 | ## Mobile platforms 230 | 231 | If you're targeting mobile platforms you'll need to configure the following access rules in `mobile-config.js`. 232 | 233 | ```js 234 | App.accessRule('*.google.com/*'); 235 | App.accessRule('*.googleapis.com/*'); 236 | App.accessRule('*.gstatic.com/*'); 237 | ``` 238 | 239 | For more refer to the [official documentation](http://docs.meteor.com/#/full/mobileconfigjs). 240 | 241 | ## License 242 | 243 | MIT 244 | -------------------------------------------------------------------------------- /google-maps-tests.js: -------------------------------------------------------------------------------- 1 | // Write your tests here! 2 | // Here is an example. 3 | Tinytest.add('example', function (test) { 4 | test.equal(true, true); 5 | }); 6 | -------------------------------------------------------------------------------- /google-maps.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /google-maps.js: -------------------------------------------------------------------------------- 1 | var supportedTypes = ['Map', 'StreetViewPanorama']; 2 | 3 | GoogleMaps = { 4 | load: _.once(function(options) { 5 | options = _.extend({ v: '3.exp' }, options); 6 | var params = _.map(options, function(value, key) { return key + '=' + value; }).join('&'); 7 | var script = document.createElement('script'); 8 | script.type = 'text/javascript'; 9 | script.src = 'https://maps.googleapis.com/maps/api/js?' + params + 10 | '&callback=GoogleMaps.initialize'; 11 | 12 | document.body.appendChild(script); 13 | }), 14 | utilityLibraries: [], 15 | loadUtilityLibrary: function(path) { 16 | this.utilityLibraries.push(path); 17 | }, 18 | _loaded: new ReactiveVar(false), 19 | loaded: function() { 20 | return this._loaded.get(); 21 | }, 22 | maps: {}, 23 | _callbacks: {}, 24 | initialize: function() { 25 | this._loaded.set(true); 26 | _.each(this.utilityLibraries, function(path) { 27 | var script = document.createElement('script'); 28 | script.type = 'text/javascript'; 29 | script.src = path; 30 | 31 | document.body.appendChild(script); 32 | }); 33 | }, 34 | _ready: function(name, map) { 35 | _.each(this._callbacks[name], function(cb) { 36 | if (_.isFunction(cb)) { 37 | cb(map); 38 | } 39 | }); 40 | }, 41 | ready: function(name, cb) { 42 | if (! this._callbacks[name]) { 43 | this._callbacks[name] = []; 44 | } 45 | // make sure we run the callback only once 46 | // as the tilesloaded event will also run after initial load 47 | this._callbacks[name].push(_.once(cb)); 48 | }, 49 | // options: function(options) { 50 | // var self = this; 51 | // return function() { 52 | // if (self.loaded()) 53 | // return options(); 54 | // }; 55 | // }, 56 | get: function(name) { 57 | return this.maps[name]; 58 | }, 59 | _create: function(name, options) { 60 | var self = this; 61 | self.maps[name] = { 62 | instance: options.instance, 63 | options: options.options 64 | }; 65 | 66 | if (options.type === 'StreetViewPanorama') { 67 | options.instance.setVisible(true); 68 | self._ready(name, self.maps[name]); 69 | } else { 70 | google.maps.event.addListener(options.instance, 'tilesloaded', function() { 71 | self._ready(name, self.maps[name]); 72 | }); 73 | } 74 | }, 75 | create: function(options) { 76 | // default to Map 77 | var type = options.type ? options.type : 'Map'; 78 | if (! _.include(supportedTypes, type)) { 79 | throw new Meteor.Error("GoogleMaps - Invalid type argument: " + type); 80 | } 81 | 82 | this._create(options.name, { 83 | type: type, 84 | instance: new google.maps[type](options.element, options.options), 85 | options: options.options 86 | }); 87 | } 88 | }; 89 | 90 | Template.googleMap.onRendered(function() { 91 | var self = this; 92 | self.autorun(function(c) { 93 | // if the api has loaded 94 | if (GoogleMaps.loaded()) { 95 | var data = Template.currentData(); 96 | 97 | if (! data.options) { 98 | return; 99 | } 100 | if (! data.name) { 101 | throw new Meteor.Error("GoogleMaps - Missing argument: name"); 102 | } 103 | 104 | self._name = data.name; 105 | 106 | var canvas = self.$('.map-canvas').get(0); 107 | 108 | GoogleMaps.create({ 109 | name: data.name, 110 | type: data.type, 111 | element: canvas, 112 | options: data.options 113 | }); 114 | 115 | c.stop(); 116 | } 117 | }); 118 | }); 119 | 120 | Template.googleMap.onDestroyed(function() { 121 | if (GoogleMaps.maps[this._name]) { 122 | google.maps.event.clearInstanceListeners(GoogleMaps.maps[this._name].instance); 123 | delete GoogleMaps.maps[this._name]; 124 | } 125 | }); 126 | -------------------------------------------------------------------------------- /package.js: -------------------------------------------------------------------------------- 1 | Package.describe({ 2 | name: 'dburles:google-maps', 3 | summary: 'Google Maps Javascript API v3', 4 | version: '1.1.5', 5 | git: 'https://github.com/dburles/meteor-google-maps.git' 6 | }); 7 | 8 | Package.onUse(function(api) { 9 | api.versionsFrom('1.0'); 10 | api.use([ 11 | 'templating', 12 | 'reactive-var', 13 | 'underscore']); 14 | api.addFiles([ 15 | 'google-maps.html', 16 | 'google-maps.js'], 'client'); 17 | api.export('GoogleMaps', 'client'); 18 | }); 19 | 20 | Package.onTest(function(api) { 21 | api.use('tinytest'); 22 | api.use('dburles:google-maps'); 23 | api.addFiles('google-maps-tests.js'); 24 | }); 25 | --------------------------------------------------------------------------------