flashgrid 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +4 -0
  3. data/Gemfile.lock +17 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +78 -0
  6. data/Rakefile +1 -0
  7. data/app/assets/fonts/gotham/gotham-bold.eot +0 -0
  8. data/app/assets/fonts/gotham/gotham-bold.svg +2066 -0
  9. data/app/assets/fonts/gotham/gotham-bold.ttf +0 -0
  10. data/app/assets/fonts/gotham/gotham-bold.woff +0 -0
  11. data/app/assets/fonts/gotham/gotham-book.eot +0 -0
  12. data/app/assets/fonts/gotham/gotham-book.svg +631 -0
  13. data/app/assets/fonts/gotham/gotham-book.ttf +0 -0
  14. data/app/assets/fonts/gotham/gotham-book.woff +0 -0
  15. data/app/assets/fonts/gotham/gotham-light.eot +0 -0
  16. data/app/assets/fonts/gotham/gotham-light.svg +635 -0
  17. data/app/assets/fonts/gotham/gotham-light.ttf +0 -0
  18. data/app/assets/fonts/gotham/gotham-light.woff +0 -0
  19. data/app/assets/fonts/gotham/gotham-medium.eot +0 -0
  20. data/app/assets/fonts/gotham/gotham-medium.svg +629 -0
  21. data/app/assets/fonts/gotham/gotham-medium.ttf +0 -0
  22. data/app/assets/fonts/gotham/gotham-medium.woff +0 -0
  23. data/app/assets/fonts/ionicons/ionicons.eot +0 -0
  24. data/app/assets/fonts/ionicons/ionicons.svg +1623 -0
  25. data/app/assets/fonts/ionicons/ionicons.ttf +0 -0
  26. data/app/assets/fonts/ionicons/ionicons.woff +0 -0
  27. data/flashgrid.gemspec +23 -0
  28. data/lib/flashgrid.rb +6 -0
  29. data/lib/flashgrid/version.rb +3 -0
  30. data/vendor/assets/javascripts/affix.js +127 -0
  31. data/vendor/assets/javascripts/alert.js +78 -0
  32. data/vendor/assets/javascripts/collapse.js +159 -0
  33. data/vendor/assets/javascripts/date_picker.js +1645 -0
  34. data/vendor/assets/javascripts/dropdown.js +134 -0
  35. data/vendor/assets/javascripts/file_input.js +94 -0
  36. data/vendor/assets/javascripts/map.js +2065 -0
  37. data/vendor/assets/javascripts/modal.js +226 -0
  38. data/vendor/assets/javascripts/popover.js +97 -0
  39. data/vendor/assets/javascripts/switch.js +346 -0
  40. data/vendor/assets/javascripts/tab.js +115 -0
  41. data/vendor/assets/javascripts/time_picker.js +1087 -0
  42. data/vendor/assets/javascripts/tooltip.js +365 -0
  43. data/vendor/assets/javascripts/transition.js +36 -0
  44. data/vendor/assets/stylesheets/ad.css.scss +72 -0
  45. data/vendor/assets/stylesheets/affix.css.scss +7 -0
  46. data/vendor/assets/stylesheets/alert.css.scss +72 -0
  47. data/vendor/assets/stylesheets/breadcrumb.css.scss +26 -0
  48. data/vendor/assets/stylesheets/button.css.scss +227 -0
  49. data/vendor/assets/stylesheets/code.css.scss +49 -0
  50. data/vendor/assets/stylesheets/collapse.css.scss +15 -0
  51. data/vendor/assets/stylesheets/datepicker.css.scss +122 -0
  52. data/vendor/assets/stylesheets/dropdown.css.scss +83 -0
  53. data/vendor/assets/stylesheets/footer.css.scss +33 -0
  54. data/vendor/assets/stylesheets/form.css.scss +213 -0
  55. data/vendor/assets/stylesheets/grid.css.scss +291 -0
  56. data/vendor/assets/stylesheets/header.css.scss +134 -0
  57. data/vendor/assets/stylesheets/icon.css.scss +1130 -0
  58. data/vendor/assets/stylesheets/image.css.scss +108 -0
  59. data/vendor/assets/stylesheets/label_and_badge.css.scss +53 -0
  60. data/vendor/assets/stylesheets/link.css.scss +21 -0
  61. data/vendor/assets/stylesheets/list.css.scss +38 -0
  62. data/vendor/assets/stylesheets/map.css.scss +13 -0
  63. data/vendor/assets/stylesheets/modal.css.scss +117 -0
  64. data/vendor/assets/stylesheets/pagination.css.scss +37 -0
  65. data/vendor/assets/stylesheets/placeholder.css.scss +27 -0
  66. data/vendor/assets/stylesheets/popover.css.scss +107 -0
  67. data/vendor/assets/stylesheets/progress.css.scss +25 -0
  68. data/vendor/assets/stylesheets/reset.css.scss +56 -0
  69. data/vendor/assets/stylesheets/switch.css.scss +73 -0
  70. data/vendor/assets/stylesheets/tab.css.scss +179 -0
  71. data/vendor/assets/stylesheets/table.css.scss +73 -0
  72. data/vendor/assets/stylesheets/timepicker.css.scss +81 -0
  73. data/vendor/assets/stylesheets/tooltip.css.scss +81 -0
  74. data/vendor/assets/stylesheets/transition.css.scss +12 -0
  75. data/vendor/assets/stylesheets/trunk.css.scss +69 -0
  76. data/vendor/assets/stylesheets/typography.css.scss +160 -0
  77. metadata +148 -0
@@ -0,0 +1,134 @@
1
+ +function ($) { "use strict";
2
+
3
+ // DROPDOWN CLASS DEFINITION
4
+ // =========================
5
+
6
+ var backdrop = '.dropdown-backdrop'
7
+ var toggle = '[data-toggle=dropdown]'
8
+ var Dropdown = function (element) {
9
+ var $el = $(element).on('click.bs.dropdown', this.toggle)
10
+ }
11
+
12
+ Dropdown.prototype.toggle = function (e) {
13
+ var $this = $(this)
14
+
15
+ if ($this.is('.disabled, :disabled')) return
16
+
17
+ var $parent = getParent($this)
18
+ var isActive = $parent.hasClass('open')
19
+
20
+ clearMenus()
21
+
22
+ if (!isActive) {
23
+ if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
24
+ // if mobile we use a backdrop because click events don't delegate
25
+ $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
26
+ }
27
+
28
+ $parent.trigger(e = $.Event('show.bs.dropdown'))
29
+
30
+ if (e.isDefaultPrevented()) return
31
+
32
+ $parent
33
+ .toggleClass('open')
34
+ .trigger('shown.bs.dropdown')
35
+
36
+ $this.focus()
37
+ }
38
+
39
+ return false
40
+ }
41
+
42
+ Dropdown.prototype.keydown = function (e) {
43
+ if (!/(38|40|27)/.test(e.keyCode)) return
44
+
45
+ var $this = $(this)
46
+
47
+ e.preventDefault()
48
+ e.stopPropagation()
49
+
50
+ if ($this.is('.disabled, :disabled')) return
51
+
52
+ var $parent = getParent($this)
53
+ var isActive = $parent.hasClass('open')
54
+
55
+ if (!isActive || (isActive && e.keyCode == 27)) {
56
+ if (e.which == 27) $parent.find(toggle).focus()
57
+ return $this.click()
58
+ }
59
+
60
+ var $items = $('[role=menu] li:not(.divider):visible a', $parent)
61
+
62
+ if (!$items.length) return
63
+
64
+ var index = $items.index($items.filter(':focus'))
65
+
66
+ if (e.keyCode == 38 && index > 0) index-- // up
67
+ if (e.keyCode == 40 && index < $items.length - 1) index++ // down
68
+ if (!~index) index=0
69
+
70
+ $items.eq(index).focus()
71
+ }
72
+
73
+ function clearMenus() {
74
+ $(backdrop).remove()
75
+ $(toggle).each(function (e) {
76
+ var $parent = getParent($(this))
77
+ if (!$parent.hasClass('open')) return
78
+ $parent.trigger(e = $.Event('hide.bs.dropdown'))
79
+ if (e.isDefaultPrevented()) return
80
+ $parent.removeClass('open').trigger('hidden.bs.dropdown')
81
+ })
82
+ }
83
+
84
+ function getParent($this) {
85
+ var selector = $this.attr('data-target')
86
+
87
+ if (!selector) {
88
+ selector = $this.attr('href')
89
+ selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
90
+ }
91
+
92
+ var $parent = selector && $(selector)
93
+
94
+ return $parent && $parent.length ? $parent : $this.parent()
95
+ }
96
+
97
+
98
+ // DROPDOWN PLUGIN DEFINITION
99
+ // ==========================
100
+
101
+ var old = $.fn.dropdown
102
+
103
+ $.fn.dropdown = function (option) {
104
+ return this.each(function () {
105
+ var $this = $(this)
106
+ var data = $this.data('dropdown')
107
+
108
+ if (!data) $this.data('dropdown', (data = new Dropdown(this)))
109
+ if (typeof option == 'string') data[option].call($this)
110
+ })
111
+ }
112
+
113
+ $.fn.dropdown.Constructor = Dropdown
114
+
115
+
116
+ // DROPDOWN NO CONFLICT
117
+ // ====================
118
+
119
+ $.fn.dropdown.noConflict = function () {
120
+ $.fn.dropdown = old
121
+ return this
122
+ }
123
+
124
+
125
+ // APPLY TO STANDARD DROPDOWN ELEMENTS
126
+ // ===================================
127
+
128
+ $(document)
129
+ .on('click.bs.dropdown.data-api', clearMenus)
130
+ .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
131
+ .on('click.bs.dropdown.data-api' , toggle, Dropdown.prototype.toggle)
132
+ .on('keydown.bs.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
133
+
134
+ }(jQuery);
@@ -0,0 +1,94 @@
1
+ $(function() {
2
+
3
+ $("input[type=file].file-input").each(function(i,el){
4
+
5
+ // Maybe some fields don't need to be standardized.
6
+ if (typeof $(this).attr("data-vendor-style") != 'undefined') {
7
+ return;
8
+ }
9
+
10
+ // Set the word to be displayed on the button
11
+ var buttonWord = "Browse";
12
+ if (typeof $(this).attr("title") != "undefined") {
13
+ buttonWord = $(this).attr("title");
14
+ }
15
+
16
+ var input = $("<div>").append( $(el).eq(0).clone() ).html();
17
+
18
+ // Set class used to style the input
19
+ var view = "btn";
20
+ if (typeof $(this).attr("data-view") != "undefined") {
21
+ view = $(this).attr("data-view");
22
+ }
23
+
24
+ $(el).replaceWith("<a class='"+view+" file-input'>"+buttonWord+input+"</a>");
25
+
26
+ // Set class when input has changed change
27
+ var viewChanged = null;
28
+ if (typeof $(this).attr("data-view-changed") != "undefined") {
29
+ viewChanged = $(this).attr("data-view-changed");
30
+ }
31
+
32
+ // Updated button on change to show add a class which can show an indicator
33
+ $(".file-input input[type=file]").change(function(){
34
+ $("a.file-input").addClass(viewChanged);
35
+ });
36
+ })
37
+
38
+ // After we have found all of the file inputs let's apply a listener for tracking the mouse movement.
39
+ // This is important because the in order to give the illusion that this is a button in FF we actually need to move the button from the file input under the cursor. Ugh.
40
+ .promise().done( function(){
41
+
42
+ // As the cursor moves over our new Bootstrap button we need to adjust the position of the invisible file input Browse button to be under the cursor.
43
+ // This gives us the pointer cursor that FF denies us
44
+ $(".file-input").mousemove(function(cursor) {
45
+
46
+ var input, wrapper, wrapperX, wrapperY, inputWidth, inputHeight, cursorX, cursorY;
47
+
48
+ // This wrapper elent (the button surround this file input)
49
+ wrapper = $(this);
50
+
51
+ // The invisible file input elent
52
+ input = wrapper.find("input");
53
+
54
+ // The left-most position of the wrapper
55
+ wrapperX = wrapper.offset().left;
56
+
57
+ // The top-most position of the wrapper
58
+ wrapperY = wrapper.offset().top;
59
+
60
+ // The with of the browsers input field
61
+ inputWidth= input.width();
62
+
63
+ // The height of the browsers input field
64
+ inputHeight= input.height();
65
+
66
+ //The position of the cursor in the wrapper
67
+ cursorX = cursor.pageX;
68
+ cursorY = cursor.pageY;
69
+
70
+ //The positions we are to move the invisible file input
71
+ // The 20 at the end is an arbitrary number of pixels that we can shift the input such that cursor is not pointing at the end of the Browse button but somewhere nearer the middle
72
+ moveInputX = cursorX - wrapperX - inputWidth + 20;
73
+
74
+ // Slides the invisible input Browse button to be positioned middle under the cursor
75
+ moveInputY = cursorY- wrapperY - (inputHeight/2);
76
+
77
+ // Apply the positioning styles to actually move the invisible file input
78
+ input.css({
79
+ left:moveInputX,
80
+ top:moveInputY
81
+ });
82
+ });
83
+ });
84
+
85
+ // Add the styles before the first stylesheet
86
+ // This ensures they can be easily overridden with developer styles
87
+ var cssHtml = "<style>"+
88
+ ".file-input { overflow: hidden; position: relative; cursor: pointer; z-index: 1; }"+
89
+ ".file-input input[type=file], .btn-file input[type=file]:focus, .btn-file input[type=file]:hover { position: absolute; top: 0; left: 0; cursor: pointer; opacity: 0; z-index: 99; outline: 0; }"+
90
+ "</style>";
91
+
92
+ $("link[rel=stylesheet]").eq(0).before(cssHtml);
93
+
94
+ });
@@ -0,0 +1,2065 @@
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.9
15
+ * http://hpneo.github.com/gmaps/
16
+ *
17
+ * Copyright 2013, 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
+ control.style.fontFamily = 'Arial, sans-serif';
484
+ control.style.fontSize = '13px';
485
+ control.style.boxShadow = 'rgba(0, 0, 0, 0.398438) 0px 2px 4px';
486
+
487
+ for (var option in options.style) {
488
+ control.style[option] = options.style[option];
489
+ }
490
+
491
+ if (options.id) {
492
+ control.id = options.id;
493
+ }
494
+
495
+ if (options.classes) {
496
+ control.className = options.classes;
497
+ }
498
+
499
+ if (options.content) {
500
+ control.innerHTML = options.content;
501
+ }
502
+
503
+ for (var ev in options.events) {
504
+ (function(object, name) {
505
+ google.maps.event.addDomListener(object, name, function(){
506
+ options.events[name].apply(this, [this]);
507
+ });
508
+ })(control, ev);
509
+ }
510
+
511
+ control.index = 1;
512
+
513
+ return control;
514
+ };
515
+
516
+ GMaps.prototype.addControl = function(options) {
517
+ var position = google.maps.ControlPosition[options.position.toUpperCase()];
518
+
519
+ delete options.position;
520
+
521
+ var control = this.createControl(options);
522
+ this.controls.push(control);
523
+
524
+ this.map.controls[position].push(control);
525
+
526
+ return control;
527
+ };
528
+
529
+ GMaps.prototype.createMarker = function(options) {
530
+ if (options.lat == undefined && options.lng == undefined && options.position == undefined) {
531
+ throw 'No latitude or longitude defined.';
532
+ }
533
+
534
+ var self = this,
535
+ details = options.details,
536
+ fences = options.fences,
537
+ outside = options.outside,
538
+ base_options = {
539
+ position: new google.maps.LatLng(options.lat, options.lng),
540
+ map: null
541
+ };
542
+
543
+ delete options.lat;
544
+ delete options.lng;
545
+ delete options.fences;
546
+ delete options.outside;
547
+
548
+ var marker_options = extend_object(base_options, options),
549
+ marker = new google.maps.Marker(marker_options);
550
+
551
+ marker.fences = fences;
552
+
553
+ if (options.infoWindow) {
554
+ marker.infoWindow = new google.maps.InfoWindow(options.infoWindow);
555
+
556
+ var info_window_events = ['closeclick', 'content_changed', 'domready', 'position_changed', 'zindex_changed'];
557
+
558
+ for (var ev = 0; ev < info_window_events.length; ev++) {
559
+ (function(object, name) {
560
+ if (options.infoWindow[name]) {
561
+ google.maps.event.addListener(object, name, function(e){
562
+ options.infoWindow[name].apply(this, [e]);
563
+ });
564
+ }
565
+ })(marker.infoWindow, info_window_events[ev]);
566
+ }
567
+ }
568
+
569
+ 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'];
570
+
571
+ var marker_events_with_mouse = ['dblclick', 'drag', 'dragend', 'dragstart', 'mousedown', 'mouseout', 'mouseover', 'mouseup'];
572
+
573
+ for (var ev = 0; ev < marker_events.length; ev++) {
574
+ (function(object, name) {
575
+ if (options[name]) {
576
+ google.maps.event.addListener(object, name, function(){
577
+ options[name].apply(this, [this]);
578
+ });
579
+ }
580
+ })(marker, marker_events[ev]);
581
+ }
582
+
583
+ for (var ev = 0; ev < marker_events_with_mouse.length; ev++) {
584
+ (function(map, object, name) {
585
+ if (options[name]) {
586
+ google.maps.event.addListener(object, name, function(me){
587
+ if(!me.pixel){
588
+ me.pixel = map.getProjection().fromLatLngToPoint(me.latLng)
589
+ }
590
+
591
+ options[name].apply(this, [me]);
592
+ });
593
+ }
594
+ })(this.map, marker, marker_events_with_mouse[ev]);
595
+ }
596
+
597
+ google.maps.event.addListener(marker, 'click', function() {
598
+ this.details = details;
599
+
600
+ if (options.click) {
601
+ options.click.apply(this, [this]);
602
+ }
603
+
604
+ if (marker.infoWindow) {
605
+ self.hideInfoWindows();
606
+ marker.infoWindow.open(self.map, marker);
607
+ }
608
+ });
609
+
610
+ google.maps.event.addListener(marker, 'rightclick', function(e) {
611
+ e.marker = this;
612
+
613
+ if (options.rightclick) {
614
+ options.rightclick.apply(this, [e]);
615
+ }
616
+
617
+ if (window.context_menu[self.el.id]['marker'] != undefined) {
618
+ self.buildContextMenu('marker', e);
619
+ }
620
+ });
621
+
622
+ if (marker.fences) {
623
+ google.maps.event.addListener(marker, 'dragend', function() {
624
+ self.checkMarkerGeofence(marker, function(m, f) {
625
+ outside(m, f);
626
+ });
627
+ });
628
+ }
629
+
630
+ return marker;
631
+ };
632
+
633
+ GMaps.prototype.addMarker = function(options) {
634
+ var marker;
635
+ if(options.hasOwnProperty('gm_accessors_')) {
636
+ // Native google.maps.Marker object
637
+ marker = options;
638
+ }
639
+ else {
640
+ if ((options.hasOwnProperty('lat') && options.hasOwnProperty('lng')) || options.position) {
641
+ marker = this.createMarker(options);
642
+ }
643
+ else {
644
+ throw 'No latitude or longitude defined.';
645
+ }
646
+ }
647
+
648
+ marker.setMap(this.map);
649
+
650
+ if(this.markerClusterer) {
651
+ this.markerClusterer.addMarker(marker);
652
+ }
653
+
654
+ this.markers.push(marker);
655
+
656
+ GMaps.fire('marker_added', marker, this);
657
+
658
+ return marker;
659
+ };
660
+
661
+ GMaps.prototype.addMarkers = function(array) {
662
+ for (var i = 0, marker; marker=array[i]; i++) {
663
+ this.addMarker(marker);
664
+ }
665
+
666
+ return this.markers;
667
+ };
668
+
669
+ GMaps.prototype.hideInfoWindows = function() {
670
+ for (var i = 0, marker; marker = this.markers[i]; i++){
671
+ if (marker.infoWindow){
672
+ marker.infoWindow.close();
673
+ }
674
+ }
675
+ };
676
+
677
+ GMaps.prototype.removeMarker = function(marker) {
678
+ for (var i = 0; i < this.markers.length; i++) {
679
+ if (this.markers[i] === marker) {
680
+ this.markers[i].setMap(null);
681
+ this.markers.splice(i, 1);
682
+
683
+ if(this.markerClusterer) {
684
+ this.markerClusterer.removeMarker(marker);
685
+ }
686
+
687
+ GMaps.fire('marker_removed', marker, this);
688
+
689
+ break;
690
+ }
691
+ }
692
+
693
+ return marker;
694
+ };
695
+
696
+ GMaps.prototype.removeMarkers = function(collection) {
697
+ var collection = (collection || this.markers);
698
+
699
+ for (var i = 0;i < this.markers.length; i++) {
700
+ if(this.markers[i] === collection[i]) {
701
+ this.markers[i].setMap(null);
702
+ }
703
+ }
704
+
705
+ var new_markers = [];
706
+
707
+ for (var i = 0;i < this.markers.length; i++) {
708
+ if(this.markers[i].getMap() != null) {
709
+ new_markers.push(this.markers[i]);
710
+ }
711
+ }
712
+
713
+ this.markers = new_markers;
714
+ };
715
+
716
+ GMaps.prototype.drawOverlay = function(options) {
717
+ var overlay = new google.maps.OverlayView(),
718
+ auto_show = true;
719
+
720
+ overlay.setMap(this.map);
721
+
722
+ if (options.auto_show != null) {
723
+ auto_show = options.auto_show;
724
+ }
725
+
726
+ overlay.onAdd = function() {
727
+ var el = document.createElement('div');
728
+
729
+ el.style.borderStyle = "none";
730
+ el.style.borderWidth = "0px";
731
+ el.style.position = "absolute";
732
+ el.style.zIndex = 100;
733
+ el.innerHTML = options.content;
734
+
735
+ overlay.el = el;
736
+
737
+ if (!options.layer) {
738
+ options.layer = 'overlayLayer';
739
+ }
740
+
741
+ var panes = this.getPanes(),
742
+ overlayLayer = panes[options.layer],
743
+ stop_overlay_events = ['contextmenu', 'DOMMouseScroll', 'dblclick', 'mousedown'];
744
+
745
+ overlayLayer.appendChild(el);
746
+
747
+ for (var ev = 0; ev < stop_overlay_events.length; ev++) {
748
+ (function(object, name) {
749
+ google.maps.event.addDomListener(object, name, function(e){
750
+ if (navigator.userAgent.toLowerCase().indexOf('msie') != -1 && document.all) {
751
+ e.cancelBubble = true;
752
+ e.returnValue = false;
753
+ }
754
+ else {
755
+ e.stopPropagation();
756
+ }
757
+ });
758
+ })(el, stop_overlay_events[ev]);
759
+ }
760
+
761
+ google.maps.event.trigger(this, 'ready');
762
+ };
763
+
764
+ overlay.draw = function() {
765
+ var projection = this.getProjection(),
766
+ pixel = projection.fromLatLngToDivPixel(new google.maps.LatLng(options.lat, options.lng));
767
+
768
+ options.horizontalOffset = options.horizontalOffset || 0;
769
+ options.verticalOffset = options.verticalOffset || 0;
770
+
771
+ var el = overlay.el,
772
+ content = el.children[0],
773
+ content_height = content.clientHeight,
774
+ content_width = content.clientWidth;
775
+
776
+ switch (options.verticalAlign) {
777
+ case 'top':
778
+ el.style.top = (pixel.y - content_height + options.verticalOffset) + 'px';
779
+ break;
780
+ default:
781
+ case 'middle':
782
+ el.style.top = (pixel.y - (content_height / 2) + options.verticalOffset) + 'px';
783
+ break;
784
+ case 'bottom':
785
+ el.style.top = (pixel.y + options.verticalOffset) + 'px';
786
+ break;
787
+ }
788
+
789
+ switch (options.horizontalAlign) {
790
+ case 'left':
791
+ el.style.left = (pixel.x - content_width + options.horizontalOffset) + 'px';
792
+ break;
793
+ default:
794
+ case 'center':
795
+ el.style.left = (pixel.x - (content_width / 2) + options.horizontalOffset) + 'px';
796
+ break;
797
+ case 'right':
798
+ el.style.left = (pixel.x + options.horizontalOffset) + 'px';
799
+ break;
800
+ }
801
+
802
+ el.style.display = auto_show ? 'block' : 'none';
803
+
804
+ if (!auto_show) {
805
+ options.show.apply(this, [el]);
806
+ }
807
+ };
808
+
809
+ overlay.onRemove = function() {
810
+ var el = overlay.el;
811
+
812
+ if (options.remove) {
813
+ options.remove.apply(this, [el]);
814
+ }
815
+ else {
816
+ overlay.el.parentNode.removeChild(overlay.el);
817
+ overlay.el = null;
818
+ }
819
+ };
820
+
821
+ this.overlays.push(overlay);
822
+ return overlay;
823
+ };
824
+
825
+ GMaps.prototype.removeOverlay = function(overlay) {
826
+ for (var i = 0; i < this.overlays.length; i++) {
827
+ if (this.overlays[i] === overlay) {
828
+ this.overlays[i].setMap(null);
829
+ this.overlays.splice(i, 1);
830
+
831
+ break;
832
+ }
833
+ }
834
+ };
835
+
836
+ GMaps.prototype.removeOverlays = function() {
837
+ for (var i = 0, item; item = this.overlays[i]; i++) {
838
+ item.setMap(null);
839
+ }
840
+
841
+ this.overlays = [];
842
+ };
843
+
844
+ GMaps.prototype.drawPolyline = function(options) {
845
+ var path = [],
846
+ points = options.path;
847
+
848
+ if (points.length) {
849
+ if (points[0][0] === undefined) {
850
+ path = points;
851
+ }
852
+ else {
853
+ for (var i=0, latlng; latlng=points[i]; i++) {
854
+ path.push(new google.maps.LatLng(latlng[0], latlng[1]));
855
+ }
856
+ }
857
+ }
858
+
859
+ var polyline_options = {
860
+ map: this.map,
861
+ path: path,
862
+ strokeColor: options.strokeColor,
863
+ strokeOpacity: options.strokeOpacity,
864
+ strokeWeight: options.strokeWeight,
865
+ geodesic: options.geodesic,
866
+ clickable: true,
867
+ editable: false,
868
+ visible: true
869
+ };
870
+
871
+ if (options.hasOwnProperty("clickable")) {
872
+ polyline_options.clickable = options.clickable;
873
+ }
874
+
875
+ if (options.hasOwnProperty("editable")) {
876
+ polyline_options.editable = options.editable;
877
+ }
878
+
879
+ if (options.hasOwnProperty("icons")) {
880
+ polyline_options.icons = options.icons;
881
+ }
882
+
883
+ if (options.hasOwnProperty("zIndex")) {
884
+ polyline_options.zIndex = options.zIndex;
885
+ }
886
+
887
+ var polyline = new google.maps.Polyline(polyline_options);
888
+
889
+ var polyline_events = ['click', 'dblclick', 'mousedown', 'mousemove', 'mouseout', 'mouseover', 'mouseup', 'rightclick'];
890
+
891
+ for (var ev = 0; ev < polyline_events.length; ev++) {
892
+ (function(object, name) {
893
+ if (options[name]) {
894
+ google.maps.event.addListener(object, name, function(e){
895
+ options[name].apply(this, [e]);
896
+ });
897
+ }
898
+ })(polyline, polyline_events[ev]);
899
+ }
900
+
901
+ this.polylines.push(polyline);
902
+
903
+ GMaps.fire('polyline_added', polyline, this);
904
+
905
+ return polyline;
906
+ };
907
+
908
+ GMaps.prototype.removePolyline = function(polyline) {
909
+ for (var i = 0; i < this.polylines.length; i++) {
910
+ if (this.polylines[i] === polyline) {
911
+ this.polylines[i].setMap(null);
912
+ this.polylines.splice(i, 1);
913
+
914
+ GMaps.fire('polyline_removed', polyline, this);
915
+
916
+ break;
917
+ }
918
+ }
919
+ };
920
+
921
+ GMaps.prototype.removePolylines = function() {
922
+ for (var i = 0, item; item = this.polylines[i]; i++) {
923
+ item.setMap(null);
924
+ }
925
+
926
+ this.polylines = [];
927
+ };
928
+
929
+ GMaps.prototype.drawCircle = function(options) {
930
+ options = extend_object({
931
+ map: this.map,
932
+ center: new google.maps.LatLng(options.lat, options.lng)
933
+ }, options);
934
+
935
+ delete options.lat;
936
+ delete options.lng;
937
+
938
+ var polygon = new google.maps.Circle(options),
939
+ polygon_events = ['click', 'dblclick', 'mousedown', 'mousemove', 'mouseout', 'mouseover', 'mouseup', 'rightclick'];
940
+
941
+ for (var ev = 0; ev < polygon_events.length; ev++) {
942
+ (function(object, name) {
943
+ if (options[name]) {
944
+ google.maps.event.addListener(object, name, function(e){
945
+ options[name].apply(this, [e]);
946
+ });
947
+ }
948
+ })(polygon, polygon_events[ev]);
949
+ }
950
+
951
+ this.polygons.push(polygon);
952
+
953
+ return polygon;
954
+ };
955
+
956
+ GMaps.prototype.drawRectangle = function(options) {
957
+ options = extend_object({
958
+ map: this.map
959
+ }, options);
960
+
961
+ var latLngBounds = new google.maps.LatLngBounds(
962
+ new google.maps.LatLng(options.bounds[0][0], options.bounds[0][1]),
963
+ new google.maps.LatLng(options.bounds[1][0], options.bounds[1][1])
964
+ );
965
+
966
+ options.bounds = latLngBounds;
967
+
968
+ var polygon = new google.maps.Rectangle(options),
969
+ polygon_events = ['click', 'dblclick', 'mousedown', 'mousemove', 'mouseout', 'mouseover', 'mouseup', 'rightclick'];
970
+
971
+ for (var ev = 0; ev < polygon_events.length; ev++) {
972
+ (function(object, name) {
973
+ if (options[name]) {
974
+ google.maps.event.addListener(object, name, function(e){
975
+ options[name].apply(this, [e]);
976
+ });
977
+ }
978
+ })(polygon, polygon_events[ev]);
979
+ }
980
+
981
+ this.polygons.push(polygon);
982
+
983
+ return polygon;
984
+ };
985
+
986
+ GMaps.prototype.drawPolygon = function(options) {
987
+ var useGeoJSON = false;
988
+
989
+ if(options.hasOwnProperty("useGeoJSON")) {
990
+ useGeoJSON = options.useGeoJSON;
991
+ }
992
+
993
+ delete options.useGeoJSON;
994
+
995
+ options = extend_object({
996
+ map: this.map
997
+ }, options);
998
+
999
+ if (useGeoJSON == false) {
1000
+ options.paths = [options.paths.slice(0)];
1001
+ }
1002
+
1003
+ if (options.paths.length > 0) {
1004
+ if (options.paths[0].length > 0) {
1005
+ options.paths = array_flat(array_map(options.paths, arrayToLatLng, useGeoJSON));
1006
+ }
1007
+ }
1008
+
1009
+ var polygon = new google.maps.Polygon(options),
1010
+ polygon_events = ['click', 'dblclick', 'mousedown', 'mousemove', 'mouseout', 'mouseover', 'mouseup', 'rightclick'];
1011
+
1012
+ for (var ev = 0; ev < polygon_events.length; ev++) {
1013
+ (function(object, name) {
1014
+ if (options[name]) {
1015
+ google.maps.event.addListener(object, name, function(e){
1016
+ options[name].apply(this, [e]);
1017
+ });
1018
+ }
1019
+ })(polygon, polygon_events[ev]);
1020
+ }
1021
+
1022
+ this.polygons.push(polygon);
1023
+
1024
+ GMaps.fire('polygon_added', polygon, this);
1025
+
1026
+ return polygon;
1027
+ };
1028
+
1029
+ GMaps.prototype.removePolygon = function(polygon) {
1030
+ for (var i = 0; i < this.polygons.length; i++) {
1031
+ if (this.polygons[i] === polygon) {
1032
+ this.polygons[i].setMap(null);
1033
+ this.polygons.splice(i, 1);
1034
+
1035
+ GMaps.fire('polygon_removed', polygon, this);
1036
+
1037
+ break;
1038
+ }
1039
+ }
1040
+ };
1041
+
1042
+ GMaps.prototype.removePolygons = function() {
1043
+ for (var i = 0, item; item = this.polygons[i]; i++) {
1044
+ item.setMap(null);
1045
+ }
1046
+
1047
+ this.polygons = [];
1048
+ };
1049
+
1050
+ GMaps.prototype.getFromFusionTables = function(options) {
1051
+ var events = options.events;
1052
+
1053
+ delete options.events;
1054
+
1055
+ var fusion_tables_options = options,
1056
+ layer = new google.maps.FusionTablesLayer(fusion_tables_options);
1057
+
1058
+ for (var ev in events) {
1059
+ (function(object, name) {
1060
+ google.maps.event.addListener(object, name, function(e) {
1061
+ events[name].apply(this, [e]);
1062
+ });
1063
+ })(layer, ev);
1064
+ }
1065
+
1066
+ this.layers.push(layer);
1067
+
1068
+ return layer;
1069
+ };
1070
+
1071
+ GMaps.prototype.loadFromFusionTables = function(options) {
1072
+ var layer = this.getFromFusionTables(options);
1073
+ layer.setMap(this.map);
1074
+
1075
+ return layer;
1076
+ };
1077
+
1078
+ GMaps.prototype.getFromKML = function(options) {
1079
+ var url = options.url,
1080
+ events = options.events;
1081
+
1082
+ delete options.url;
1083
+ delete options.events;
1084
+
1085
+ var kml_options = options,
1086
+ layer = new google.maps.KmlLayer(url, kml_options);
1087
+
1088
+ for (var ev in events) {
1089
+ (function(object, name) {
1090
+ google.maps.event.addListener(object, name, function(e) {
1091
+ events[name].apply(this, [e]);
1092
+ });
1093
+ })(layer, ev);
1094
+ }
1095
+
1096
+ this.layers.push(layer);
1097
+
1098
+ return layer;
1099
+ };
1100
+
1101
+ GMaps.prototype.loadFromKML = function(options) {
1102
+ var layer = this.getFromKML(options);
1103
+ layer.setMap(this.map);
1104
+
1105
+ return layer;
1106
+ };
1107
+
1108
+ GMaps.prototype.addLayer = function(layerName, options) {
1109
+ //var default_layers = ['weather', 'clouds', 'traffic', 'transit', 'bicycling', 'panoramio', 'places'];
1110
+ options = options || {};
1111
+ var layer;
1112
+
1113
+ switch(layerName) {
1114
+ case 'weather': this.singleLayers.weather = layer = new google.maps.weather.WeatherLayer();
1115
+ break;
1116
+ case 'clouds': this.singleLayers.clouds = layer = new google.maps.weather.CloudLayer();
1117
+ break;
1118
+ case 'traffic': this.singleLayers.traffic = layer = new google.maps.TrafficLayer();
1119
+ break;
1120
+ case 'transit': this.singleLayers.transit = layer = new google.maps.TransitLayer();
1121
+ break;
1122
+ case 'bicycling': this.singleLayers.bicycling = layer = new google.maps.BicyclingLayer();
1123
+ break;
1124
+ case 'panoramio':
1125
+ this.singleLayers.panoramio = layer = new google.maps.panoramio.PanoramioLayer();
1126
+ layer.setTag(options.filter);
1127
+ delete options.filter;
1128
+
1129
+ //click event
1130
+ if (options.click) {
1131
+ google.maps.event.addListener(layer, 'click', function(event) {
1132
+ options.click(event);
1133
+ delete options.click;
1134
+ });
1135
+ }
1136
+ break;
1137
+ case 'places':
1138
+ this.singleLayers.places = layer = new google.maps.places.PlacesService(this.map);
1139
+
1140
+ //search and nearbySearch callback, Both are the same
1141
+ if (options.search || options.nearbySearch) {
1142
+ var placeSearchRequest = {
1143
+ bounds : options.bounds || null,
1144
+ keyword : options.keyword || null,
1145
+ location : options.location || null,
1146
+ name : options.name || null,
1147
+ radius : options.radius || null,
1148
+ rankBy : options.rankBy || null,
1149
+ types : options.types || null
1150
+ };
1151
+
1152
+ if (options.search) {
1153
+ layer.search(placeSearchRequest, options.search);
1154
+ }
1155
+
1156
+ if (options.nearbySearch) {
1157
+ layer.nearbySearch(placeSearchRequest, options.nearbySearch);
1158
+ }
1159
+ }
1160
+
1161
+ //textSearch callback
1162
+ if (options.textSearch) {
1163
+ var textSearchRequest = {
1164
+ bounds : options.bounds || null,
1165
+ location : options.location || null,
1166
+ query : options.query || null,
1167
+ radius : options.radius || null
1168
+ };
1169
+
1170
+ layer.textSearch(textSearchRequest, options.textSearch);
1171
+ }
1172
+ break;
1173
+ }
1174
+
1175
+ if (layer !== undefined) {
1176
+ if (typeof layer.setOptions == 'function') {
1177
+ layer.setOptions(options);
1178
+ }
1179
+ if (typeof layer.setMap == 'function') {
1180
+ layer.setMap(this.map);
1181
+ }
1182
+
1183
+ return layer;
1184
+ }
1185
+ };
1186
+
1187
+ GMaps.prototype.removeLayer = function(layer) {
1188
+ if (typeof(layer) == "string" && this.singleLayers[layer] !== undefined) {
1189
+ this.singleLayers[layer].setMap(null);
1190
+
1191
+ delete this.singleLayers[layer];
1192
+ }
1193
+ else {
1194
+ for (var i = 0; i < this.layers.length; i++) {
1195
+ if (this.layers[i] === layer) {
1196
+ this.layers[i].setMap(null);
1197
+ this.layers.splice(i, 1);
1198
+
1199
+ break;
1200
+ }
1201
+ }
1202
+ }
1203
+ };
1204
+
1205
+ var travelMode, unitSystem;
1206
+
1207
+ GMaps.prototype.getRoutes = function(options) {
1208
+ switch (options.travelMode) {
1209
+ case 'bicycling':
1210
+ travelMode = google.maps.TravelMode.BICYCLING;
1211
+ break;
1212
+ case 'transit':
1213
+ travelMode = google.maps.TravelMode.TRANSIT;
1214
+ break;
1215
+ case 'driving':
1216
+ travelMode = google.maps.TravelMode.DRIVING;
1217
+ break;
1218
+ default:
1219
+ travelMode = google.maps.TravelMode.WALKING;
1220
+ break;
1221
+ }
1222
+
1223
+ if (options.unitSystem === 'imperial') {
1224
+ unitSystem = google.maps.UnitSystem.IMPERIAL;
1225
+ }
1226
+ else {
1227
+ unitSystem = google.maps.UnitSystem.METRIC;
1228
+ }
1229
+
1230
+ var base_options = {
1231
+ avoidHighways: false,
1232
+ avoidTolls: false,
1233
+ optimizeWaypoints: false,
1234
+ waypoints: []
1235
+ },
1236
+ request_options = extend_object(base_options, options);
1237
+
1238
+ request_options.origin = /string/.test(typeof options.origin) ? options.origin : new google.maps.LatLng(options.origin[0], options.origin[1]);
1239
+ request_options.destination = /string/.test(typeof options.destination) ? options.destination : new google.maps.LatLng(options.destination[0], options.destination[1]);
1240
+ request_options.travelMode = travelMode;
1241
+ request_options.unitSystem = unitSystem;
1242
+
1243
+ delete request_options.callback;
1244
+ delete request_options.error;
1245
+
1246
+ var self = this,
1247
+ service = new google.maps.DirectionsService();
1248
+
1249
+ service.route(request_options, function(result, status) {
1250
+ if (status === google.maps.DirectionsStatus.OK) {
1251
+ for (var r in result.routes) {
1252
+ if (result.routes.hasOwnProperty(r)) {
1253
+ self.routes.push(result.routes[r]);
1254
+ }
1255
+ }
1256
+
1257
+ if (options.callback) {
1258
+ options.callback(self.routes);
1259
+ }
1260
+ }
1261
+ else {
1262
+ if (options.error) {
1263
+ options.error(result, status);
1264
+ }
1265
+ }
1266
+ });
1267
+ };
1268
+
1269
+ GMaps.prototype.removeRoutes = function() {
1270
+ this.routes = [];
1271
+ };
1272
+
1273
+ GMaps.prototype.getElevations = function(options) {
1274
+ options = extend_object({
1275
+ locations: [],
1276
+ path : false,
1277
+ samples : 256
1278
+ }, options);
1279
+
1280
+ if (options.locations.length > 0) {
1281
+ if (options.locations[0].length > 0) {
1282
+ options.locations = array_flat(array_map([options.locations], arrayToLatLng, false));
1283
+ }
1284
+ }
1285
+
1286
+ var callback = options.callback;
1287
+ delete options.callback;
1288
+
1289
+ var service = new google.maps.ElevationService();
1290
+
1291
+ //location request
1292
+ if (!options.path) {
1293
+ delete options.path;
1294
+ delete options.samples;
1295
+
1296
+ service.getElevationForLocations(options, function(result, status) {
1297
+ if (callback && typeof(callback) === "function") {
1298
+ callback(result, status);
1299
+ }
1300
+ });
1301
+ //path request
1302
+ } else {
1303
+ var pathRequest = {
1304
+ path : options.locations,
1305
+ samples : options.samples
1306
+ };
1307
+
1308
+ service.getElevationAlongPath(pathRequest, function(result, status) {
1309
+ if (callback && typeof(callback) === "function") {
1310
+ callback(result, status);
1311
+ }
1312
+ });
1313
+ }
1314
+ };
1315
+
1316
+ GMaps.prototype.cleanRoute = GMaps.prototype.removePolylines;
1317
+
1318
+ GMaps.prototype.drawRoute = function(options) {
1319
+ var self = this;
1320
+
1321
+ this.getRoutes({
1322
+ origin: options.origin,
1323
+ destination: options.destination,
1324
+ travelMode: options.travelMode,
1325
+ waypoints: options.waypoints,
1326
+ unitSystem: options.unitSystem,
1327
+ error: options.error,
1328
+ callback: function(e) {
1329
+ if (e.length > 0) {
1330
+ self.drawPolyline({
1331
+ path: e[e.length - 1].overview_path,
1332
+ strokeColor: options.strokeColor,
1333
+ strokeOpacity: options.strokeOpacity,
1334
+ strokeWeight: options.strokeWeight
1335
+ });
1336
+
1337
+ if (options.callback) {
1338
+ options.callback(e[e.length - 1]);
1339
+ }
1340
+ }
1341
+ }
1342
+ });
1343
+ };
1344
+
1345
+ GMaps.prototype.travelRoute = function(options) {
1346
+ if (options.origin && options.destination) {
1347
+ this.getRoutes({
1348
+ origin: options.origin,
1349
+ destination: options.destination,
1350
+ travelMode: options.travelMode,
1351
+ waypoints : options.waypoints,
1352
+ error: options.error,
1353
+ callback: function(e) {
1354
+ //start callback
1355
+ if (e.length > 0 && options.start) {
1356
+ options.start(e[e.length - 1]);
1357
+ }
1358
+
1359
+ //step callback
1360
+ if (e.length > 0 && options.step) {
1361
+ var route = e[e.length - 1];
1362
+ if (route.legs.length > 0) {
1363
+ var steps = route.legs[0].steps;
1364
+ for (var i=0, step; step=steps[i]; i++) {
1365
+ step.step_number = i;
1366
+ options.step(step, (route.legs[0].steps.length - 1));
1367
+ }
1368
+ }
1369
+ }
1370
+
1371
+ //end callback
1372
+ if (e.length > 0 && options.end) {
1373
+ options.end(e[e.length - 1]);
1374
+ }
1375
+ }
1376
+ });
1377
+ }
1378
+ else if (options.route) {
1379
+ if (options.route.legs.length > 0) {
1380
+ var steps = options.route.legs[0].steps;
1381
+ for (var i=0, step; step=steps[i]; i++) {
1382
+ step.step_number = i;
1383
+ options.step(step);
1384
+ }
1385
+ }
1386
+ }
1387
+ };
1388
+
1389
+ GMaps.prototype.drawSteppedRoute = function(options) {
1390
+ var self = this;
1391
+
1392
+ if (options.origin && options.destination) {
1393
+ this.getRoutes({
1394
+ origin: options.origin,
1395
+ destination: options.destination,
1396
+ travelMode: options.travelMode,
1397
+ waypoints : options.waypoints,
1398
+ error: options.error,
1399
+ callback: function(e) {
1400
+ //start callback
1401
+ if (e.length > 0 && options.start) {
1402
+ options.start(e[e.length - 1]);
1403
+ }
1404
+
1405
+ //step callback
1406
+ if (e.length > 0 && options.step) {
1407
+ var route = e[e.length - 1];
1408
+ if (route.legs.length > 0) {
1409
+ var steps = route.legs[0].steps;
1410
+ for (var i=0, step; step=steps[i]; i++) {
1411
+ step.step_number = i;
1412
+ self.drawPolyline({
1413
+ path: step.path,
1414
+ strokeColor: options.strokeColor,
1415
+ strokeOpacity: options.strokeOpacity,
1416
+ strokeWeight: options.strokeWeight
1417
+ });
1418
+ options.step(step, (route.legs[0].steps.length - 1));
1419
+ }
1420
+ }
1421
+ }
1422
+
1423
+ //end callback
1424
+ if (e.length > 0 && options.end) {
1425
+ options.end(e[e.length - 1]);
1426
+ }
1427
+ }
1428
+ });
1429
+ }
1430
+ else if (options.route) {
1431
+ if (options.route.legs.length > 0) {
1432
+ var steps = options.route.legs[0].steps;
1433
+ for (var i=0, step; step=steps[i]; i++) {
1434
+ step.step_number = i;
1435
+ self.drawPolyline({
1436
+ path: step.path,
1437
+ strokeColor: options.strokeColor,
1438
+ strokeOpacity: options.strokeOpacity,
1439
+ strokeWeight: options.strokeWeight
1440
+ });
1441
+ options.step(step);
1442
+ }
1443
+ }
1444
+ }
1445
+ };
1446
+
1447
+ GMaps.Route = function(options) {
1448
+ this.origin = options.origin;
1449
+ this.destination = options.destination;
1450
+ this.waypoints = options.waypoints;
1451
+
1452
+ this.map = options.map;
1453
+ this.route = options.route;
1454
+ this.step_count = 0;
1455
+ this.steps = this.route.legs[0].steps;
1456
+ this.steps_length = this.steps.length;
1457
+
1458
+ this.polyline = this.map.drawPolyline({
1459
+ path: new google.maps.MVCArray(),
1460
+ strokeColor: options.strokeColor,
1461
+ strokeOpacity: options.strokeOpacity,
1462
+ strokeWeight: options.strokeWeight
1463
+ }).getPath();
1464
+ };
1465
+
1466
+ GMaps.Route.prototype.getRoute = function(options) {
1467
+ var self = this;
1468
+
1469
+ this.map.getRoutes({
1470
+ origin : this.origin,
1471
+ destination : this.destination,
1472
+ travelMode : options.travelMode,
1473
+ waypoints : this.waypoints || [],
1474
+ error: options.error,
1475
+ callback : function() {
1476
+ self.route = e[0];
1477
+
1478
+ if (options.callback) {
1479
+ options.callback.call(self);
1480
+ }
1481
+ }
1482
+ });
1483
+ };
1484
+
1485
+ GMaps.Route.prototype.back = function() {
1486
+ if (this.step_count > 0) {
1487
+ this.step_count--;
1488
+ var path = this.route.legs[0].steps[this.step_count].path;
1489
+
1490
+ for (var p in path){
1491
+ if (path.hasOwnProperty(p)){
1492
+ this.polyline.pop();
1493
+ }
1494
+ }
1495
+ }
1496
+ };
1497
+
1498
+ GMaps.Route.prototype.forward = function() {
1499
+ if (this.step_count < this.steps_length) {
1500
+ var path = this.route.legs[0].steps[this.step_count].path;
1501
+
1502
+ for (var p in path){
1503
+ if (path.hasOwnProperty(p)){
1504
+ this.polyline.push(path[p]);
1505
+ }
1506
+ }
1507
+ this.step_count++;
1508
+ }
1509
+ };
1510
+
1511
+ GMaps.prototype.checkGeofence = function(lat, lng, fence) {
1512
+ return fence.containsLatLng(new google.maps.LatLng(lat, lng));
1513
+ };
1514
+
1515
+ GMaps.prototype.checkMarkerGeofence = function(marker, outside_callback) {
1516
+ if (marker.fences) {
1517
+ for (var i = 0, fence; fence = marker.fences[i]; i++) {
1518
+ var pos = marker.getPosition();
1519
+ if (!this.checkGeofence(pos.lat(), pos.lng(), fence)) {
1520
+ outside_callback(marker, fence);
1521
+ }
1522
+ }
1523
+ }
1524
+ };
1525
+
1526
+ GMaps.prototype.toImage = function(options) {
1527
+ var options = options || {},
1528
+ static_map_options = {};
1529
+
1530
+ static_map_options['size'] = options['size'] || [this.el.clientWidth, this.el.clientHeight];
1531
+ static_map_options['lat'] = this.getCenter().lat();
1532
+ static_map_options['lng'] = this.getCenter().lng();
1533
+
1534
+ if (this.markers.length > 0) {
1535
+ static_map_options['markers'] = [];
1536
+
1537
+ for (var i = 0; i < this.markers.length; i++) {
1538
+ static_map_options['markers'].push({
1539
+ lat: this.markers[i].getPosition().lat(),
1540
+ lng: this.markers[i].getPosition().lng()
1541
+ });
1542
+ }
1543
+ }
1544
+
1545
+ if (this.polylines.length > 0) {
1546
+ var polyline = this.polylines[0];
1547
+
1548
+ static_map_options['polyline'] = {};
1549
+ static_map_options['polyline']['path'] = google.maps.geometry.encoding.encodePath(polyline.getPath());
1550
+ static_map_options['polyline']['strokeColor'] = polyline.strokeColor
1551
+ static_map_options['polyline']['strokeOpacity'] = polyline.strokeOpacity
1552
+ static_map_options['polyline']['strokeWeight'] = polyline.strokeWeight
1553
+ }
1554
+
1555
+ return GMaps.staticMapURL(static_map_options);
1556
+ };
1557
+
1558
+ GMaps.staticMapURL = function(options){
1559
+ var parameters = [],
1560
+ data,
1561
+ static_root = 'http://maps.googleapis.com/maps/api/staticmap';
1562
+
1563
+ if (options.url) {
1564
+ static_root = options.url;
1565
+ delete options.url;
1566
+ }
1567
+
1568
+ static_root += '?';
1569
+
1570
+ var markers = options.markers;
1571
+
1572
+ delete options.markers;
1573
+
1574
+ if (!markers && options.marker) {
1575
+ markers = [options.marker];
1576
+ delete options.marker;
1577
+ }
1578
+
1579
+ var styles = options.styles;
1580
+
1581
+ delete options.styles;
1582
+
1583
+ var polyline = options.polyline;
1584
+ delete options.polyline;
1585
+
1586
+ /** Map options **/
1587
+ if (options.center) {
1588
+ parameters.push('center=' + options.center);
1589
+ delete options.center;
1590
+ }
1591
+ else if (options.address) {
1592
+ parameters.push('center=' + options.address);
1593
+ delete options.address;
1594
+ }
1595
+ else if (options.lat) {
1596
+ parameters.push(['center=', options.lat, ',', options.lng].join(''));
1597
+ delete options.lat;
1598
+ delete options.lng;
1599
+ }
1600
+ else if (options.visible) {
1601
+ var visible = encodeURI(options.visible.join('|'));
1602
+ parameters.push('visible=' + visible);
1603
+ }
1604
+
1605
+ var size = options.size;
1606
+ if (size) {
1607
+ if (size.join) {
1608
+ size = size.join('x');
1609
+ }
1610
+ delete options.size;
1611
+ }
1612
+ else {
1613
+ size = '630x300';
1614
+ }
1615
+ parameters.push('size=' + size);
1616
+
1617
+ if (!options.zoom && options.zoom !== false) {
1618
+ options.zoom = 15;
1619
+ }
1620
+
1621
+ var sensor = options.hasOwnProperty('sensor') ? !!options.sensor : true;
1622
+ delete options.sensor;
1623
+ parameters.push('sensor=' + sensor);
1624
+
1625
+ for (var param in options) {
1626
+ if (options.hasOwnProperty(param)) {
1627
+ parameters.push(param + '=' + options[param]);
1628
+ }
1629
+ }
1630
+
1631
+ /** Markers **/
1632
+ if (markers) {
1633
+ var marker, loc;
1634
+
1635
+ for (var i=0; data=markers[i]; i++) {
1636
+ marker = [];
1637
+
1638
+ if (data.size && data.size !== 'normal') {
1639
+ marker.push('size:' + data.size);
1640
+ delete data.size;
1641
+ }
1642
+ else if (data.icon) {
1643
+ marker.push('icon:' + encodeURI(data.icon));
1644
+ delete data.icon;
1645
+ }
1646
+
1647
+ if (data.color) {
1648
+ marker.push('color:' + data.color.replace('#', '0x'));
1649
+ delete data.color;
1650
+ }
1651
+
1652
+ if (data.label) {
1653
+ marker.push('label:' + data.label[0].toUpperCase());
1654
+ delete data.label;
1655
+ }
1656
+
1657
+ loc = (data.address ? data.address : data.lat + ',' + data.lng);
1658
+ delete data.address;
1659
+ delete data.lat;
1660
+ delete data.lng;
1661
+
1662
+ for(var param in data){
1663
+ if (data.hasOwnProperty(param)) {
1664
+ marker.push(param + ':' + data[param]);
1665
+ }
1666
+ }
1667
+
1668
+ if (marker.length || i === 0) {
1669
+ marker.push(loc);
1670
+ marker = marker.join('|');
1671
+ parameters.push('markers=' + encodeURI(marker));
1672
+ }
1673
+ // New marker without styles
1674
+ else {
1675
+ marker = parameters.pop() + encodeURI('|' + loc);
1676
+ parameters.push(marker);
1677
+ }
1678
+ }
1679
+ }
1680
+
1681
+ /** Map Styles **/
1682
+ if (styles) {
1683
+ for (var i = 0; i < styles.length; i++) {
1684
+ var styleRule = [];
1685
+ if (styles[i].featureType && styles[i].featureType != 'all' ) {
1686
+ styleRule.push('feature:' + styles[i].featureType);
1687
+ }
1688
+
1689
+ if (styles[i].elementType && styles[i].elementType != 'all') {
1690
+ styleRule.push('element:' + styles[i].elementType);
1691
+ }
1692
+
1693
+ for (var j = 0; j < styles[i].stylers.length; j++) {
1694
+ for (var p in styles[i].stylers[j]) {
1695
+ var ruleArg = styles[i].stylers[j][p];
1696
+ if (p == 'hue' || p == 'color') {
1697
+ ruleArg = '0x' + ruleArg.substring(1);
1698
+ }
1699
+ styleRule.push(p + ':' + ruleArg);
1700
+ }
1701
+ }
1702
+
1703
+ var rule = styleRule.join('|');
1704
+ if (rule != '') {
1705
+ parameters.push('style=' + rule);
1706
+ }
1707
+ }
1708
+ }
1709
+
1710
+ /** Polylines **/
1711
+ function parseColor(color, opacity) {
1712
+ if (color[0] === '#'){
1713
+ color = color.replace('#', '0x');
1714
+
1715
+ if (opacity) {
1716
+ opacity = parseFloat(opacity);
1717
+ opacity = Math.min(1, Math.max(opacity, 0));
1718
+ if (opacity === 0) {
1719
+ return '0x00000000';
1720
+ }
1721
+ opacity = (opacity * 255).toString(16);
1722
+ if (opacity.length === 1) {
1723
+ opacity += opacity;
1724
+ }
1725
+
1726
+ color = color.slice(0,8) + opacity;
1727
+ }
1728
+ }
1729
+ return color;
1730
+ }
1731
+
1732
+ if (polyline) {
1733
+ data = polyline;
1734
+ polyline = [];
1735
+
1736
+ if (data.strokeWeight) {
1737
+ polyline.push('weight:' + parseInt(data.strokeWeight, 10));
1738
+ }
1739
+
1740
+ if (data.strokeColor) {
1741
+ var color = parseColor(data.strokeColor, data.strokeOpacity);
1742
+ polyline.push('color:' + color);
1743
+ }
1744
+
1745
+ if (data.fillColor) {
1746
+ var fillcolor = parseColor(data.fillColor, data.fillOpacity);
1747
+ polyline.push('fillcolor:' + fillcolor);
1748
+ }
1749
+
1750
+ var path = data.path;
1751
+ if (path.join) {
1752
+ for (var j=0, pos; pos=path[j]; j++) {
1753
+ polyline.push(pos.join(','));
1754
+ }
1755
+ }
1756
+ else {
1757
+ polyline.push('enc:' + path);
1758
+ }
1759
+
1760
+ polyline = polyline.join('|');
1761
+ parameters.push('path=' + encodeURI(polyline));
1762
+ }
1763
+
1764
+ /** Retina support **/
1765
+ var dpi = window.devicePixelRatio || 1;
1766
+ parameters.push('scale=' + dpi);
1767
+
1768
+ parameters = parameters.join('&');
1769
+ return static_root + parameters;
1770
+ };
1771
+
1772
+ GMaps.prototype.addMapType = function(mapTypeId, options) {
1773
+ if (options.hasOwnProperty("getTileUrl") && typeof(options["getTileUrl"]) == "function") {
1774
+ options.tileSize = options.tileSize || new google.maps.Size(256, 256);
1775
+
1776
+ var mapType = new google.maps.ImageMapType(options);
1777
+
1778
+ this.map.mapTypes.set(mapTypeId, mapType);
1779
+ }
1780
+ else {
1781
+ throw "'getTileUrl' function required.";
1782
+ }
1783
+ };
1784
+
1785
+ GMaps.prototype.addOverlayMapType = function(options) {
1786
+ if (options.hasOwnProperty("getTile") && typeof(options["getTile"]) == "function") {
1787
+ var overlayMapTypeIndex = options.index;
1788
+
1789
+ delete options.index;
1790
+
1791
+ this.map.overlayMapTypes.insertAt(overlayMapTypeIndex, options);
1792
+ }
1793
+ else {
1794
+ throw "'getTile' function required.";
1795
+ }
1796
+ };
1797
+
1798
+ GMaps.prototype.removeOverlayMapType = function(overlayMapTypeIndex) {
1799
+ this.map.overlayMapTypes.removeAt(overlayMapTypeIndex);
1800
+ };
1801
+
1802
+ GMaps.prototype.addStyle = function(options) {
1803
+ var styledMapType = new google.maps.StyledMapType(options.styles, { name: options.styledMapName });
1804
+
1805
+ this.map.mapTypes.set(options.mapTypeId, styledMapType);
1806
+ };
1807
+
1808
+ GMaps.prototype.setStyle = function(mapTypeId) {
1809
+ this.map.setMapTypeId(mapTypeId);
1810
+ };
1811
+
1812
+ GMaps.prototype.createPanorama = function(streetview_options) {
1813
+ if (!streetview_options.hasOwnProperty('lat') || !streetview_options.hasOwnProperty('lng')) {
1814
+ streetview_options.lat = this.getCenter().lat();
1815
+ streetview_options.lng = this.getCenter().lng();
1816
+ }
1817
+
1818
+ this.panorama = GMaps.createPanorama(streetview_options);
1819
+
1820
+ this.map.setStreetView(this.panorama);
1821
+
1822
+ return this.panorama;
1823
+ };
1824
+
1825
+ GMaps.createPanorama = function(options) {
1826
+ var el = getElementById(options.el, options.context);
1827
+
1828
+ options.position = new google.maps.LatLng(options.lat, options.lng);
1829
+
1830
+ delete options.el;
1831
+ delete options.context;
1832
+ delete options.lat;
1833
+ delete options.lng;
1834
+
1835
+ var streetview_events = ['closeclick', 'links_changed', 'pano_changed', 'position_changed', 'pov_changed', 'resize', 'visible_changed'],
1836
+ streetview_options = extend_object({visible : true}, options);
1837
+
1838
+ for (var i = 0; i < streetview_events.length; i++) {
1839
+ delete streetview_options[streetview_events[i]];
1840
+ }
1841
+
1842
+ var panorama = new google.maps.StreetViewPanorama(el, streetview_options);
1843
+
1844
+ for (var i = 0; i < streetview_events.length; i++) {
1845
+ (function(object, name) {
1846
+ if (options[name]) {
1847
+ google.maps.event.addListener(object, name, function(){
1848
+ options[name].apply(this);
1849
+ });
1850
+ }
1851
+ })(panorama, streetview_events[i]);
1852
+ }
1853
+
1854
+ return panorama;
1855
+ };
1856
+
1857
+ GMaps.prototype.on = function(event_name, handler) {
1858
+ return GMaps.on(event_name, this, handler);
1859
+ };
1860
+
1861
+ GMaps.prototype.off = function(event_name) {
1862
+ GMaps.off(event_name, this);
1863
+ };
1864
+
1865
+ GMaps.custom_events = ['marker_added', 'marker_removed', 'polyline_added', 'polyline_removed', 'polygon_added', 'polygon_removed', 'geolocated', 'geolocation_failed'];
1866
+
1867
+ GMaps.on = function(event_name, object, handler) {
1868
+ if (GMaps.custom_events.indexOf(event_name) == -1) {
1869
+ return google.maps.event.addListener(object, event_name, handler);
1870
+ }
1871
+ else {
1872
+ var registered_event = {
1873
+ handler : handler,
1874
+ eventName : event_name
1875
+ };
1876
+
1877
+ object.registered_events[event_name] = object.registered_events[event_name] || [];
1878
+ object.registered_events[event_name].push(registered_event);
1879
+
1880
+ return registered_event;
1881
+ }
1882
+ };
1883
+
1884
+ GMaps.off = function(event_name, object) {
1885
+ if (GMaps.custom_events.indexOf(event_name) == -1) {
1886
+ google.maps.event.clearListeners(object, event_name);
1887
+ }
1888
+ else {
1889
+ object.registered_events[event_name] = [];
1890
+ }
1891
+ };
1892
+
1893
+ GMaps.fire = function(event_name, object, scope) {
1894
+ if (GMaps.custom_events.indexOf(event_name) == -1) {
1895
+ google.maps.event.trigger(object, event_name, Array.prototype.slice.apply(arguments).slice(2));
1896
+ }
1897
+ else {
1898
+ if(event_name in scope.registered_events) {
1899
+ var firing_events = scope.registered_events[event_name];
1900
+
1901
+ for(var i = 0; i < firing_events.length; i++) {
1902
+ (function(handler, scope, object) {
1903
+ handler.apply(scope, [object]);
1904
+ })(firing_events[i]['handler'], scope, object);
1905
+ }
1906
+ }
1907
+ }
1908
+ };
1909
+
1910
+ GMaps.geolocate = function(options) {
1911
+ var complete_callback = options.always || options.complete;
1912
+
1913
+ if (navigator.geolocation) {
1914
+ navigator.geolocation.getCurrentPosition(function(position) {
1915
+ options.success(position);
1916
+
1917
+ if (complete_callback) {
1918
+ complete_callback();
1919
+ }
1920
+ }, function(error) {
1921
+ options.error(error);
1922
+
1923
+ if (complete_callback) {
1924
+ complete_callback();
1925
+ }
1926
+ }, options.options);
1927
+ }
1928
+ else {
1929
+ options.not_supported();
1930
+
1931
+ if (complete_callback) {
1932
+ complete_callback();
1933
+ }
1934
+ }
1935
+ };
1936
+
1937
+ GMaps.geocode = function(options) {
1938
+ this.geocoder = new google.maps.Geocoder();
1939
+ var callback = options.callback;
1940
+ if (options.hasOwnProperty('lat') && options.hasOwnProperty('lng')) {
1941
+ options.latLng = new google.maps.LatLng(options.lat, options.lng);
1942
+ }
1943
+
1944
+ delete options.lat;
1945
+ delete options.lng;
1946
+ delete options.callback;
1947
+
1948
+ this.geocoder.geocode(options, function(results, status) {
1949
+ callback(results, status);
1950
+ });
1951
+ };
1952
+
1953
+ //==========================
1954
+ // Polygon containsLatLng
1955
+ // https://github.com/tparkin/Google-Maps-Point-in-Polygon
1956
+ // Poygon getBounds extension - google-maps-extensions
1957
+ // http://code.google.com/p/google-maps-extensions/source/browse/google.maps.Polygon.getBounds.js
1958
+ if (!google.maps.Polygon.prototype.getBounds) {
1959
+ google.maps.Polygon.prototype.getBounds = function(latLng) {
1960
+ var bounds = new google.maps.LatLngBounds();
1961
+ var paths = this.getPaths();
1962
+ var path;
1963
+
1964
+ for (var p = 0; p < paths.getLength(); p++) {
1965
+ path = paths.getAt(p);
1966
+ for (var i = 0; i < path.getLength(); i++) {
1967
+ bounds.extend(path.getAt(i));
1968
+ }
1969
+ }
1970
+
1971
+ return bounds;
1972
+ };
1973
+ }
1974
+
1975
+ if (!google.maps.Polygon.prototype.containsLatLng) {
1976
+ // Polygon containsLatLng - method to determine if a latLng is within a polygon
1977
+ google.maps.Polygon.prototype.containsLatLng = function(latLng) {
1978
+ // Exclude points outside of bounds as there is no way they are in the poly
1979
+ var bounds = this.getBounds();
1980
+
1981
+ if (bounds !== null && !bounds.contains(latLng)) {
1982
+ return false;
1983
+ }
1984
+
1985
+ // Raycast point in polygon method
1986
+ var inPoly = false;
1987
+
1988
+ var numPaths = this.getPaths().getLength();
1989
+ for (var p = 0; p < numPaths; p++) {
1990
+ var path = this.getPaths().getAt(p);
1991
+ var numPoints = path.getLength();
1992
+ var j = numPoints - 1;
1993
+
1994
+ for (var i = 0; i < numPoints; i++) {
1995
+ var vertex1 = path.getAt(i);
1996
+ var vertex2 = path.getAt(j);
1997
+
1998
+ if (vertex1.lng() < latLng.lng() && vertex2.lng() >= latLng.lng() || vertex2.lng() < latLng.lng() && vertex1.lng() >= latLng.lng()) {
1999
+ if (vertex1.lat() + (latLng.lng() - vertex1.lng()) / (vertex2.lng() - vertex1.lng()) * (vertex2.lat() - vertex1.lat()) < latLng.lat()) {
2000
+ inPoly = !inPoly;
2001
+ }
2002
+ }
2003
+
2004
+ j = i;
2005
+ }
2006
+ }
2007
+
2008
+ return inPoly;
2009
+ };
2010
+ }
2011
+
2012
+ google.maps.LatLngBounds.prototype.containsLatLng = function(latLng) {
2013
+ return this.contains(latLng);
2014
+ };
2015
+
2016
+ google.maps.Marker.prototype.setFences = function(fences) {
2017
+ this.fences = fences;
2018
+ };
2019
+
2020
+ google.maps.Marker.prototype.addFence = function(fence) {
2021
+ this.fences.push(fence);
2022
+ };
2023
+
2024
+ google.maps.Marker.prototype.getId = function() {
2025
+ return this['__gm_id'];
2026
+ };
2027
+
2028
+ //==========================
2029
+ // Array indexOf
2030
+ // https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf
2031
+ if (!Array.prototype.indexOf) {
2032
+ Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
2033
+ "use strict";
2034
+ if (this == null) {
2035
+ throw new TypeError();
2036
+ }
2037
+ var t = Object(this);
2038
+ var len = t.length >>> 0;
2039
+ if (len === 0) {
2040
+ return -1;
2041
+ }
2042
+ var n = 0;
2043
+ if (arguments.length > 1) {
2044
+ n = Number(arguments[1]);
2045
+ if (n != n) { // shortcut for verifying if it's NaN
2046
+ n = 0;
2047
+ } else if (n != 0 && n != Infinity && n != -Infinity) {
2048
+ n = (n > 0 || -1) * Math.floor(Math.abs(n));
2049
+ }
2050
+ }
2051
+ if (n >= len) {
2052
+ return -1;
2053
+ }
2054
+ var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
2055
+ for (; k < len; k++) {
2056
+ if (k in t && t[k] === searchElement) {
2057
+ return k;
2058
+ }
2059
+ }
2060
+ return -1;
2061
+ }
2062
+ }
2063
+
2064
+ return GMaps;
2065
+ }));