gmaps-rails 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ }));