active_frontend 1.0.0

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