gmaps-rails 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 327693bbe44f8208f1d9880344588f013b428ab3
4
+ data.tar.gz: f70ac97858f5ca3d7e45b76fdd9b113f5c111ad3
5
+ SHA512:
6
+ metadata.gz: 0ee9a32097e6e1aefffb6350bf70120cc1b444e3c4a87e8feee72556ffd9593da0a49946e3588e171dcd1bf69ccaab7786f3b2df2af22d353015e4647cd3f8af
7
+ data.tar.gz: 1fb576e7e0414785fad9459bd0deedafe15b8e449f0c614cbd9796e7d663dd1bfb755625400fdd7d1fcaa0cbd896740f76d9c64a5eacfe4c7fbec422865d04a2
@@ -0,0 +1,24 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
23
+
24
+ vendor/bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in gmaps-rails.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Kentaro Imai
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,119 @@
1
+ # gmaps-rails
2
+
3
+ gmaps-rails is a gem which includes [GMaps.js](http://hpneo.github.io/gmaps/)
4
+ and provides an easy way to use it in Rails.
5
+
6
+ GMaps.js has [over 4,000 stars on Github](https://github.com/hpneo/gmaps) and
7
+ you will love to use it with Rails.
8
+
9
+
10
+ - This is not [gmaps4rails](https://github.com/apneadiving/Google-Maps-for-Rails) gem.
11
+
12
+ - If you just want GMaps.js in your Rails app, I recommend
13
+ [gmapsjs](https://github.com/xenda/gmapsjs).
14
+
15
+
16
+
17
+ ## Installation
18
+
19
+ Add this line to your application's Gemfile:
20
+
21
+ gem 'gmaps-rails'
22
+
23
+ And then execute:
24
+
25
+ $ bundle
26
+
27
+ Or install it yourself as:
28
+
29
+ $ gem install gmaps-rails
30
+
31
+ ## Usage
32
+
33
+ ### GMaps.js
34
+ First of all, you have to include Google Maps API in a view file or in a layout file.
35
+
36
+ ```erb
37
+ <%= javascript_include_tag 'http://maps.googleapis.com/maps/api/js?key=YOUR_KEY&sensor=true' %>
38
+ ```
39
+
40
+ You can use [GMaps.js](http://hpneo.github.io/gmaps/)
41
+ simply by requiring `gmaps` in `app/assets/javascripts/application.js` file.
42
+
43
+ ```javascript
44
+ :
45
+ :
46
+ //= turbolinks
47
+ //= gmaps
48
+ //= require_tree .
49
+ ```
50
+
51
+ ### Helpers
52
+ #### GMaps in Ruby
53
+ In addition to that, this gem has helpers.
54
+
55
+ You can define GMaps object in a controller or a presenter \(such as [Draper](https://github.com/drapergem/draper)\).
56
+
57
+ ```ruby
58
+ @map = GMaps.new(div: '#map', lat: -12.043333, lng: -77.028333)
59
+ @map.addMarker(lat: -12.043333,
60
+ lng: -77.028333,
61
+ title: 'Lima',
62
+ click: GMaps::JS["function(e) { alert('You clicked in this marker'); }"])
63
+ @map.addMarker(lat: -12.042,
64
+ lng: -77.028333,
65
+ title: 'Marker with InfoWindow',
66
+ infoWindow: {
67
+ content: '<p>HTML Content</p>'
68
+ })
69
+ ```
70
+
71
+ You can show maps as follows:
72
+ ```erb
73
+ <script>
74
+ jQuery(function() {
75
+ <%= @map.to_js %>
76
+ }
77
+ </script>
78
+ <body>
79
+ <div sytle='width: 800px'>
80
+ <div id='map' style='width: 800px; height: 400px'></div>
81
+ </div>
82
+ </body>
83
+ ```
84
+
85
+
86
+ #### gmaps_ujs
87
+ By requiring `gmaps_ujs` in addition to `gmaps`, you can remove all JavaScript code for Google Maps.
88
+
89
+ ```javascript
90
+ :
91
+ :
92
+ //= turbolinks
93
+ //= gmaps
94
+ //= gmaps_ujs
95
+ //= require_tree .
96
+ ```
97
+
98
+ Controller code is same as the above example, but you can omit `div` parameter when initializing GMaps object.
99
+
100
+ ```ruby
101
+ @map = GMaps.new(lat: -12.043333, lng: -77.028333)
102
+ ```
103
+
104
+ In a view file, you can show maps by using `map_div` helper method.
105
+ ```erb
106
+ <body>
107
+ <div sytle='width: 800px'>
108
+ <%= map_div @map, style: 'width: 800px; height: 400px' %>
109
+ </div>
110
+ </body>
111
+ ```
112
+
113
+ ## Contributing
114
+
115
+ 1. Fork it ( https://github.com/kentaroi/gmaps-rails/fork )
116
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
117
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
118
+ 4. Push to the branch (`git push origin my-new-feature`)
119
+ 5. Create a new Pull Request
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'gmaps/rails/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "gmaps-rails"
8
+ spec.version = GMaps::Rails::VERSION
9
+ spec.authors = ["Kentaro Imai"]
10
+ spec.email = ["kentaroi@gmail.com"]
11
+ spec.summary = %q{gmaps-rails is a gem which includes GMaps.js and provides an easy way to use it in Rails}
12
+ spec.description = %q{gmaps-rails is a gem which includes GMaps.js and provides an easy way to use it in Rails. GMaps.js has over 4,000 stars on Github and you will love to use it with Rails.}
13
+ spec.homepage = "https://github.com/kentaroi/gmaps-rails"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "rails"
22
+ spec.add_development_dependency "bundler", "~> 1.6"
23
+ spec.add_development_dependency "rake"
24
+ end
@@ -0,0 +1,5 @@
1
+ require 'rails'
2
+ require 'gmaps'
3
+ require 'gmaps/rails/railtie'
4
+ require 'gmaps/rails/engine'
5
+ require 'gmaps/rails/version'
@@ -0,0 +1,40 @@
1
+ require 'active_support/core_ext/string/output_safety'
2
+ require 'gmaps/js'
3
+ require 'gmaps/rails/core_ext'
4
+
5
+ class GMaps
6
+ class << self
7
+ def [](*args)
8
+ GMaps.new(*args)
9
+ end
10
+ end
11
+
12
+ attr_accessor :map, :directives
13
+
14
+ def initialize(options={})
15
+ @map = options
16
+ @directives = []
17
+ end
18
+
19
+ def method_missing(m, *args)
20
+ @directives << {name: m, args: args}
21
+ end
22
+
23
+ def name
24
+ @name ||= @map[:div] ? @map[:div].gsub(/[#\.]/, '') : 'map'
25
+ end
26
+ attr_writer :name
27
+
28
+ def to_js
29
+ ("var #{name} = GMaps(#{{div: '#map'}.merge!(@map)._to_s19});\n" +
30
+ @directives.map{ |directive|
31
+ func = directive[:name]
32
+ args = directive[:args]
33
+ "#{name}.#{func}(#{args.map{|e| e._to_s19}.join(', ')})"
34
+ }.join(";\n")).html_safe
35
+ end
36
+
37
+ def to_s
38
+ {map: @map, directives: @directives}._to_s19
39
+ end
40
+ end
@@ -0,0 +1,61 @@
1
+ require 'active_support/core_ext/string/output_safety'
2
+
3
+ class GMaps
4
+ class JS
5
+ class << self
6
+ def [](*args)
7
+ self.new(*args)
8
+ end
9
+ end
10
+
11
+ def initialize(str, *args)
12
+ @str = if args.empty?
13
+ str
14
+ elsif args.length == 1 && args.first.is_a?(Hash)
15
+ escaped_args = {}
16
+ args.first.each { |k, v| escaped_args[k] = v.is_a?(String) ? escape_javascript(v) : v}
17
+ str % (escaped_args)
18
+ else
19
+ args.map!{ |arg| arg.is_a?(String) ? escape_javascript(arg) : arg}
20
+ str % args
21
+ end
22
+ end
23
+
24
+ def inspect
25
+ @str
26
+ end
27
+ alias to_s inspect
28
+
29
+
30
+ ###################################################
31
+ # escape_javascript
32
+ # Copied from ActionView::Helpers::JavaScriptHelper
33
+ JS_ESCAPE_MAP = {
34
+ '\\' => '\\\\',
35
+ '</' => '<\/',
36
+ "\r\n" => '\n',
37
+ "\n" => '\n',
38
+ "\r" => '\n',
39
+ '"' => '\\"',
40
+ "'" => "\\'"
41
+ }
42
+
43
+ JS_ESCAPE_MAP["\342\200\250".force_encoding(Encoding::UTF_8).encode!] = '&#x2028;'
44
+ JS_ESCAPE_MAP["\342\200\251".force_encoding(Encoding::UTF_8).encode!] = '&#x2029;'
45
+
46
+ # Escapes carriage returns and single and double quotes for JavaScript segments.
47
+ #
48
+ # Also available through the alias j(). This is particularly helpful in JavaScript
49
+ # responses, like:
50
+ #
51
+ # $('some_element').replaceWith('<%=j render 'some/element_template' %>');
52
+ def escape_javascript(javascript)
53
+ if javascript
54
+ result = javascript.gsub(/(\\|<\/|\r\n|\342\200\250|\342\200\251|[\n\r"'])/u) {|match| JS_ESCAPE_MAP[match] }
55
+ javascript.html_safe? ? result.html_safe : result
56
+ else
57
+ ''
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,17 @@
1
+ class GMaps
2
+ module Rails
3
+ class << self
4
+ def to_s19(val)
5
+ case val
6
+ when String, Symbol
7
+ "\"#{val}\""
8
+ when Array, Hash
9
+ val._to_s19
10
+ else
11
+ val.inspect
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+
@@ -0,0 +1,15 @@
1
+ require 'gmaps/rails'
2
+
3
+ class Array
4
+ def _to_s19
5
+ '[' + self.map { |e| GMaps::Rails.to_s19(e) }.join(', ') + ']'
6
+ end
7
+ end
8
+
9
+ class Hash
10
+ def _to_s19
11
+ '{' + self.map { |k, v|
12
+ "#{k}: #{GMaps::Rails.to_s19(v)}"
13
+ }.join(', ') + '}'
14
+ end
15
+ end
@@ -0,0 +1,6 @@
1
+ class GMaps
2
+ module Rails
3
+ class Engine < ::Rails::Engine
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,11 @@
1
+ require 'gmaps/rails/view_helpers'
2
+
3
+ class GMaps
4
+ module Rails
5
+ class Railtie < ::Rails::Railtie
6
+ initializer "gmaps-rails.view_helpers" do
7
+ ActionView::Base.send :include, ViewHelpers
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ class GMaps
2
+ module Rails
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,9 @@
1
+ class GMaps
2
+ module Rails
3
+ module ViewHelpers
4
+ def map_div(gmaps, options={})
5
+ content_tag(:div, nil, {id: 'map', data: {map: h(gmaps.to_s)}}.merge(options))
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,2110 @@
1
+ (function(root, factory) {
2
+ if(typeof exports === 'object') {
3
+ module.exports = factory();
4
+ }
5
+ else if(typeof define === 'function' && define.amd) {
6
+ define('GMaps', [], factory);
7
+ }
8
+
9
+ root.GMaps = factory();
10
+
11
+ }(this, function() {
12
+
13
+ /*!
14
+ * GMaps.js v0.4.13
15
+ * http://hpneo.github.com/gmaps/
16
+ *
17
+ * Copyright 2014, Gustavo Leon
18
+ * Released under the MIT License.
19
+ */
20
+
21
+ if (!(typeof window.google === 'object' && window.google.maps)) {
22
+ throw 'Google Maps API is required. Please register the following JavaScript library http://maps.google.com/maps/api/js?sensor=true.'
23
+ }
24
+
25
+ var extend_object = function(obj, new_obj) {
26
+ var name;
27
+
28
+ if (obj === new_obj) {
29
+ return obj;
30
+ }
31
+
32
+ for (name in new_obj) {
33
+ obj[name] = new_obj[name];
34
+ }
35
+
36
+ return obj;
37
+ };
38
+
39
+ var replace_object = function(obj, replace) {
40
+ var name;
41
+
42
+ if (obj === replace) {
43
+ return obj;
44
+ }
45
+
46
+ for (name in replace) {
47
+ if (obj[name] != undefined) {
48
+ obj[name] = replace[name];
49
+ }
50
+ }
51
+
52
+ return obj;
53
+ };
54
+
55
+ var array_map = function(array, callback) {
56
+ var original_callback_params = Array.prototype.slice.call(arguments, 2),
57
+ array_return = [],
58
+ array_length = array.length,
59
+ i;
60
+
61
+ if (Array.prototype.map && array.map === Array.prototype.map) {
62
+ array_return = Array.prototype.map.call(array, function(item) {
63
+ callback_params = original_callback_params;
64
+ callback_params.splice(0, 0, item);
65
+
66
+ return callback.apply(this, callback_params);
67
+ });
68
+ }
69
+ else {
70
+ for (i = 0; i < array_length; i++) {
71
+ callback_params = original_callback_params;
72
+ callback_params.splice(0, 0, array[i]);
73
+ array_return.push(callback.apply(this, callback_params));
74
+ }
75
+ }
76
+
77
+ return array_return;
78
+ };
79
+
80
+ var array_flat = function(array) {
81
+ var new_array = [],
82
+ i;
83
+
84
+ for (i = 0; i < array.length; i++) {
85
+ new_array = new_array.concat(array[i]);
86
+ }
87
+
88
+ return new_array;
89
+ };
90
+
91
+ var coordsToLatLngs = function(coords, useGeoJSON) {
92
+ var first_coord = coords[0],
93
+ second_coord = coords[1];
94
+
95
+ if (useGeoJSON) {
96
+ first_coord = coords[1];
97
+ second_coord = coords[0];
98
+ }
99
+
100
+ return new google.maps.LatLng(first_coord, second_coord);
101
+ };
102
+
103
+ var arrayToLatLng = function(coords, useGeoJSON) {
104
+ var i;
105
+
106
+ for (i = 0; i < coords.length; i++) {
107
+ if (coords[i].length > 0 && typeof(coords[i][0]) == "object") {
108
+ coords[i] = arrayToLatLng(coords[i], useGeoJSON);
109
+ }
110
+ else {
111
+ coords[i] = coordsToLatLngs(coords[i], useGeoJSON);
112
+ }
113
+ }
114
+
115
+ return coords;
116
+ };
117
+
118
+ var getElementById = function(id, context) {
119
+ var element,
120
+ id = id.replace('#', '');
121
+
122
+ if ('jQuery' in this && context) {
123
+ element = $("#" + id, context)[0];
124
+ } else {
125
+ element = document.getElementById(id);
126
+ };
127
+
128
+ return element;
129
+ };
130
+
131
+ var findAbsolutePosition = function(obj) {
132
+ var curleft = 0,
133
+ curtop = 0;
134
+
135
+ if (obj.offsetParent) {
136
+ do {
137
+ curleft += obj.offsetLeft;
138
+ curtop += obj.offsetTop;
139
+ } while (obj = obj.offsetParent);
140
+ }
141
+
142
+ return [curleft, curtop];
143
+ };
144
+
145
+ var GMaps = (function(global) {
146
+ "use strict";
147
+
148
+ var doc = document;
149
+
150
+ var GMaps = function(options) {
151
+ if (!this) return new GMaps(options);
152
+
153
+ options.zoom = options.zoom || 15;
154
+ options.mapType = options.mapType || 'roadmap';
155
+
156
+ var self = this,
157
+ i,
158
+ events_that_hide_context_menu = ['bounds_changed', 'center_changed', 'click', 'dblclick', 'drag', 'dragend', 'dragstart', 'idle', 'maptypeid_changed', 'projection_changed', 'resize', 'tilesloaded', 'zoom_changed'],
159
+ events_that_doesnt_hide_context_menu = ['mousemove', 'mouseout', 'mouseover'],
160
+ options_to_be_deleted = ['el', 'lat', 'lng', 'mapType', 'width', 'height', 'markerClusterer', 'enableNewStyle'],
161
+ container_id = options.el || options.div,
162
+ markerClustererFunction = options.markerClusterer,
163
+ mapType = google.maps.MapTypeId[options.mapType.toUpperCase()],
164
+ map_center = new google.maps.LatLng(options.lat, options.lng),
165
+ zoomControl = options.zoomControl || true,
166
+ zoomControlOpt = options.zoomControlOpt || {
167
+ style: 'DEFAULT',
168
+ position: 'TOP_LEFT'
169
+ },
170
+ zoomControlStyle = zoomControlOpt.style || 'DEFAULT',
171
+ zoomControlPosition = zoomControlOpt.position || 'TOP_LEFT',
172
+ panControl = options.panControl || true,
173
+ mapTypeControl = options.mapTypeControl || true,
174
+ scaleControl = options.scaleControl || true,
175
+ streetViewControl = options.streetViewControl || true,
176
+ overviewMapControl = overviewMapControl || true,
177
+ map_options = {},
178
+ map_base_options = {
179
+ zoom: this.zoom,
180
+ center: map_center,
181
+ mapTypeId: mapType
182
+ },
183
+ map_controls_options = {
184
+ panControl: panControl,
185
+ zoomControl: zoomControl,
186
+ zoomControlOptions: {
187
+ style: google.maps.ZoomControlStyle[zoomControlStyle],
188
+ position: google.maps.ControlPosition[zoomControlPosition]
189
+ },
190
+ mapTypeControl: mapTypeControl,
191
+ scaleControl: scaleControl,
192
+ streetViewControl: streetViewControl,
193
+ overviewMapControl: overviewMapControl
194
+ };
195
+
196
+ if (typeof(options.el) === 'string' || typeof(options.div) === 'string') {
197
+ this.el = getElementById(container_id, options.context);
198
+ } else {
199
+ this.el = container_id;
200
+ }
201
+
202
+ if (typeof(this.el) === 'undefined' || this.el === null) {
203
+ throw 'No element defined.';
204
+ }
205
+
206
+ window.context_menu = window.context_menu || {};
207
+ window.context_menu[self.el.id] = {};
208
+
209
+ this.controls = [];
210
+ this.overlays = [];
211
+ this.layers = []; // array with kml/georss and fusiontables layers, can be as many
212
+ this.singleLayers = {}; // object with the other layers, only one per layer
213
+ this.markers = [];
214
+ this.polylines = [];
215
+ this.routes = [];
216
+ this.polygons = [];
217
+ this.infoWindow = null;
218
+ this.overlay_el = null;
219
+ this.zoom = options.zoom;
220
+ this.registered_events = {};
221
+
222
+ this.el.style.width = options.width || this.el.scrollWidth || this.el.offsetWidth;
223
+ this.el.style.height = options.height || this.el.scrollHeight || this.el.offsetHeight;
224
+
225
+ google.maps.visualRefresh = options.enableNewStyle;
226
+
227
+ for (i = 0; i < options_to_be_deleted.length; i++) {
228
+ delete options[options_to_be_deleted[i]];
229
+ }
230
+
231
+ if(options.disableDefaultUI != true) {
232
+ map_base_options = extend_object(map_base_options, map_controls_options);
233
+ }
234
+
235
+ map_options = extend_object(map_base_options, options);
236
+
237
+ for (i = 0; i < events_that_hide_context_menu.length; i++) {
238
+ delete map_options[events_that_hide_context_menu[i]];
239
+ }
240
+
241
+ for (i = 0; i < events_that_doesnt_hide_context_menu.length; i++) {
242
+ delete map_options[events_that_doesnt_hide_context_menu[i]];
243
+ }
244
+
245
+ this.map = new google.maps.Map(this.el, map_options);
246
+
247
+ if (markerClustererFunction) {
248
+ this.markerClusterer = markerClustererFunction.apply(this, [this.map]);
249
+ }
250
+
251
+ var buildContextMenuHTML = function(control, e) {
252
+ var html = '',
253
+ options = window.context_menu[self.el.id][control];
254
+
255
+ for (var i in options){
256
+ if (options.hasOwnProperty(i)) {
257
+ var option = options[i];
258
+
259
+ html += '<li><a id="' + control + '_' + i + '" href="#">' + option.title + '</a></li>';
260
+ }
261
+ }
262
+
263
+ if (!getElementById('gmaps_context_menu')) return;
264
+
265
+ var context_menu_element = getElementById('gmaps_context_menu');
266
+
267
+ context_menu_element.innerHTML = html;
268
+
269
+ var context_menu_items = context_menu_element.getElementsByTagName('a'),
270
+ context_menu_items_count = context_menu_items.length,
271
+ i;
272
+
273
+ for (i = 0; i < context_menu_items_count; i++) {
274
+ var context_menu_item = context_menu_items[i];
275
+
276
+ var assign_menu_item_action = function(ev){
277
+ ev.preventDefault();
278
+
279
+ options[this.id.replace(control + '_', '')].action.apply(self, [e]);
280
+ self.hideContextMenu();
281
+ };
282
+
283
+ google.maps.event.clearListeners(context_menu_item, 'click');
284
+ google.maps.event.addDomListenerOnce(context_menu_item, 'click', assign_menu_item_action, false);
285
+ }
286
+
287
+ var position = findAbsolutePosition.apply(this, [self.el]),
288
+ left = position[0] + e.pixel.x - 15,
289
+ top = position[1] + e.pixel.y- 15;
290
+
291
+ context_menu_element.style.left = left + "px";
292
+ context_menu_element.style.top = top + "px";
293
+
294
+ context_menu_element.style.display = 'block';
295
+ };
296
+
297
+ this.buildContextMenu = function(control, e) {
298
+ if (control === 'marker') {
299
+ e.pixel = {};
300
+
301
+ var overlay = new google.maps.OverlayView();
302
+ overlay.setMap(self.map);
303
+
304
+ overlay.draw = function() {
305
+ var projection = overlay.getProjection(),
306
+ position = e.marker.getPosition();
307
+
308
+ e.pixel = projection.fromLatLngToContainerPixel(position);
309
+
310
+ buildContextMenuHTML(control, e);
311
+ };
312
+ }
313
+ else {
314
+ buildContextMenuHTML(control, e);
315
+ }
316
+ };
317
+
318
+ this.setContextMenu = function(options) {
319
+ window.context_menu[self.el.id][options.control] = {};
320
+
321
+ var i,
322
+ ul = doc.createElement('ul');
323
+
324
+ for (i in options.options) {
325
+ if (options.options.hasOwnProperty(i)) {
326
+ var option = options.options[i];
327
+
328
+ window.context_menu[self.el.id][options.control][option.name] = {
329
+ title: option.title,
330
+ action: option.action
331
+ };
332
+ }
333
+ }
334
+
335
+ ul.id = 'gmaps_context_menu';
336
+ ul.style.display = 'none';
337
+ ul.style.position = 'absolute';
338
+ ul.style.minWidth = '100px';
339
+ ul.style.background = 'white';
340
+ ul.style.listStyle = 'none';
341
+ ul.style.padding = '8px';
342
+ ul.style.boxShadow = '2px 2px 6px #ccc';
343
+
344
+ doc.body.appendChild(ul);
345
+
346
+ var context_menu_element = getElementById('gmaps_context_menu')
347
+
348
+ google.maps.event.addDomListener(context_menu_element, 'mouseout', function(ev) {
349
+ if (!ev.relatedTarget || !this.contains(ev.relatedTarget)) {
350
+ window.setTimeout(function(){
351
+ context_menu_element.style.display = 'none';
352
+ }, 400);
353
+ }
354
+ }, false);
355
+ };
356
+
357
+ this.hideContextMenu = function() {
358
+ var context_menu_element = getElementById('gmaps_context_menu');
359
+
360
+ if (context_menu_element) {
361
+ context_menu_element.style.display = 'none';
362
+ }
363
+ };
364
+
365
+ var setupListener = function(object, name) {
366
+ google.maps.event.addListener(object, name, function(e){
367
+ if (e == undefined) {
368
+ e = this;
369
+ }
370
+
371
+ options[name].apply(this, [e]);
372
+
373
+ self.hideContextMenu();
374
+ });
375
+ };
376
+
377
+ for (var ev = 0; ev < events_that_hide_context_menu.length; ev++) {
378
+ var name = events_that_hide_context_menu[ev];
379
+
380
+ if (name in options) {
381
+ setupListener(this.map, name);
382
+ }
383
+ }
384
+
385
+ for (var ev = 0; ev < events_that_doesnt_hide_context_menu.length; ev++) {
386
+ var name = events_that_doesnt_hide_context_menu[ev];
387
+
388
+ if (name in options) {
389
+ setupListener(this.map, name);
390
+ }
391
+ }
392
+
393
+ google.maps.event.addListener(this.map, 'rightclick', function(e) {
394
+ if (options.rightclick) {
395
+ options.rightclick.apply(this, [e]);
396
+ }
397
+
398
+ if(window.context_menu[self.el.id]['map'] != undefined) {
399
+ self.buildContextMenu('map', e);
400
+ }
401
+ });
402
+
403
+ this.refresh = function() {
404
+ google.maps.event.trigger(this.map, 'resize');
405
+ };
406
+
407
+ this.fitZoom = function() {
408
+ var latLngs = [],
409
+ markers_length = this.markers.length,
410
+ i;
411
+
412
+ for (i = 0; i < markers_length; i++) {
413
+ if(typeof(this.markers[i].visible) === 'boolean' && this.markers[i].visible) {
414
+ latLngs.push(this.markers[i].getPosition());
415
+ }
416
+ }
417
+
418
+ this.fitLatLngBounds(latLngs);
419
+ };
420
+
421
+ this.fitLatLngBounds = function(latLngs) {
422
+ var total = latLngs.length;
423
+ var bounds = new google.maps.LatLngBounds();
424
+
425
+ for(var i=0; i < total; i++) {
426
+ bounds.extend(latLngs[i]);
427
+ }
428
+
429
+ this.map.fitBounds(bounds);
430
+ };
431
+
432
+ this.setCenter = function(lat, lng, callback) {
433
+ this.map.panTo(new google.maps.LatLng(lat, lng));
434
+
435
+ if (callback) {
436
+ callback();
437
+ }
438
+ };
439
+
440
+ this.getElement = function() {
441
+ return this.el;
442
+ };
443
+
444
+ this.zoomIn = function(value) {
445
+ value = value || 1;
446
+
447
+ this.zoom = this.map.getZoom() + value;
448
+ this.map.setZoom(this.zoom);
449
+ };
450
+
451
+ this.zoomOut = function(value) {
452
+ value = value || 1;
453
+
454
+ this.zoom = this.map.getZoom() - value;
455
+ this.map.setZoom(this.zoom);
456
+ };
457
+
458
+ var native_methods = [],
459
+ method;
460
+
461
+ for (method in this.map) {
462
+ if (typeof(this.map[method]) == 'function' && !this[method]) {
463
+ native_methods.push(method);
464
+ }
465
+ }
466
+
467
+ for (i=0; i < native_methods.length; i++) {
468
+ (function(gmaps, scope, method_name) {
469
+ gmaps[method_name] = function(){
470
+ return scope[method_name].apply(scope, arguments);
471
+ };
472
+ })(this, this.map, native_methods[i]);
473
+ }
474
+ };
475
+
476
+ return GMaps;
477
+ })(this);
478
+
479
+ GMaps.prototype.createControl = function(options) {
480
+ var control = document.createElement('div');
481
+
482
+ control.style.cursor = 'pointer';
483
+
484
+ if (options.disableDefaultStyles !== true) {
485
+ control.style.fontFamily = 'Roboto, Arial, sans-serif';
486
+ control.style.fontSize = '11px';
487
+ control.style.boxShadow = 'rgba(0, 0, 0, 0.298039) 0px 1px 4px -1px';
488
+ }
489
+
490
+ for (var option in options.style) {
491
+ control.style[option] = options.style[option];
492
+ }
493
+
494
+ if (options.id) {
495
+ control.id = options.id;
496
+ }
497
+
498
+ if (options.classes) {
499
+ control.className = options.classes;
500
+ }
501
+
502
+ if (options.content) {
503
+ control.innerHTML = options.content;
504
+ }
505
+
506
+ if (options.position) {
507
+ control.position = google.maps.ControlPosition[options.position.toUpperCase()];
508
+ }
509
+
510
+ for (var ev in options.events) {
511
+ (function(object, name) {
512
+ google.maps.event.addDomListener(object, name, function(){
513
+ options.events[name].apply(this, [this]);
514
+ });
515
+ })(control, ev);
516
+ }
517
+
518
+ control.index = 1;
519
+
520
+ return control;
521
+ };
522
+
523
+ GMaps.prototype.addControl = function(options) {
524
+ var control = this.createControl(options);
525
+ this.controls.push(control);
526
+ this.map.controls[control.position].push(control);
527
+
528
+ return control;
529
+ };
530
+
531
+ GMaps.prototype.removeControl = function(control) {
532
+ var position = null;
533
+
534
+ for (var i = 0; i < this.controls.length; i++) {
535
+ if (this.controls[i] == control) {
536
+ position = this.controls[i].position;
537
+ this.controls.splice(i, 1);
538
+ }
539
+ }
540
+
541
+ if (position) {
542
+ for (i = 0; i < this.map.controls.length; i++) {
543
+ var controlsForPosition = this.map.controls[control.position]
544
+ if (controlsForPosition.getAt(i) == control) {
545
+ controlsForPosition.removeAt(i);
546
+ break;
547
+ }
548
+ }
549
+ }
550
+
551
+ return control;
552
+ };
553
+
554
+ GMaps.prototype.createMarker = function(options) {
555
+ if (options.lat == undefined && options.lng == undefined && options.position == undefined) {
556
+ throw 'No latitude or longitude defined.';
557
+ }
558
+
559
+ var self = this,
560
+ details = options.details,
561
+ fences = options.fences,
562
+ outside = options.outside,
563
+ base_options = {
564
+ position: new google.maps.LatLng(options.lat, options.lng),
565
+ map: null
566
+ },
567
+ marker_options = extend_object(base_options, options);
568
+
569
+ delete marker_options.lat;
570
+ delete marker_options.lng;
571
+ delete marker_options.fences;
572
+ delete marker_options.outside;
573
+
574
+ var marker = new google.maps.Marker(marker_options);
575
+
576
+ marker.fences = fences;
577
+
578
+ if (options.infoWindow) {
579
+ marker.infoWindow = new google.maps.InfoWindow(options.infoWindow);
580
+
581
+ var info_window_events = ['closeclick', 'content_changed', 'domready', 'position_changed', 'zindex_changed'];
582
+
583
+ for (var ev = 0; ev < info_window_events.length; ev++) {
584
+ (function(object, name) {
585
+ if (options.infoWindow[name]) {
586
+ google.maps.event.addListener(object, name, function(e){
587
+ options.infoWindow[name].apply(this, [e]);
588
+ });
589
+ }
590
+ })(marker.infoWindow, info_window_events[ev]);
591
+ }
592
+ }
593
+
594
+ var marker_events = ['animation_changed', 'clickable_changed', 'cursor_changed', 'draggable_changed', 'flat_changed', 'icon_changed', 'position_changed', 'shadow_changed', 'shape_changed', 'title_changed', 'visible_changed', 'zindex_changed'];
595
+
596
+ var marker_events_with_mouse = ['dblclick', 'drag', 'dragend', 'dragstart', 'mousedown', 'mouseout', 'mouseover', 'mouseup'];
597
+
598
+ for (var ev = 0; ev < marker_events.length; ev++) {
599
+ (function(object, name) {
600
+ if (options[name]) {
601
+ google.maps.event.addListener(object, name, function(){
602
+ options[name].apply(this, [this]);
603
+ });
604
+ }
605
+ })(marker, marker_events[ev]);
606
+ }
607
+
608
+ for (var ev = 0; ev < marker_events_with_mouse.length; ev++) {
609
+ (function(map, object, name) {
610
+ if (options[name]) {
611
+ google.maps.event.addListener(object, name, function(me){
612
+ if(!me.pixel){
613
+ me.pixel = map.getProjection().fromLatLngToPoint(me.latLng)
614
+ }
615
+
616
+ options[name].apply(this, [me]);
617
+ });
618
+ }
619
+ })(this.map, marker, marker_events_with_mouse[ev]);
620
+ }
621
+
622
+ google.maps.event.addListener(marker, 'click', function() {
623
+ this.details = details;
624
+
625
+ if (options.click) {
626
+ options.click.apply(this, [this]);
627
+ }
628
+
629
+ if (marker.infoWindow) {
630
+ self.hideInfoWindows();
631
+ marker.infoWindow.open(self.map, marker);
632
+ }
633
+ });
634
+
635
+ google.maps.event.addListener(marker, 'rightclick', function(e) {
636
+ e.marker = this;
637
+
638
+ if (options.rightclick) {
639
+ options.rightclick.apply(this, [e]);
640
+ }
641
+
642
+ if (window.context_menu[self.el.id]['marker'] != undefined) {
643
+ self.buildContextMenu('marker', e);
644
+ }
645
+ });
646
+
647
+ if (marker.fences) {
648
+ google.maps.event.addListener(marker, 'dragend', function() {
649
+ self.checkMarkerGeofence(marker, function(m, f) {
650
+ outside(m, f);
651
+ });
652
+ });
653
+ }
654
+
655
+ return marker;
656
+ };
657
+
658
+ GMaps.prototype.addMarker = function(options) {
659
+ var marker;
660
+ if(options.hasOwnProperty('gm_accessors_')) {
661
+ // Native google.maps.Marker object
662
+ marker = options;
663
+ }
664
+ else {
665
+ if ((options.hasOwnProperty('lat') && options.hasOwnProperty('lng')) || options.position) {
666
+ marker = this.createMarker(options);
667
+ }
668
+ else {
669
+ throw 'No latitude or longitude defined.';
670
+ }
671
+ }
672
+
673
+ marker.setMap(this.map);
674
+
675
+ if(this.markerClusterer) {
676
+ this.markerClusterer.addMarker(marker);
677
+ }
678
+
679
+ this.markers.push(marker);
680
+
681
+ GMaps.fire('marker_added', marker, this);
682
+
683
+ return marker;
684
+ };
685
+
686
+ GMaps.prototype.addMarkers = function(array) {
687
+ for (var i = 0, marker; marker=array[i]; i++) {
688
+ this.addMarker(marker);
689
+ }
690
+
691
+ return this.markers;
692
+ };
693
+
694
+ GMaps.prototype.hideInfoWindows = function() {
695
+ for (var i = 0, marker; marker = this.markers[i]; i++){
696
+ if (marker.infoWindow) {
697
+ marker.infoWindow.close();
698
+ }
699
+ }
700
+ };
701
+
702
+ GMaps.prototype.removeMarker = function(marker) {
703
+ for (var i = 0; i < this.markers.length; i++) {
704
+ if (this.markers[i] === marker) {
705
+ this.markers[i].setMap(null);
706
+ this.markers.splice(i, 1);
707
+
708
+ if(this.markerClusterer) {
709
+ this.markerClusterer.removeMarker(marker);
710
+ }
711
+
712
+ GMaps.fire('marker_removed', marker, this);
713
+
714
+ break;
715
+ }
716
+ }
717
+
718
+ return marker;
719
+ };
720
+
721
+ GMaps.prototype.removeMarkers = function (collection) {
722
+ var new_markers = [];
723
+
724
+ if (typeof collection == 'undefined') {
725
+ for (var i = 0; i < this.markers.length; i++) {
726
+ this.markers[i].setMap(null);
727
+ }
728
+
729
+ this.markers = new_markers;
730
+ }
731
+ else {
732
+ for (var i = 0; i < collection.length; i++) {
733
+ if (this.markers.indexOf(collection[i]) > -1) {
734
+ this.markers[i].setMap(null);
735
+ }
736
+ }
737
+
738
+ for (var i = 0; i < this.markers.length; i++) {
739
+ if (this.markers[i].getMap() != null) {
740
+ new_markers.push(this.markers[i]);
741
+ }
742
+ }
743
+
744
+ this.markers = new_markers;
745
+ }
746
+ };
747
+
748
+ GMaps.prototype.drawOverlay = function(options) {
749
+ var overlay = new google.maps.OverlayView(),
750
+ auto_show = true;
751
+
752
+ overlay.setMap(this.map);
753
+
754
+ if (options.auto_show != null) {
755
+ auto_show = options.auto_show;
756
+ }
757
+
758
+ overlay.onAdd = function() {
759
+ var el = document.createElement('div');
760
+
761
+ el.style.borderStyle = "none";
762
+ el.style.borderWidth = "0px";
763
+ el.style.position = "absolute";
764
+ el.style.zIndex = 100;
765
+ el.innerHTML = options.content;
766
+
767
+ overlay.el = el;
768
+
769
+ if (!options.layer) {
770
+ options.layer = 'overlayLayer';
771
+ }
772
+
773
+ var panes = this.getPanes(),
774
+ overlayLayer = panes[options.layer],
775
+ stop_overlay_events = ['contextmenu', 'DOMMouseScroll', 'dblclick', 'mousedown'];
776
+
777
+ overlayLayer.appendChild(el);
778
+
779
+ for (var ev = 0; ev < stop_overlay_events.length; ev++) {
780
+ (function(object, name) {
781
+ google.maps.event.addDomListener(object, name, function(e){
782
+ if (navigator.userAgent.toLowerCase().indexOf('msie') != -1 && document.all) {
783
+ e.cancelBubble = true;
784
+ e.returnValue = false;
785
+ }
786
+ else {
787
+ e.stopPropagation();
788
+ }
789
+ });
790
+ })(el, stop_overlay_events[ev]);
791
+ }
792
+
793
+ if (options.click) {
794
+ google.maps.event.addDomListener(overlay.el, 'click', function() {
795
+ options.click.apply(overlay, [overlay]);
796
+ });
797
+ }
798
+
799
+ google.maps.event.trigger(this, 'ready');
800
+ };
801
+
802
+ overlay.draw = function() {
803
+ var projection = this.getProjection(),
804
+ pixel = projection.fromLatLngToDivPixel(new google.maps.LatLng(options.lat, options.lng));
805
+
806
+ options.horizontalOffset = options.horizontalOffset || 0;
807
+ options.verticalOffset = options.verticalOffset || 0;
808
+
809
+ var el = overlay.el,
810
+ content = el.children[0],
811
+ content_height = content.clientHeight,
812
+ content_width = content.clientWidth;
813
+
814
+ switch (options.verticalAlign) {
815
+ case 'top':
816
+ el.style.top = (pixel.y - content_height + options.verticalOffset) + 'px';
817
+ break;
818
+ default:
819
+ case 'middle':
820
+ el.style.top = (pixel.y - (content_height / 2) + options.verticalOffset) + 'px';
821
+ break;
822
+ case 'bottom':
823
+ el.style.top = (pixel.y + options.verticalOffset) + 'px';
824
+ break;
825
+ }
826
+
827
+ switch (options.horizontalAlign) {
828
+ case 'left':
829
+ el.style.left = (pixel.x - content_width + options.horizontalOffset) + 'px';
830
+ break;
831
+ default:
832
+ case 'center':
833
+ el.style.left = (pixel.x - (content_width / 2) + options.horizontalOffset) + 'px';
834
+ break;
835
+ case 'right':
836
+ el.style.left = (pixel.x + options.horizontalOffset) + 'px';
837
+ break;
838
+ }
839
+
840
+ el.style.display = auto_show ? 'block' : 'none';
841
+
842
+ if (!auto_show) {
843
+ options.show.apply(this, [el]);
844
+ }
845
+ };
846
+
847
+ overlay.onRemove = function() {
848
+ var el = overlay.el;
849
+
850
+ if (options.remove) {
851
+ options.remove.apply(this, [el]);
852
+ }
853
+ else {
854
+ overlay.el.parentNode.removeChild(overlay.el);
855
+ overlay.el = null;
856
+ }
857
+ };
858
+
859
+ this.overlays.push(overlay);
860
+ return overlay;
861
+ };
862
+
863
+ GMaps.prototype.removeOverlay = function(overlay) {
864
+ for (var i = 0; i < this.overlays.length; i++) {
865
+ if (this.overlays[i] === overlay) {
866
+ this.overlays[i].setMap(null);
867
+ this.overlays.splice(i, 1);
868
+
869
+ break;
870
+ }
871
+ }
872
+ };
873
+
874
+ GMaps.prototype.removeOverlays = function() {
875
+ for (var i = 0, item; item = this.overlays[i]; i++) {
876
+ item.setMap(null);
877
+ }
878
+
879
+ this.overlays = [];
880
+ };
881
+
882
+ GMaps.prototype.drawPolyline = function(options) {
883
+ var path = [],
884
+ points = options.path;
885
+
886
+ if (points.length) {
887
+ if (points[0][0] === undefined) {
888
+ path = points;
889
+ }
890
+ else {
891
+ for (var i=0, latlng; latlng=points[i]; i++) {
892
+ path.push(new google.maps.LatLng(latlng[0], latlng[1]));
893
+ }
894
+ }
895
+ }
896
+
897
+ var polyline_options = {
898
+ map: this.map,
899
+ path: path,
900
+ strokeColor: options.strokeColor,
901
+ strokeOpacity: options.strokeOpacity,
902
+ strokeWeight: options.strokeWeight,
903
+ geodesic: options.geodesic,
904
+ clickable: true,
905
+ editable: false,
906
+ visible: true
907
+ };
908
+
909
+ if (options.hasOwnProperty("clickable")) {
910
+ polyline_options.clickable = options.clickable;
911
+ }
912
+
913
+ if (options.hasOwnProperty("editable")) {
914
+ polyline_options.editable = options.editable;
915
+ }
916
+
917
+ if (options.hasOwnProperty("icons")) {
918
+ polyline_options.icons = options.icons;
919
+ }
920
+
921
+ if (options.hasOwnProperty("zIndex")) {
922
+ polyline_options.zIndex = options.zIndex;
923
+ }
924
+
925
+ var polyline = new google.maps.Polyline(polyline_options);
926
+
927
+ var polyline_events = ['click', 'dblclick', 'mousedown', 'mousemove', 'mouseout', 'mouseover', 'mouseup', 'rightclick'];
928
+
929
+ for (var ev = 0; ev < polyline_events.length; ev++) {
930
+ (function(object, name) {
931
+ if (options[name]) {
932
+ google.maps.event.addListener(object, name, function(e){
933
+ options[name].apply(this, [e]);
934
+ });
935
+ }
936
+ })(polyline, polyline_events[ev]);
937
+ }
938
+
939
+ this.polylines.push(polyline);
940
+
941
+ GMaps.fire('polyline_added', polyline, this);
942
+
943
+ return polyline;
944
+ };
945
+
946
+ GMaps.prototype.removePolyline = function(polyline) {
947
+ for (var i = 0; i < this.polylines.length; i++) {
948
+ if (this.polylines[i] === polyline) {
949
+ this.polylines[i].setMap(null);
950
+ this.polylines.splice(i, 1);
951
+
952
+ GMaps.fire('polyline_removed', polyline, this);
953
+
954
+ break;
955
+ }
956
+ }
957
+ };
958
+
959
+ GMaps.prototype.removePolylines = function() {
960
+ for (var i = 0, item; item = this.polylines[i]; i++) {
961
+ item.setMap(null);
962
+ }
963
+
964
+ this.polylines = [];
965
+ };
966
+
967
+ GMaps.prototype.drawCircle = function(options) {
968
+ options = extend_object({
969
+ map: this.map,
970
+ center: new google.maps.LatLng(options.lat, options.lng)
971
+ }, options);
972
+
973
+ delete options.lat;
974
+ delete options.lng;
975
+
976
+ var polygon = new google.maps.Circle(options),
977
+ polygon_events = ['click', 'dblclick', 'mousedown', 'mousemove', 'mouseout', 'mouseover', 'mouseup', 'rightclick'];
978
+
979
+ for (var ev = 0; ev < polygon_events.length; ev++) {
980
+ (function(object, name) {
981
+ if (options[name]) {
982
+ google.maps.event.addListener(object, name, function(e){
983
+ options[name].apply(this, [e]);
984
+ });
985
+ }
986
+ })(polygon, polygon_events[ev]);
987
+ }
988
+
989
+ this.polygons.push(polygon);
990
+
991
+ return polygon;
992
+ };
993
+
994
+ GMaps.prototype.drawRectangle = function(options) {
995
+ options = extend_object({
996
+ map: this.map
997
+ }, options);
998
+
999
+ var latLngBounds = new google.maps.LatLngBounds(
1000
+ new google.maps.LatLng(options.bounds[0][0], options.bounds[0][1]),
1001
+ new google.maps.LatLng(options.bounds[1][0], options.bounds[1][1])
1002
+ );
1003
+
1004
+ options.bounds = latLngBounds;
1005
+
1006
+ var polygon = new google.maps.Rectangle(options),
1007
+ polygon_events = ['click', 'dblclick', 'mousedown', 'mousemove', 'mouseout', 'mouseover', 'mouseup', 'rightclick'];
1008
+
1009
+ for (var ev = 0; ev < polygon_events.length; ev++) {
1010
+ (function(object, name) {
1011
+ if (options[name]) {
1012
+ google.maps.event.addListener(object, name, function(e){
1013
+ options[name].apply(this, [e]);
1014
+ });
1015
+ }
1016
+ })(polygon, polygon_events[ev]);
1017
+ }
1018
+
1019
+ this.polygons.push(polygon);
1020
+
1021
+ return polygon;
1022
+ };
1023
+
1024
+ GMaps.prototype.drawPolygon = function(options) {
1025
+ var useGeoJSON = false;
1026
+
1027
+ if(options.hasOwnProperty("useGeoJSON")) {
1028
+ useGeoJSON = options.useGeoJSON;
1029
+ }
1030
+
1031
+ delete options.useGeoJSON;
1032
+
1033
+ options = extend_object({
1034
+ map: this.map
1035
+ }, options);
1036
+
1037
+ if (useGeoJSON == false) {
1038
+ options.paths = [options.paths.slice(0)];
1039
+ }
1040
+
1041
+ if (options.paths.length > 0) {
1042
+ if (options.paths[0].length > 0) {
1043
+ options.paths = array_flat(array_map(options.paths, arrayToLatLng, useGeoJSON));
1044
+ }
1045
+ }
1046
+
1047
+ var polygon = new google.maps.Polygon(options),
1048
+ polygon_events = ['click', 'dblclick', 'mousedown', 'mousemove', 'mouseout', 'mouseover', 'mouseup', 'rightclick'];
1049
+
1050
+ for (var ev = 0; ev < polygon_events.length; ev++) {
1051
+ (function(object, name) {
1052
+ if (options[name]) {
1053
+ google.maps.event.addListener(object, name, function(e){
1054
+ options[name].apply(this, [e]);
1055
+ });
1056
+ }
1057
+ })(polygon, polygon_events[ev]);
1058
+ }
1059
+
1060
+ this.polygons.push(polygon);
1061
+
1062
+ GMaps.fire('polygon_added', polygon, this);
1063
+
1064
+ return polygon;
1065
+ };
1066
+
1067
+ GMaps.prototype.removePolygon = function(polygon) {
1068
+ for (var i = 0; i < this.polygons.length; i++) {
1069
+ if (this.polygons[i] === polygon) {
1070
+ this.polygons[i].setMap(null);
1071
+ this.polygons.splice(i, 1);
1072
+
1073
+ GMaps.fire('polygon_removed', polygon, this);
1074
+
1075
+ break;
1076
+ }
1077
+ }
1078
+ };
1079
+
1080
+ GMaps.prototype.removePolygons = function() {
1081
+ for (var i = 0, item; item = this.polygons[i]; i++) {
1082
+ item.setMap(null);
1083
+ }
1084
+
1085
+ this.polygons = [];
1086
+ };
1087
+
1088
+ GMaps.prototype.getFromFusionTables = function(options) {
1089
+ var events = options.events;
1090
+
1091
+ delete options.events;
1092
+
1093
+ var fusion_tables_options = options,
1094
+ layer = new google.maps.FusionTablesLayer(fusion_tables_options);
1095
+
1096
+ for (var ev in events) {
1097
+ (function(object, name) {
1098
+ google.maps.event.addListener(object, name, function(e) {
1099
+ events[name].apply(this, [e]);
1100
+ });
1101
+ })(layer, ev);
1102
+ }
1103
+
1104
+ this.layers.push(layer);
1105
+
1106
+ return layer;
1107
+ };
1108
+
1109
+ GMaps.prototype.loadFromFusionTables = function(options) {
1110
+ var layer = this.getFromFusionTables(options);
1111
+ layer.setMap(this.map);
1112
+
1113
+ return layer;
1114
+ };
1115
+
1116
+ GMaps.prototype.getFromKML = function(options) {
1117
+ var url = options.url,
1118
+ events = options.events;
1119
+
1120
+ delete options.url;
1121
+ delete options.events;
1122
+
1123
+ var kml_options = options,
1124
+ layer = new google.maps.KmlLayer(url, kml_options);
1125
+
1126
+ for (var ev in events) {
1127
+ (function(object, name) {
1128
+ google.maps.event.addListener(object, name, function(e) {
1129
+ events[name].apply(this, [e]);
1130
+ });
1131
+ })(layer, ev);
1132
+ }
1133
+
1134
+ this.layers.push(layer);
1135
+
1136
+ return layer;
1137
+ };
1138
+
1139
+ GMaps.prototype.loadFromKML = function(options) {
1140
+ var layer = this.getFromKML(options);
1141
+ layer.setMap(this.map);
1142
+
1143
+ return layer;
1144
+ };
1145
+
1146
+ GMaps.prototype.addLayer = function(layerName, options) {
1147
+ //var default_layers = ['weather', 'clouds', 'traffic', 'transit', 'bicycling', 'panoramio', 'places'];
1148
+ options = options || {};
1149
+ var layer;
1150
+
1151
+ switch(layerName) {
1152
+ case 'weather': this.singleLayers.weather = layer = new google.maps.weather.WeatherLayer();
1153
+ break;
1154
+ case 'clouds': this.singleLayers.clouds = layer = new google.maps.weather.CloudLayer();
1155
+ break;
1156
+ case 'traffic': this.singleLayers.traffic = layer = new google.maps.TrafficLayer();
1157
+ break;
1158
+ case 'transit': this.singleLayers.transit = layer = new google.maps.TransitLayer();
1159
+ break;
1160
+ case 'bicycling': this.singleLayers.bicycling = layer = new google.maps.BicyclingLayer();
1161
+ break;
1162
+ case 'panoramio':
1163
+ this.singleLayers.panoramio = layer = new google.maps.panoramio.PanoramioLayer();
1164
+ layer.setTag(options.filter);
1165
+ delete options.filter;
1166
+
1167
+ //click event
1168
+ if (options.click) {
1169
+ google.maps.event.addListener(layer, 'click', function(event) {
1170
+ options.click(event);
1171
+ delete options.click;
1172
+ });
1173
+ }
1174
+ break;
1175
+ case 'places':
1176
+ this.singleLayers.places = layer = new google.maps.places.PlacesService(this.map);
1177
+
1178
+ //search, nearbySearch, radarSearch callback, Both are the same
1179
+ if (options.search || options.nearbySearch || options.radarSearch) {
1180
+ var placeSearchRequest = {
1181
+ bounds : options.bounds || null,
1182
+ keyword : options.keyword || null,
1183
+ location : options.location || null,
1184
+ name : options.name || null,
1185
+ radius : options.radius || null,
1186
+ rankBy : options.rankBy || null,
1187
+ types : options.types || null
1188
+ };
1189
+
1190
+ if (options.radarSearch) {
1191
+ layer.radarSearch(placeSearchRequest, options.radarSearch);
1192
+ }
1193
+
1194
+ if (options.search) {
1195
+ layer.search(placeSearchRequest, options.search);
1196
+ }
1197
+
1198
+ if (options.nearbySearch) {
1199
+ layer.nearbySearch(placeSearchRequest, options.nearbySearch);
1200
+ }
1201
+ }
1202
+
1203
+ //textSearch callback
1204
+ if (options.textSearch) {
1205
+ var textSearchRequest = {
1206
+ bounds : options.bounds || null,
1207
+ location : options.location || null,
1208
+ query : options.query || null,
1209
+ radius : options.radius || null
1210
+ };
1211
+
1212
+ layer.textSearch(textSearchRequest, options.textSearch);
1213
+ }
1214
+ break;
1215
+ }
1216
+
1217
+ if (layer !== undefined) {
1218
+ if (typeof layer.setOptions == 'function') {
1219
+ layer.setOptions(options);
1220
+ }
1221
+ if (typeof layer.setMap == 'function') {
1222
+ layer.setMap(this.map);
1223
+ }
1224
+
1225
+ return layer;
1226
+ }
1227
+ };
1228
+
1229
+ GMaps.prototype.removeLayer = function(layer) {
1230
+ if (typeof(layer) == "string" && this.singleLayers[layer] !== undefined) {
1231
+ this.singleLayers[layer].setMap(null);
1232
+
1233
+ delete this.singleLayers[layer];
1234
+ }
1235
+ else {
1236
+ for (var i = 0; i < this.layers.length; i++) {
1237
+ if (this.layers[i] === layer) {
1238
+ this.layers[i].setMap(null);
1239
+ this.layers.splice(i, 1);
1240
+
1241
+ break;
1242
+ }
1243
+ }
1244
+ }
1245
+ };
1246
+
1247
+ var travelMode, unitSystem;
1248
+
1249
+ GMaps.prototype.getRoutes = function(options) {
1250
+ switch (options.travelMode) {
1251
+ case 'bicycling':
1252
+ travelMode = google.maps.TravelMode.BICYCLING;
1253
+ break;
1254
+ case 'transit':
1255
+ travelMode = google.maps.TravelMode.TRANSIT;
1256
+ break;
1257
+ case 'driving':
1258
+ travelMode = google.maps.TravelMode.DRIVING;
1259
+ break;
1260
+ default:
1261
+ travelMode = google.maps.TravelMode.WALKING;
1262
+ break;
1263
+ }
1264
+
1265
+ if (options.unitSystem === 'imperial') {
1266
+ unitSystem = google.maps.UnitSystem.IMPERIAL;
1267
+ }
1268
+ else {
1269
+ unitSystem = google.maps.UnitSystem.METRIC;
1270
+ }
1271
+
1272
+ var base_options = {
1273
+ avoidHighways: false,
1274
+ avoidTolls: false,
1275
+ optimizeWaypoints: false,
1276
+ waypoints: []
1277
+ },
1278
+ request_options = extend_object(base_options, options);
1279
+
1280
+ request_options.origin = /string/.test(typeof options.origin) ? options.origin : new google.maps.LatLng(options.origin[0], options.origin[1]);
1281
+ request_options.destination = /string/.test(typeof options.destination) ? options.destination : new google.maps.LatLng(options.destination[0], options.destination[1]);
1282
+ request_options.travelMode = travelMode;
1283
+ request_options.unitSystem = unitSystem;
1284
+
1285
+ delete request_options.callback;
1286
+ delete request_options.error;
1287
+
1288
+ var self = this,
1289
+ service = new google.maps.DirectionsService();
1290
+
1291
+ service.route(request_options, function(result, status) {
1292
+ if (status === google.maps.DirectionsStatus.OK) {
1293
+ for (var r in result.routes) {
1294
+ if (result.routes.hasOwnProperty(r)) {
1295
+ self.routes.push(result.routes[r]);
1296
+ }
1297
+ }
1298
+
1299
+ if (options.callback) {
1300
+ options.callback(self.routes);
1301
+ }
1302
+ }
1303
+ else {
1304
+ if (options.error) {
1305
+ options.error(result, status);
1306
+ }
1307
+ }
1308
+ });
1309
+ };
1310
+
1311
+ GMaps.prototype.removeRoutes = function() {
1312
+ this.routes = [];
1313
+ };
1314
+
1315
+ GMaps.prototype.getElevations = function(options) {
1316
+ options = extend_object({
1317
+ locations: [],
1318
+ path : false,
1319
+ samples : 256
1320
+ }, options);
1321
+
1322
+ if (options.locations.length > 0) {
1323
+ if (options.locations[0].length > 0) {
1324
+ options.locations = array_flat(array_map([options.locations], arrayToLatLng, false));
1325
+ }
1326
+ }
1327
+
1328
+ var callback = options.callback;
1329
+ delete options.callback;
1330
+
1331
+ var service = new google.maps.ElevationService();
1332
+
1333
+ //location request
1334
+ if (!options.path) {
1335
+ delete options.path;
1336
+ delete options.samples;
1337
+
1338
+ service.getElevationForLocations(options, function(result, status) {
1339
+ if (callback && typeof(callback) === "function") {
1340
+ callback(result, status);
1341
+ }
1342
+ });
1343
+ //path request
1344
+ } else {
1345
+ var pathRequest = {
1346
+ path : options.locations,
1347
+ samples : options.samples
1348
+ };
1349
+
1350
+ service.getElevationAlongPath(pathRequest, function(result, status) {
1351
+ if (callback && typeof(callback) === "function") {
1352
+ callback(result, status);
1353
+ }
1354
+ });
1355
+ }
1356
+ };
1357
+
1358
+ GMaps.prototype.cleanRoute = GMaps.prototype.removePolylines;
1359
+
1360
+ GMaps.prototype.drawRoute = function(options) {
1361
+ var self = this;
1362
+
1363
+ this.getRoutes({
1364
+ origin: options.origin,
1365
+ destination: options.destination,
1366
+ travelMode: options.travelMode,
1367
+ waypoints: options.waypoints,
1368
+ unitSystem: options.unitSystem,
1369
+ error: options.error,
1370
+ callback: function(e) {
1371
+ if (e.length > 0) {
1372
+ self.drawPolyline({
1373
+ path: e[e.length - 1].overview_path,
1374
+ strokeColor: options.strokeColor,
1375
+ strokeOpacity: options.strokeOpacity,
1376
+ strokeWeight: options.strokeWeight
1377
+ });
1378
+
1379
+ if (options.callback) {
1380
+ options.callback(e[e.length - 1]);
1381
+ }
1382
+ }
1383
+ }
1384
+ });
1385
+ };
1386
+
1387
+ GMaps.prototype.travelRoute = function(options) {
1388
+ if (options.origin && options.destination) {
1389
+ this.getRoutes({
1390
+ origin: options.origin,
1391
+ destination: options.destination,
1392
+ travelMode: options.travelMode,
1393
+ waypoints : options.waypoints,
1394
+ unitSystem: options.unitSystem,
1395
+ error: options.error,
1396
+ callback: function(e) {
1397
+ //start callback
1398
+ if (e.length > 0 && options.start) {
1399
+ options.start(e[e.length - 1]);
1400
+ }
1401
+
1402
+ //step callback
1403
+ if (e.length > 0 && options.step) {
1404
+ var route = e[e.length - 1];
1405
+ if (route.legs.length > 0) {
1406
+ var steps = route.legs[0].steps;
1407
+ for (var i=0, step; step=steps[i]; i++) {
1408
+ step.step_number = i;
1409
+ options.step(step, (route.legs[0].steps.length - 1));
1410
+ }
1411
+ }
1412
+ }
1413
+
1414
+ //end callback
1415
+ if (e.length > 0 && options.end) {
1416
+ options.end(e[e.length - 1]);
1417
+ }
1418
+ }
1419
+ });
1420
+ }
1421
+ else if (options.route) {
1422
+ if (options.route.legs.length > 0) {
1423
+ var steps = options.route.legs[0].steps;
1424
+ for (var i=0, step; step=steps[i]; i++) {
1425
+ step.step_number = i;
1426
+ options.step(step);
1427
+ }
1428
+ }
1429
+ }
1430
+ };
1431
+
1432
+ GMaps.prototype.drawSteppedRoute = function(options) {
1433
+ var self = this;
1434
+
1435
+ if (options.origin && options.destination) {
1436
+ this.getRoutes({
1437
+ origin: options.origin,
1438
+ destination: options.destination,
1439
+ travelMode: options.travelMode,
1440
+ waypoints : options.waypoints,
1441
+ error: options.error,
1442
+ callback: function(e) {
1443
+ //start callback
1444
+ if (e.length > 0 && options.start) {
1445
+ options.start(e[e.length - 1]);
1446
+ }
1447
+
1448
+ //step callback
1449
+ if (e.length > 0 && options.step) {
1450
+ var route = e[e.length - 1];
1451
+ if (route.legs.length > 0) {
1452
+ var steps = route.legs[0].steps;
1453
+ for (var i=0, step; step=steps[i]; i++) {
1454
+ step.step_number = i;
1455
+ self.drawPolyline({
1456
+ path: step.path,
1457
+ strokeColor: options.strokeColor,
1458
+ strokeOpacity: options.strokeOpacity,
1459
+ strokeWeight: options.strokeWeight
1460
+ });
1461
+ options.step(step, (route.legs[0].steps.length - 1));
1462
+ }
1463
+ }
1464
+ }
1465
+
1466
+ //end callback
1467
+ if (e.length > 0 && options.end) {
1468
+ options.end(e[e.length - 1]);
1469
+ }
1470
+ }
1471
+ });
1472
+ }
1473
+ else if (options.route) {
1474
+ if (options.route.legs.length > 0) {
1475
+ var steps = options.route.legs[0].steps;
1476
+ for (var i=0, step; step=steps[i]; i++) {
1477
+ step.step_number = i;
1478
+ self.drawPolyline({
1479
+ path: step.path,
1480
+ strokeColor: options.strokeColor,
1481
+ strokeOpacity: options.strokeOpacity,
1482
+ strokeWeight: options.strokeWeight
1483
+ });
1484
+ options.step(step);
1485
+ }
1486
+ }
1487
+ }
1488
+ };
1489
+
1490
+ GMaps.Route = function(options) {
1491
+ this.origin = options.origin;
1492
+ this.destination = options.destination;
1493
+ this.waypoints = options.waypoints;
1494
+
1495
+ this.map = options.map;
1496
+ this.route = options.route;
1497
+ this.step_count = 0;
1498
+ this.steps = this.route.legs[0].steps;
1499
+ this.steps_length = this.steps.length;
1500
+
1501
+ this.polyline = this.map.drawPolyline({
1502
+ path: new google.maps.MVCArray(),
1503
+ strokeColor: options.strokeColor,
1504
+ strokeOpacity: options.strokeOpacity,
1505
+ strokeWeight: options.strokeWeight
1506
+ }).getPath();
1507
+ };
1508
+
1509
+ GMaps.Route.prototype.getRoute = function(options) {
1510
+ var self = this;
1511
+
1512
+ this.map.getRoutes({
1513
+ origin : this.origin,
1514
+ destination : this.destination,
1515
+ travelMode : options.travelMode,
1516
+ waypoints : this.waypoints || [],
1517
+ error: options.error,
1518
+ callback : function() {
1519
+ self.route = e[0];
1520
+
1521
+ if (options.callback) {
1522
+ options.callback.call(self);
1523
+ }
1524
+ }
1525
+ });
1526
+ };
1527
+
1528
+ GMaps.Route.prototype.back = function() {
1529
+ if (this.step_count > 0) {
1530
+ this.step_count--;
1531
+ var path = this.route.legs[0].steps[this.step_count].path;
1532
+
1533
+ for (var p in path){
1534
+ if (path.hasOwnProperty(p)){
1535
+ this.polyline.pop();
1536
+ }
1537
+ }
1538
+ }
1539
+ };
1540
+
1541
+ GMaps.Route.prototype.forward = function() {
1542
+ if (this.step_count < this.steps_length) {
1543
+ var path = this.route.legs[0].steps[this.step_count].path;
1544
+
1545
+ for (var p in path){
1546
+ if (path.hasOwnProperty(p)){
1547
+ this.polyline.push(path[p]);
1548
+ }
1549
+ }
1550
+ this.step_count++;
1551
+ }
1552
+ };
1553
+
1554
+ GMaps.prototype.checkGeofence = function(lat, lng, fence) {
1555
+ return fence.containsLatLng(new google.maps.LatLng(lat, lng));
1556
+ };
1557
+
1558
+ GMaps.prototype.checkMarkerGeofence = function(marker, outside_callback) {
1559
+ if (marker.fences) {
1560
+ for (var i = 0, fence; fence = marker.fences[i]; i++) {
1561
+ var pos = marker.getPosition();
1562
+ if (!this.checkGeofence(pos.lat(), pos.lng(), fence)) {
1563
+ outside_callback(marker, fence);
1564
+ }
1565
+ }
1566
+ }
1567
+ };
1568
+
1569
+ GMaps.prototype.toImage = function(options) {
1570
+ var options = options || {},
1571
+ static_map_options = {};
1572
+
1573
+ static_map_options['size'] = options['size'] || [this.el.clientWidth, this.el.clientHeight];
1574
+ static_map_options['lat'] = this.getCenter().lat();
1575
+ static_map_options['lng'] = this.getCenter().lng();
1576
+
1577
+ if (this.markers.length > 0) {
1578
+ static_map_options['markers'] = [];
1579
+
1580
+ for (var i = 0; i < this.markers.length; i++) {
1581
+ static_map_options['markers'].push({
1582
+ lat: this.markers[i].getPosition().lat(),
1583
+ lng: this.markers[i].getPosition().lng()
1584
+ });
1585
+ }
1586
+ }
1587
+
1588
+ if (this.polylines.length > 0) {
1589
+ var polyline = this.polylines[0];
1590
+
1591
+ static_map_options['polyline'] = {};
1592
+ static_map_options['polyline']['path'] = google.maps.geometry.encoding.encodePath(polyline.getPath());
1593
+ static_map_options['polyline']['strokeColor'] = polyline.strokeColor
1594
+ static_map_options['polyline']['strokeOpacity'] = polyline.strokeOpacity
1595
+ static_map_options['polyline']['strokeWeight'] = polyline.strokeWeight
1596
+ }
1597
+
1598
+ return GMaps.staticMapURL(static_map_options);
1599
+ };
1600
+
1601
+ GMaps.staticMapURL = function(options){
1602
+ var parameters = [],
1603
+ data,
1604
+ static_root = 'http://maps.googleapis.com/maps/api/staticmap';
1605
+
1606
+ if (options.url) {
1607
+ static_root = options.url;
1608
+ delete options.url;
1609
+ }
1610
+
1611
+ static_root += '?';
1612
+
1613
+ var markers = options.markers;
1614
+
1615
+ delete options.markers;
1616
+
1617
+ if (!markers && options.marker) {
1618
+ markers = [options.marker];
1619
+ delete options.marker;
1620
+ }
1621
+
1622
+ var styles = options.styles;
1623
+
1624
+ delete options.styles;
1625
+
1626
+ var polyline = options.polyline;
1627
+ delete options.polyline;
1628
+
1629
+ /** Map options **/
1630
+ if (options.center) {
1631
+ parameters.push('center=' + options.center);
1632
+ delete options.center;
1633
+ }
1634
+ else if (options.address) {
1635
+ parameters.push('center=' + options.address);
1636
+ delete options.address;
1637
+ }
1638
+ else if (options.lat) {
1639
+ parameters.push(['center=', options.lat, ',', options.lng].join(''));
1640
+ delete options.lat;
1641
+ delete options.lng;
1642
+ }
1643
+ else if (options.visible) {
1644
+ var visible = encodeURI(options.visible.join('|'));
1645
+ parameters.push('visible=' + visible);
1646
+ }
1647
+
1648
+ var size = options.size;
1649
+ if (size) {
1650
+ if (size.join) {
1651
+ size = size.join('x');
1652
+ }
1653
+ delete options.size;
1654
+ }
1655
+ else {
1656
+ size = '630x300';
1657
+ }
1658
+ parameters.push('size=' + size);
1659
+
1660
+ if (!options.zoom && options.zoom !== false) {
1661
+ options.zoom = 15;
1662
+ }
1663
+
1664
+ var sensor = options.hasOwnProperty('sensor') ? !!options.sensor : true;
1665
+ delete options.sensor;
1666
+ parameters.push('sensor=' + sensor);
1667
+
1668
+ for (var param in options) {
1669
+ if (options.hasOwnProperty(param)) {
1670
+ parameters.push(param + '=' + options[param]);
1671
+ }
1672
+ }
1673
+
1674
+ /** Markers **/
1675
+ if (markers) {
1676
+ var marker, loc;
1677
+
1678
+ for (var i=0; data=markers[i]; i++) {
1679
+ marker = [];
1680
+
1681
+ if (data.size && data.size !== 'normal') {
1682
+ marker.push('size:' + data.size);
1683
+ delete data.size;
1684
+ }
1685
+ else if (data.icon) {
1686
+ marker.push('icon:' + encodeURI(data.icon));
1687
+ delete data.icon;
1688
+ }
1689
+
1690
+ if (data.color) {
1691
+ marker.push('color:' + data.color.replace('#', '0x'));
1692
+ delete data.color;
1693
+ }
1694
+
1695
+ if (data.label) {
1696
+ marker.push('label:' + data.label[0].toUpperCase());
1697
+ delete data.label;
1698
+ }
1699
+
1700
+ loc = (data.address ? data.address : data.lat + ',' + data.lng);
1701
+ delete data.address;
1702
+ delete data.lat;
1703
+ delete data.lng;
1704
+
1705
+ for(var param in data){
1706
+ if (data.hasOwnProperty(param)) {
1707
+ marker.push(param + ':' + data[param]);
1708
+ }
1709
+ }
1710
+
1711
+ if (marker.length || i === 0) {
1712
+ marker.push(loc);
1713
+ marker = marker.join('|');
1714
+ parameters.push('markers=' + encodeURI(marker));
1715
+ }
1716
+ // New marker without styles
1717
+ else {
1718
+ marker = parameters.pop() + encodeURI('|' + loc);
1719
+ parameters.push(marker);
1720
+ }
1721
+ }
1722
+ }
1723
+
1724
+ /** Map Styles **/
1725
+ if (styles) {
1726
+ for (var i = 0; i < styles.length; i++) {
1727
+ var styleRule = [];
1728
+ if (styles[i].featureType){
1729
+ styleRule.push('feature:' + styles[i].featureType.toLowerCase());
1730
+ }
1731
+
1732
+ if (styles[i].elementType) {
1733
+ styleRule.push('element:' + styles[i].elementType.toLowerCase());
1734
+ }
1735
+
1736
+ for (var j = 0; j < styles[i].stylers.length; j++) {
1737
+ for (var p in styles[i].stylers[j]) {
1738
+ var ruleArg = styles[i].stylers[j][p];
1739
+ if (p == 'hue' || p == 'color') {
1740
+ ruleArg = '0x' + ruleArg.substring(1);
1741
+ }
1742
+ styleRule.push(p + ':' + ruleArg);
1743
+ }
1744
+ }
1745
+
1746
+ var rule = styleRule.join('|');
1747
+ if (rule != '') {
1748
+ parameters.push('style=' + rule);
1749
+ }
1750
+ }
1751
+ }
1752
+
1753
+ /** Polylines **/
1754
+ function parseColor(color, opacity) {
1755
+ if (color[0] === '#'){
1756
+ color = color.replace('#', '0x');
1757
+
1758
+ if (opacity) {
1759
+ opacity = parseFloat(opacity);
1760
+ opacity = Math.min(1, Math.max(opacity, 0));
1761
+ if (opacity === 0) {
1762
+ return '0x00000000';
1763
+ }
1764
+ opacity = (opacity * 255).toString(16);
1765
+ if (opacity.length === 1) {
1766
+ opacity += opacity;
1767
+ }
1768
+
1769
+ color = color.slice(0,8) + opacity;
1770
+ }
1771
+ }
1772
+ return color;
1773
+ }
1774
+
1775
+ if (polyline) {
1776
+ data = polyline;
1777
+ polyline = [];
1778
+
1779
+ if (data.strokeWeight) {
1780
+ polyline.push('weight:' + parseInt(data.strokeWeight, 10));
1781
+ }
1782
+
1783
+ if (data.strokeColor) {
1784
+ var color = parseColor(data.strokeColor, data.strokeOpacity);
1785
+ polyline.push('color:' + color);
1786
+ }
1787
+
1788
+ if (data.fillColor) {
1789
+ var fillcolor = parseColor(data.fillColor, data.fillOpacity);
1790
+ polyline.push('fillcolor:' + fillcolor);
1791
+ }
1792
+
1793
+ var path = data.path;
1794
+ if (path.join) {
1795
+ for (var j=0, pos; pos=path[j]; j++) {
1796
+ polyline.push(pos.join(','));
1797
+ }
1798
+ }
1799
+ else {
1800
+ polyline.push('enc:' + path);
1801
+ }
1802
+
1803
+ polyline = polyline.join('|');
1804
+ parameters.push('path=' + encodeURI(polyline));
1805
+ }
1806
+
1807
+ /** Retina support **/
1808
+ var dpi = window.devicePixelRatio || 1;
1809
+ parameters.push('scale=' + dpi);
1810
+
1811
+ parameters = parameters.join('&');
1812
+ return static_root + parameters;
1813
+ };
1814
+
1815
+ GMaps.prototype.addMapType = function(mapTypeId, options) {
1816
+ if (options.hasOwnProperty("getTileUrl") && typeof(options["getTileUrl"]) == "function") {
1817
+ options.tileSize = options.tileSize || new google.maps.Size(256, 256);
1818
+
1819
+ var mapType = new google.maps.ImageMapType(options);
1820
+
1821
+ this.map.mapTypes.set(mapTypeId, mapType);
1822
+ }
1823
+ else {
1824
+ throw "'getTileUrl' function required.";
1825
+ }
1826
+ };
1827
+
1828
+ GMaps.prototype.addOverlayMapType = function(options) {
1829
+ if (options.hasOwnProperty("getTile") && typeof(options["getTile"]) == "function") {
1830
+ var overlayMapTypeIndex = options.index;
1831
+
1832
+ delete options.index;
1833
+
1834
+ this.map.overlayMapTypes.insertAt(overlayMapTypeIndex, options);
1835
+ }
1836
+ else {
1837
+ throw "'getTile' function required.";
1838
+ }
1839
+ };
1840
+
1841
+ GMaps.prototype.removeOverlayMapType = function(overlayMapTypeIndex) {
1842
+ this.map.overlayMapTypes.removeAt(overlayMapTypeIndex);
1843
+ };
1844
+
1845
+ GMaps.prototype.addStyle = function(options) {
1846
+ var styledMapType = new google.maps.StyledMapType(options.styles, { name: options.styledMapName });
1847
+
1848
+ this.map.mapTypes.set(options.mapTypeId, styledMapType);
1849
+ };
1850
+
1851
+ GMaps.prototype.setStyle = function(mapTypeId) {
1852
+ this.map.setMapTypeId(mapTypeId);
1853
+ };
1854
+
1855
+ GMaps.prototype.createPanorama = function(streetview_options) {
1856
+ if (!streetview_options.hasOwnProperty('lat') || !streetview_options.hasOwnProperty('lng')) {
1857
+ streetview_options.lat = this.getCenter().lat();
1858
+ streetview_options.lng = this.getCenter().lng();
1859
+ }
1860
+
1861
+ this.panorama = GMaps.createPanorama(streetview_options);
1862
+
1863
+ this.map.setStreetView(this.panorama);
1864
+
1865
+ return this.panorama;
1866
+ };
1867
+
1868
+ GMaps.createPanorama = function(options) {
1869
+ var el = getElementById(options.el, options.context);
1870
+
1871
+ options.position = new google.maps.LatLng(options.lat, options.lng);
1872
+
1873
+ delete options.el;
1874
+ delete options.context;
1875
+ delete options.lat;
1876
+ delete options.lng;
1877
+
1878
+ var streetview_events = ['closeclick', 'links_changed', 'pano_changed', 'position_changed', 'pov_changed', 'resize', 'visible_changed'],
1879
+ streetview_options = extend_object({visible : true}, options);
1880
+
1881
+ for (var i = 0; i < streetview_events.length; i++) {
1882
+ delete streetview_options[streetview_events[i]];
1883
+ }
1884
+
1885
+ var panorama = new google.maps.StreetViewPanorama(el, streetview_options);
1886
+
1887
+ for (var i = 0; i < streetview_events.length; i++) {
1888
+ (function(object, name) {
1889
+ if (options[name]) {
1890
+ google.maps.event.addListener(object, name, function(){
1891
+ options[name].apply(this);
1892
+ });
1893
+ }
1894
+ })(panorama, streetview_events[i]);
1895
+ }
1896
+
1897
+ return panorama;
1898
+ };
1899
+
1900
+ GMaps.prototype.on = function(event_name, handler) {
1901
+ return GMaps.on(event_name, this, handler);
1902
+ };
1903
+
1904
+ GMaps.prototype.off = function(event_name) {
1905
+ GMaps.off(event_name, this);
1906
+ };
1907
+
1908
+ GMaps.custom_events = ['marker_added', 'marker_removed', 'polyline_added', 'polyline_removed', 'polygon_added', 'polygon_removed', 'geolocated', 'geolocation_failed'];
1909
+
1910
+ GMaps.on = function(event_name, object, handler) {
1911
+ if (GMaps.custom_events.indexOf(event_name) == -1) {
1912
+ if(object instanceof GMaps) object = object.map;
1913
+ return google.maps.event.addListener(object, event_name, handler);
1914
+ }
1915
+ else {
1916
+ var registered_event = {
1917
+ handler : handler,
1918
+ eventName : event_name
1919
+ };
1920
+
1921
+ object.registered_events[event_name] = object.registered_events[event_name] || [];
1922
+ object.registered_events[event_name].push(registered_event);
1923
+
1924
+ return registered_event;
1925
+ }
1926
+ };
1927
+
1928
+ GMaps.off = function(event_name, object) {
1929
+ if (GMaps.custom_events.indexOf(event_name) == -1) {
1930
+ if(object instanceof GMaps) object = object.map;
1931
+ google.maps.event.clearListeners(object, event_name);
1932
+ }
1933
+ else {
1934
+ object.registered_events[event_name] = [];
1935
+ }
1936
+ };
1937
+
1938
+ GMaps.fire = function(event_name, object, scope) {
1939
+ if (GMaps.custom_events.indexOf(event_name) == -1) {
1940
+ google.maps.event.trigger(object, event_name, Array.prototype.slice.apply(arguments).slice(2));
1941
+ }
1942
+ else {
1943
+ if(event_name in scope.registered_events) {
1944
+ var firing_events = scope.registered_events[event_name];
1945
+
1946
+ for(var i = 0; i < firing_events.length; i++) {
1947
+ (function(handler, scope, object) {
1948
+ handler.apply(scope, [object]);
1949
+ })(firing_events[i]['handler'], scope, object);
1950
+ }
1951
+ }
1952
+ }
1953
+ };
1954
+
1955
+ GMaps.geolocate = function(options) {
1956
+ var complete_callback = options.always || options.complete;
1957
+
1958
+ if (navigator.geolocation) {
1959
+ navigator.geolocation.getCurrentPosition(function(position) {
1960
+ options.success(position);
1961
+
1962
+ if (complete_callback) {
1963
+ complete_callback();
1964
+ }
1965
+ }, function(error) {
1966
+ options.error(error);
1967
+
1968
+ if (complete_callback) {
1969
+ complete_callback();
1970
+ }
1971
+ }, options.options);
1972
+ }
1973
+ else {
1974
+ options.not_supported();
1975
+
1976
+ if (complete_callback) {
1977
+ complete_callback();
1978
+ }
1979
+ }
1980
+ };
1981
+
1982
+ GMaps.geocode = function(options) {
1983
+ this.geocoder = new google.maps.Geocoder();
1984
+ var callback = options.callback;
1985
+ if (options.hasOwnProperty('lat') && options.hasOwnProperty('lng')) {
1986
+ options.latLng = new google.maps.LatLng(options.lat, options.lng);
1987
+ }
1988
+
1989
+ delete options.lat;
1990
+ delete options.lng;
1991
+ delete options.callback;
1992
+
1993
+ this.geocoder.geocode(options, function(results, status) {
1994
+ callback(results, status);
1995
+ });
1996
+ };
1997
+
1998
+ //==========================
1999
+ // Polygon containsLatLng
2000
+ // https://github.com/tparkin/Google-Maps-Point-in-Polygon
2001
+ // Poygon getBounds extension - google-maps-extensions
2002
+ // http://code.google.com/p/google-maps-extensions/source/browse/google.maps.Polygon.getBounds.js
2003
+ if (!google.maps.Polygon.prototype.getBounds) {
2004
+ google.maps.Polygon.prototype.getBounds = function(latLng) {
2005
+ var bounds = new google.maps.LatLngBounds();
2006
+ var paths = this.getPaths();
2007
+ var path;
2008
+
2009
+ for (var p = 0; p < paths.getLength(); p++) {
2010
+ path = paths.getAt(p);
2011
+ for (var i = 0; i < path.getLength(); i++) {
2012
+ bounds.extend(path.getAt(i));
2013
+ }
2014
+ }
2015
+
2016
+ return bounds;
2017
+ };
2018
+ }
2019
+
2020
+ if (!google.maps.Polygon.prototype.containsLatLng) {
2021
+ // Polygon containsLatLng - method to determine if a latLng is within a polygon
2022
+ google.maps.Polygon.prototype.containsLatLng = function(latLng) {
2023
+ // Exclude points outside of bounds as there is no way they are in the poly
2024
+ var bounds = this.getBounds();
2025
+
2026
+ if (bounds !== null && !bounds.contains(latLng)) {
2027
+ return false;
2028
+ }
2029
+
2030
+ // Raycast point in polygon method
2031
+ var inPoly = false;
2032
+
2033
+ var numPaths = this.getPaths().getLength();
2034
+ for (var p = 0; p < numPaths; p++) {
2035
+ var path = this.getPaths().getAt(p);
2036
+ var numPoints = path.getLength();
2037
+ var j = numPoints - 1;
2038
+
2039
+ for (var i = 0; i < numPoints; i++) {
2040
+ var vertex1 = path.getAt(i);
2041
+ var vertex2 = path.getAt(j);
2042
+
2043
+ if (vertex1.lng() < latLng.lng() && vertex2.lng() >= latLng.lng() || vertex2.lng() < latLng.lng() && vertex1.lng() >= latLng.lng()) {
2044
+ if (vertex1.lat() + (latLng.lng() - vertex1.lng()) / (vertex2.lng() - vertex1.lng()) * (vertex2.lat() - vertex1.lat()) < latLng.lat()) {
2045
+ inPoly = !inPoly;
2046
+ }
2047
+ }
2048
+
2049
+ j = i;
2050
+ }
2051
+ }
2052
+
2053
+ return inPoly;
2054
+ };
2055
+ }
2056
+
2057
+ google.maps.LatLngBounds.prototype.containsLatLng = function(latLng) {
2058
+ return this.contains(latLng);
2059
+ };
2060
+
2061
+ google.maps.Marker.prototype.setFences = function(fences) {
2062
+ this.fences = fences;
2063
+ };
2064
+
2065
+ google.maps.Marker.prototype.addFence = function(fence) {
2066
+ this.fences.push(fence);
2067
+ };
2068
+
2069
+ google.maps.Marker.prototype.getId = function() {
2070
+ return this['__gm_id'];
2071
+ };
2072
+
2073
+ //==========================
2074
+ // Array indexOf
2075
+ // https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf
2076
+ if (!Array.prototype.indexOf) {
2077
+ Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
2078
+ "use strict";
2079
+ if (this == null) {
2080
+ throw new TypeError();
2081
+ }
2082
+ var t = Object(this);
2083
+ var len = t.length >>> 0;
2084
+ if (len === 0) {
2085
+ return -1;
2086
+ }
2087
+ var n = 0;
2088
+ if (arguments.length > 1) {
2089
+ n = Number(arguments[1]);
2090
+ if (n != n) { // shortcut for verifying if it's NaN
2091
+ n = 0;
2092
+ } else if (n != 0 && n != Infinity && n != -Infinity) {
2093
+ n = (n > 0 || -1) * Math.floor(Math.abs(n));
2094
+ }
2095
+ }
2096
+ if (n >= len) {
2097
+ return -1;
2098
+ }
2099
+ var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
2100
+ for (; k < len; k++) {
2101
+ if (k in t && t[k] === searchElement) {
2102
+ return k;
2103
+ }
2104
+ }
2105
+ return -1;
2106
+ }
2107
+ }
2108
+
2109
+ return GMaps;
2110
+ }));