jquery-gmap3-rails 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +46 -0
- data/Rakefile +2 -0
- data/jquery-gmap3-rails.gemspec +20 -0
- data/lib/generators/jquery/gmap3/install/install_generator.rb +41 -0
- data/lib/jquery-gmap3-rails.rb +1 -0
- data/lib/jquery/gmap3/rails.rb +13 -0
- data/lib/jquery/gmap3/rails/engine.rb +8 -0
- data/lib/jquery/gmap3/rails/version.rb +8 -0
- data/vendor/assets/javascripts/gmap3.js +2222 -0
- data/vendor/assets/javascripts/gmap3.min.js +39 -0
- metadata +70 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Erick Dennis
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# Jquery::Gmap3::Rails
|
2
|
+
|
3
|
+
This gem provides your Rails 3 application with Jean-Baptiste DEMONTE's [GMAP3 Plugin for JQuery](http://gmap3.net/).
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'jquery-gmap3-rails'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install jquery-gmap3-rails
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
If you're using rails 3.0 or are using rails 3.1 and above and have the asset pipeline disabled you can also use this
|
22
|
+
generator to install the static files:
|
23
|
+
|
24
|
+
$ rails g jquery:gmap3:install
|
25
|
+
|
26
|
+
Once you have the libraries installed you will first need to include the google maps API in your application layout:
|
27
|
+
|
28
|
+
javascript_include_tag "http://maps.googleapis.com/maps/api/js?sensor=true"
|
29
|
+
|
30
|
+
Then you have to load the GMAP3 library by adding the following line to your app/assets/javascripts/application.js:
|
31
|
+
|
32
|
+
//= require gmap3
|
33
|
+
|
34
|
+
After that it's as simple as calling the gmap3() method on the div that you want to display the map in:
|
35
|
+
|
36
|
+
$("#map_canvas").gmap3();
|
37
|
+
|
38
|
+
For further details on the usage of GMAP3 please see the [documentation](http://gmap3.net/documentation.html).
|
39
|
+
|
40
|
+
## Contributing
|
41
|
+
|
42
|
+
1. Fork it
|
43
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
44
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
45
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
46
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/jquery/gmap3/rails/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Erick Dennis"]
|
6
|
+
gem.email = ["erick.dennis@gmail.com"]
|
7
|
+
gem.description = "This gem provides your Rails 3 application with the GMAP3 Plugin for JQuery."
|
8
|
+
gem.summary = "Use GMAP3 Plugin for JQuery with Rails 3"
|
9
|
+
gem.homepage = "http://github.com/erickd/jquery-gmap3-rails"
|
10
|
+
|
11
|
+
# todo: add the correct jquery-rails version
|
12
|
+
gem.add_dependency "jquery-rails", ">= 1.0"
|
13
|
+
|
14
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
15
|
+
gem.files = `git ls-files`.split("\n")
|
16
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
gem.name = "jquery-gmap3-rails"
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
gem.version = Jquery::Gmap3::Rails::VERSION
|
20
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'rails'
|
2
|
+
|
3
|
+
# Supply generator for Rails 3.0.x or if asset pipeline is not enabled
|
4
|
+
if ::Rails.version < "3.1" || !::Rails.application.config.assets.enabled
|
5
|
+
module Jquery
|
6
|
+
module Gmap3
|
7
|
+
module Generators
|
8
|
+
class InstallGenerator < ::Rails::Generators::Base
|
9
|
+
|
10
|
+
desc "This generator installs the GMAP3 Plugin for JQuery #{Jquery::Gmap3::Rails::JQUERY_GMAP3_VERSION}"
|
11
|
+
source_root File.expand_path('../../../../../vendor/assets/javascripts', __FILE__)
|
12
|
+
|
13
|
+
def copy_gmap3
|
14
|
+
say_status("copying", "GMAP3 Plugin for jQuery (#{Jquery::Gmap3::Rails::JQUERY_GMAP3_VERSION})", :green)
|
15
|
+
copy_file "gmap3.js", "public/javascripts/gmap3.js"
|
16
|
+
copy_file "gmap3.min.js", "public/javascripts/gmap3.min.js"
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
else
|
24
|
+
module Jquery
|
25
|
+
module Gmap3
|
26
|
+
module Generators
|
27
|
+
class InstallGenerator < ::Rails::Generators::Base
|
28
|
+
desc "Show instructions so people will know what to do when mistakenly using generator for Rails 3.1 apps"
|
29
|
+
|
30
|
+
def do_nothing
|
31
|
+
say_status("deprecated", "You are using Rails #{::Rails.version} with the asset pipeline enabled, so this generator is not needed.")
|
32
|
+
say_status("", "The necessary files are already in your asset pipeline.")
|
33
|
+
say_status("", "Just add `//= require gmap3` to your app/assets/javascripts/application.js")
|
34
|
+
say_status("", "If you upgraded your app from Rails 3.0 and still have gmap3.js in your javascripts, be sure to remove it.")
|
35
|
+
say_status("", "If you do not want the asset pipeline enabled, you may turn it off in application.rb and re-run this generator.")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require "jquery/gmap3/rails"
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "jquery/gmap3/rails/version"
|
2
|
+
|
3
|
+
if defined? Rails && Rails::VERSION::MAJOR == 3 && Rails::VERSION::MINOR >= 1
|
4
|
+
require "jquery/gmap3/rails/engine"
|
5
|
+
end
|
6
|
+
|
7
|
+
module Jquery
|
8
|
+
module Gmap3
|
9
|
+
module Rails
|
10
|
+
# Your code goes here...
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,2222 @@
|
|
1
|
+
/*
|
2
|
+
* GMAP3 Plugin for JQuery
|
3
|
+
* Version : 4.1
|
4
|
+
* Date : 2011-11-18
|
5
|
+
* Licence : GPL v3 : http://www.gnu.org/licenses/gpl.html
|
6
|
+
* Author : DEMONTE Jean-Baptiste
|
7
|
+
* Contact : jbdemonte@gmail.com
|
8
|
+
* Web site : http://gmap3.net
|
9
|
+
*
|
10
|
+
* Copyright (c) 2010-2011 Jean-Baptiste DEMONTE
|
11
|
+
* All rights reserved.
|
12
|
+
*
|
13
|
+
* Redistribution and use in source and binary forms, with or without
|
14
|
+
* modification, are permitted provided that the following conditions are met:
|
15
|
+
*
|
16
|
+
* - Redistributions of source code must retain the above copyright
|
17
|
+
* notice, this list of conditions and the following disclaimer.
|
18
|
+
* - Redistributions in binary form must reproduce the above
|
19
|
+
* copyright notice, this list of conditions and the following
|
20
|
+
* disclaimer in the documentation and/or other materials provided
|
21
|
+
* with the distribution.
|
22
|
+
* - Neither the name of the author nor the names of its contributors
|
23
|
+
* may be used to endorse or promote products derived from this
|
24
|
+
* software without specific prior written permission.
|
25
|
+
*
|
26
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
27
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
28
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
29
|
+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
30
|
+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
31
|
+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
32
|
+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
33
|
+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
34
|
+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
35
|
+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
36
|
+
* POSSIBILITY OF SUCH DAMAGE.
|
37
|
+
*/
|
38
|
+
|
39
|
+
(function ($) {
|
40
|
+
|
41
|
+
/***************************************************************************/
|
42
|
+
/* STACK */
|
43
|
+
/***************************************************************************/
|
44
|
+
function Stack (){
|
45
|
+
var st = [];
|
46
|
+
this.empty = function (){
|
47
|
+
for(var i = 0; i < st.length; i++){
|
48
|
+
if (st[i]){
|
49
|
+
return false
|
50
|
+
}
|
51
|
+
}
|
52
|
+
return true;
|
53
|
+
}
|
54
|
+
this.add = function(v){
|
55
|
+
st.push(v);
|
56
|
+
}
|
57
|
+
this.addNext = function ( v){
|
58
|
+
var t=[], i, k = 0;
|
59
|
+
for(i = 0; i < st.length; i++){
|
60
|
+
if (!st[i]){
|
61
|
+
continue;
|
62
|
+
}
|
63
|
+
if (k == 1) {
|
64
|
+
t.push(v);
|
65
|
+
}
|
66
|
+
t.push(st[i]);
|
67
|
+
k++;
|
68
|
+
}
|
69
|
+
if (k < 2) {
|
70
|
+
t.push(v);
|
71
|
+
}
|
72
|
+
st = t;
|
73
|
+
}
|
74
|
+
this.get = function (){
|
75
|
+
for(var i = 0; i < st.length; i++){
|
76
|
+
if (st[i]) {
|
77
|
+
return st[i];
|
78
|
+
}
|
79
|
+
}
|
80
|
+
return false;
|
81
|
+
}
|
82
|
+
this.ack = function (){
|
83
|
+
for(var i = 0; i < st.length; i++){
|
84
|
+
if (st[i]) {
|
85
|
+
delete st[i];
|
86
|
+
break;
|
87
|
+
}
|
88
|
+
}
|
89
|
+
if (this.empty()){
|
90
|
+
st = [];
|
91
|
+
}
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
95
|
+
/***************************************************************************/
|
96
|
+
/* STORE */
|
97
|
+
/***************************************************************************/
|
98
|
+
function Store(){
|
99
|
+
var store = {};
|
100
|
+
|
101
|
+
/**
|
102
|
+
* add a mixed to the store
|
103
|
+
**/
|
104
|
+
this.add = function(name, obj, todo){
|
105
|
+
name = name.toLowerCase();
|
106
|
+
if (!store[name]){
|
107
|
+
store[name] = [];
|
108
|
+
}
|
109
|
+
store[name].push({obj:obj, tag:ival(todo, 'tag')});
|
110
|
+
return name + '-' + (store[name].length-1);
|
111
|
+
}
|
112
|
+
|
113
|
+
/**
|
114
|
+
* return a stored mixed
|
115
|
+
**/
|
116
|
+
this.get = function(name, last, tag){
|
117
|
+
var i, idx, add;
|
118
|
+
name = name.toLowerCase();
|
119
|
+
if (!store[name] || !store[name].length){
|
120
|
+
return null;
|
121
|
+
}
|
122
|
+
idx = last ? store[name].length : -1;
|
123
|
+
add = last ? -1 : 1;
|
124
|
+
for(i=0; i<store[name].length; i++){
|
125
|
+
idx += add;
|
126
|
+
if (store[name][idx]){
|
127
|
+
if (tag !== undefined) {
|
128
|
+
if ( (store[name][idx].tag === undefined) || ($.inArray(store[name][idx].tag, tag) < 0) ){
|
129
|
+
continue;
|
130
|
+
}
|
131
|
+
}
|
132
|
+
return store[name][idx].obj;
|
133
|
+
}
|
134
|
+
}
|
135
|
+
return null;
|
136
|
+
}
|
137
|
+
|
138
|
+
/**
|
139
|
+
* return all stored mixed
|
140
|
+
**/
|
141
|
+
this.all = function(name, tag){
|
142
|
+
var i, result = [];
|
143
|
+
name = name.toLowerCase();
|
144
|
+
if (!store[name] || !store[name].length){
|
145
|
+
return result;
|
146
|
+
}
|
147
|
+
for(i=0; i<store[name].length; i++){
|
148
|
+
if (!store[name][i]){
|
149
|
+
continue;
|
150
|
+
}
|
151
|
+
if ( (tag !== undefined) && ( (store[name][i].tag === undefined) || ($.inArray(store[name][i].tag, tag) < 0) ) ){
|
152
|
+
continue;
|
153
|
+
}
|
154
|
+
result.push(store[name][i].obj);
|
155
|
+
}
|
156
|
+
return result;
|
157
|
+
}
|
158
|
+
|
159
|
+
/**
|
160
|
+
* return all storation groups
|
161
|
+
**/
|
162
|
+
this.names = function(){
|
163
|
+
var name, result = [];
|
164
|
+
for(name in store){
|
165
|
+
result.push(name);
|
166
|
+
}
|
167
|
+
return result;
|
168
|
+
}
|
169
|
+
|
170
|
+
/**
|
171
|
+
* return an object from its reference
|
172
|
+
**/
|
173
|
+
this.refToObj = function(ref){
|
174
|
+
ref = ref.split('-'); // name - idx
|
175
|
+
if ((ref.length == 2) && store[ref[0]] && store[ref[0]][ref[1]]){
|
176
|
+
return store[ref[0]][ref[1]].obj;
|
177
|
+
}
|
178
|
+
return null;
|
179
|
+
}
|
180
|
+
|
181
|
+
/**
|
182
|
+
* remove one object from the store
|
183
|
+
**/
|
184
|
+
this.rm = function(name, tag, pop){
|
185
|
+
var idx, i, tmp;
|
186
|
+
name = name.toLowerCase();
|
187
|
+
if (!store[name]) {
|
188
|
+
return false;
|
189
|
+
}
|
190
|
+
if (tag !== undefined){
|
191
|
+
if (pop){
|
192
|
+
for(idx = store[name].length - 1; idx >= 0; idx--){
|
193
|
+
if ( (store[name][idx] !== undefined) && (store[name][idx].tag !== undefined) && ($.inArray(store[name][idx].tag, tag) >= 0) ){
|
194
|
+
break;
|
195
|
+
}
|
196
|
+
}
|
197
|
+
} else {
|
198
|
+
for(idx = 0; idx < store[name].length; idx++){
|
199
|
+
if ( (store[name][idx] !== undefined) && (store[name][idx].tag !== undefined) && ($.inArray(store[name][idx].tag, tag) >= 0) ){
|
200
|
+
break;
|
201
|
+
}
|
202
|
+
}
|
203
|
+
}
|
204
|
+
} else {
|
205
|
+
idx = pop ? store[name].length - 1 : 0;
|
206
|
+
}
|
207
|
+
if ( !(idx in store[name]) ) {
|
208
|
+
return false;
|
209
|
+
}
|
210
|
+
// Google maps element
|
211
|
+
if (typeof(store[name][idx].obj.setMap) === 'function') {
|
212
|
+
store[name][idx].obj.setMap(null);
|
213
|
+
}
|
214
|
+
// jQuery
|
215
|
+
if (typeof(store[name][idx].obj.remove) === 'function') {
|
216
|
+
store[name][idx].obj.remove();
|
217
|
+
}
|
218
|
+
// internal (cluster)
|
219
|
+
if (typeof(store[name][idx].obj.free) === 'function') {
|
220
|
+
store[name][idx].obj.free();
|
221
|
+
}
|
222
|
+
delete store[name][idx].obj;
|
223
|
+
if (tag !== undefined){
|
224
|
+
tmp = [];
|
225
|
+
for(i=0; i<store[name].length; i++){
|
226
|
+
if (i !== idx){
|
227
|
+
tmp.push(store[name][i]);
|
228
|
+
}
|
229
|
+
}
|
230
|
+
store[name] = tmp;
|
231
|
+
} else {
|
232
|
+
if (pop) {
|
233
|
+
store[name].pop();
|
234
|
+
} else {
|
235
|
+
store[name].shift();
|
236
|
+
}
|
237
|
+
}
|
238
|
+
return true;
|
239
|
+
}
|
240
|
+
|
241
|
+
/**
|
242
|
+
* remove objects from the store
|
243
|
+
**/
|
244
|
+
this.clear = function(list, last, first, tag){
|
245
|
+
var k, i, name;
|
246
|
+
if (!list || !list.length){
|
247
|
+
list = [];
|
248
|
+
for(k in store){
|
249
|
+
list.push(k);
|
250
|
+
}
|
251
|
+
} else {
|
252
|
+
list = array(list);
|
253
|
+
}
|
254
|
+
for(i=0; i<list.length; i++){
|
255
|
+
if (list[i]){
|
256
|
+
name = list[i].toLowerCase();
|
257
|
+
if (!store[name]){
|
258
|
+
continue;
|
259
|
+
}
|
260
|
+
if (last){
|
261
|
+
this.rm(name, tag, true);
|
262
|
+
} else if (first){
|
263
|
+
this.rm(name, tag, false);
|
264
|
+
} else {
|
265
|
+
// all
|
266
|
+
while (this.rm(name, tag, false));
|
267
|
+
}
|
268
|
+
}
|
269
|
+
}
|
270
|
+
}
|
271
|
+
}
|
272
|
+
|
273
|
+
/***************************************************************************/
|
274
|
+
/* CLUSTERER */
|
275
|
+
/***************************************************************************/
|
276
|
+
|
277
|
+
function Clusterer(){
|
278
|
+
var markers = [], events=[], stored=[], latest=[], redrawing = false, redraw;
|
279
|
+
|
280
|
+
this.events = function(){
|
281
|
+
for(var i=0; i<arguments.length; i++){
|
282
|
+
events.push(arguments[i]);
|
283
|
+
}
|
284
|
+
}
|
285
|
+
|
286
|
+
this.startRedraw = function(){
|
287
|
+
if (!redrawing){
|
288
|
+
redrawing = true;
|
289
|
+
return true;
|
290
|
+
}
|
291
|
+
return false;
|
292
|
+
}
|
293
|
+
|
294
|
+
this.endRedraw = function(){
|
295
|
+
redrawing = false;
|
296
|
+
}
|
297
|
+
|
298
|
+
this.redraw = function(){
|
299
|
+
var i, args = [], that = this;
|
300
|
+
for(i=0; i<arguments.length; i++){
|
301
|
+
args.push(arguments[i]);
|
302
|
+
}
|
303
|
+
if (this.startRedraw){
|
304
|
+
redraw.apply(that, args);
|
305
|
+
this.endRedraw();
|
306
|
+
} else {
|
307
|
+
setTimeout(function(){
|
308
|
+
that.redraw.apply(that, args);
|
309
|
+
},
|
310
|
+
50
|
311
|
+
);
|
312
|
+
}
|
313
|
+
};
|
314
|
+
|
315
|
+
this.setRedraw = function(fnc){
|
316
|
+
redraw = fnc;
|
317
|
+
}
|
318
|
+
|
319
|
+
this.store = function(data, obj, shadow){
|
320
|
+
stored.push({data:data, obj:obj, shadow:shadow});
|
321
|
+
}
|
322
|
+
|
323
|
+
this.free = function(){
|
324
|
+
for(var i = 0; i < events.length; i++){
|
325
|
+
google.maps.event.removeListener(events[i]);
|
326
|
+
}
|
327
|
+
events=[];
|
328
|
+
this.freeAll();
|
329
|
+
}
|
330
|
+
|
331
|
+
this.freeIndex = function(i){
|
332
|
+
if (typeof(stored[i].obj.setMap) === 'function') {
|
333
|
+
stored[i].obj.setMap(null);
|
334
|
+
}
|
335
|
+
if (typeof(stored[i].obj.remove) === 'function') {
|
336
|
+
stored[i].obj.remove();
|
337
|
+
}
|
338
|
+
if (stored[i].shadow){ // only overlays has shadow
|
339
|
+
if (typeof(stored[i].shadow.remove) === 'function') {
|
340
|
+
stored[i].obj.remove();
|
341
|
+
}
|
342
|
+
if (typeof(stored[i].shadow.setMap) === 'function') {
|
343
|
+
stored[i].shadow.setMap(null);
|
344
|
+
}
|
345
|
+
delete stored[i].shadow;
|
346
|
+
}
|
347
|
+
delete stored[i].obj;
|
348
|
+
delete stored[i].data;
|
349
|
+
delete stored[i];
|
350
|
+
}
|
351
|
+
|
352
|
+
this.freeAll = function(){
|
353
|
+
var i;
|
354
|
+
for(i = 0; i < stored.length; i++){
|
355
|
+
if (stored[i]) {
|
356
|
+
this.freeIndex(i);
|
357
|
+
}
|
358
|
+
}
|
359
|
+
stored = [];
|
360
|
+
}
|
361
|
+
|
362
|
+
this.freeDiff = function(clusters){
|
363
|
+
var i, j, same = {}, idx = [];
|
364
|
+
for(i=0; i<clusters.length; i++){
|
365
|
+
idx.push( clusters[i].idx.join('-') );
|
366
|
+
}
|
367
|
+
for(i = 0; i < stored.length; i++){
|
368
|
+
if (!stored[i]) {
|
369
|
+
continue;
|
370
|
+
}
|
371
|
+
j = $.inArray(stored[i].data.idx.join('-'), idx);
|
372
|
+
if (j >= 0){
|
373
|
+
same[j] = true;
|
374
|
+
} else {
|
375
|
+
this.freeIndex(i);
|
376
|
+
}
|
377
|
+
}
|
378
|
+
return same;
|
379
|
+
}
|
380
|
+
|
381
|
+
this.add = function(latLng, marker){
|
382
|
+
markers.push({latLng:latLng, marker:marker});
|
383
|
+
}
|
384
|
+
|
385
|
+
this.get = function(i){
|
386
|
+
return markers[i];
|
387
|
+
}
|
388
|
+
|
389
|
+
this.clusters = function(map, radius, maxZoom, force){
|
390
|
+
var proj = map.getProjection(),
|
391
|
+
nwP = proj.fromLatLngToPoint(
|
392
|
+
new google.maps.LatLng(
|
393
|
+
map.getBounds().getNorthEast().lat(),
|
394
|
+
map.getBounds().getSouthWest().lng()
|
395
|
+
)
|
396
|
+
),
|
397
|
+
i, j, j2, p, x, y, k, k2,
|
398
|
+
z = map.getZoom(),
|
399
|
+
pos = {},
|
400
|
+
saved = {},
|
401
|
+
unik = {},
|
402
|
+
clusters = [],
|
403
|
+
cluster,
|
404
|
+
chk,
|
405
|
+
lat, lng, keys, cnt,
|
406
|
+
bounds = map.getBounds(),
|
407
|
+
noClusters = maxZoom && (maxZoom <= map.getZoom()),
|
408
|
+
chkContain = map.getZoom() > 2;
|
409
|
+
|
410
|
+
cnt = 0;
|
411
|
+
keys = {};
|
412
|
+
for(i = 0; i < markers.length; i++){
|
413
|
+
if (chkContain && !bounds.contains(markers[i].latLng)){
|
414
|
+
continue;
|
415
|
+
}
|
416
|
+
p = proj.fromLatLngToPoint(markers[i].latLng);
|
417
|
+
pos[i] = [
|
418
|
+
Math.floor((p.x - nwP.x) * Math.pow(2, z)),
|
419
|
+
Math.floor((p.y - nwP.y) * Math.pow(2, z))
|
420
|
+
];
|
421
|
+
keys[i] = true;
|
422
|
+
cnt++;
|
423
|
+
}
|
424
|
+
// check if visible markers have changed
|
425
|
+
if (!force && !noClusters){
|
426
|
+
for(k = 0; k < latest.length; k++){
|
427
|
+
if( k in keys ){
|
428
|
+
cnt--;
|
429
|
+
} else {
|
430
|
+
break;
|
431
|
+
}
|
432
|
+
}
|
433
|
+
if (!cnt){
|
434
|
+
return false; // no change
|
435
|
+
}
|
436
|
+
}
|
437
|
+
|
438
|
+
// save current keys to check later if an update has been done
|
439
|
+
latest = keys;
|
440
|
+
|
441
|
+
keys = [];
|
442
|
+
for(i in pos){
|
443
|
+
x = pos[i][0];
|
444
|
+
y = pos[i][1];
|
445
|
+
if ( !(x in saved) ){
|
446
|
+
saved[x] = {};
|
447
|
+
}
|
448
|
+
if (!( y in saved[x]) ) {
|
449
|
+
saved[x][y] = i;
|
450
|
+
unik[i] = {};
|
451
|
+
keys.push(i);
|
452
|
+
}
|
453
|
+
unik[ saved[x][y] ][i] = true;
|
454
|
+
}
|
455
|
+
radius = Math.pow(radius, 2);
|
456
|
+
delete(saved);
|
457
|
+
|
458
|
+
k = 0;
|
459
|
+
while(1){
|
460
|
+
while((k <keys.length) && !(keys[k] in unik)){
|
461
|
+
k++;
|
462
|
+
}
|
463
|
+
if (k == keys.length){
|
464
|
+
break;
|
465
|
+
}
|
466
|
+
i = keys[k];
|
467
|
+
lat = pos[i][0];
|
468
|
+
lng = pos[i][1];
|
469
|
+
saved = null;
|
470
|
+
|
471
|
+
|
472
|
+
if (noClusters){
|
473
|
+
saved = {lat:lat, lng:lng, idx:[i]};
|
474
|
+
} else {
|
475
|
+
do{
|
476
|
+
cluster = {lat:0, lng:0, idx:[]};
|
477
|
+
for(k2 = k; k2<keys.length; k2++){
|
478
|
+
if (!(keys[k2] in unik)){
|
479
|
+
continue;
|
480
|
+
}
|
481
|
+
j = keys[k2];
|
482
|
+
if ( Math.pow(lat - pos[j][0], 2) + Math.pow(lng-pos[j][1], 2) <= radius ){
|
483
|
+
for(j2 in unik[j]){
|
484
|
+
cluster.lat += markers[j2].latLng.lat();
|
485
|
+
cluster.lng += markers[j2].latLng.lng();
|
486
|
+
cluster.idx.push(j2);
|
487
|
+
}
|
488
|
+
}
|
489
|
+
}
|
490
|
+
cluster.lat /= cluster.idx.length;
|
491
|
+
cluster.lng /= cluster.idx.length;
|
492
|
+
if (!saved){
|
493
|
+
chk = cluster.idx.length > 1;
|
494
|
+
saved = cluster;
|
495
|
+
} else {
|
496
|
+
chk = cluster.idx.length > saved.idx.length;
|
497
|
+
if (chk){
|
498
|
+
saved = cluster;
|
499
|
+
}
|
500
|
+
}
|
501
|
+
if (chk){
|
502
|
+
p = proj.fromLatLngToPoint( new google.maps.LatLng(saved.lat, saved.lng) );
|
503
|
+
lat = Math.floor((p.x - nwP.x) * Math.pow(2, z));
|
504
|
+
lng = Math.floor((p.y - nwP.y) * Math.pow(2, z));
|
505
|
+
}
|
506
|
+
} while(chk);
|
507
|
+
}
|
508
|
+
|
509
|
+
for(k2 = 0; k2 < saved.idx.length; k2++){
|
510
|
+
if (saved.idx[k2] in unik){
|
511
|
+
delete(unik[saved.idx[k2]]);
|
512
|
+
}
|
513
|
+
}
|
514
|
+
clusters.push(saved);
|
515
|
+
}
|
516
|
+
return clusters;
|
517
|
+
}
|
518
|
+
|
519
|
+
this.getBounds = function(){
|
520
|
+
var i, bounds = new google.maps.LatLngBounds();
|
521
|
+
for(i=0; i<markers.length; i++){
|
522
|
+
bounds.extend(markers[i].latLng);
|
523
|
+
}
|
524
|
+
return bounds;
|
525
|
+
}
|
526
|
+
}
|
527
|
+
|
528
|
+
/***************************************************************************/
|
529
|
+
/* GMAP3 GLOBALS */
|
530
|
+
/***************************************************************************/
|
531
|
+
|
532
|
+
var _default = {
|
533
|
+
verbose:false,
|
534
|
+
queryLimit:{
|
535
|
+
attempt:5,
|
536
|
+
delay:250, // setTimeout(..., delay + random);
|
537
|
+
random:250
|
538
|
+
},
|
539
|
+
init:{
|
540
|
+
mapTypeId : google.maps.MapTypeId.ROADMAP,
|
541
|
+
center:[46.578498,2.457275],
|
542
|
+
zoom: 2
|
543
|
+
},
|
544
|
+
classes:{
|
545
|
+
Map : google.maps.Map,
|
546
|
+
Marker : google.maps.Marker,
|
547
|
+
InfoWindow : google.maps.InfoWindow,
|
548
|
+
Circle : google.maps.Circle,
|
549
|
+
Rectangle : google.maps.Rectangle,
|
550
|
+
OverlayView : google.maps.OverlayView,
|
551
|
+
StreetViewPanorama: google.maps.StreetViewPanorama,
|
552
|
+
KmlLayer : google.maps.KmlLayer,
|
553
|
+
TrafficLayer : google.maps.TrafficLayer,
|
554
|
+
BicyclingLayer : google.maps.BicyclingLayer,
|
555
|
+
GroundOverlay : google.maps.GroundOverlay,
|
556
|
+
StyledMapType : google.maps.StyledMapType
|
557
|
+
}
|
558
|
+
},
|
559
|
+
_properties = ['events','onces','options','apply', 'callback', 'data', 'tag'],
|
560
|
+
_noInit = ['init', 'geolatlng', 'getlatlng', 'getroute', 'getelevation', 'getdistance', 'addstyledmap', 'setdefault', 'destroy'],
|
561
|
+
_directs = ['get'],
|
562
|
+
geocoder = directionsService = elevationService = maxZoomService = distanceMatrixService = null;
|
563
|
+
|
564
|
+
function setDefault(values){
|
565
|
+
for(var k in values){
|
566
|
+
if (typeof(_default[k]) === 'object'){
|
567
|
+
_default[k] = $.extend({}, _default[k], values[k]);
|
568
|
+
} else {
|
569
|
+
_default[k] = values[k];
|
570
|
+
}
|
571
|
+
}
|
572
|
+
}
|
573
|
+
|
574
|
+
function autoInit(iname){
|
575
|
+
if (!iname){
|
576
|
+
return true;
|
577
|
+
}
|
578
|
+
for(var i = 0; i < _noInit.length; i++){
|
579
|
+
if (_noInit[i] === iname) {
|
580
|
+
return false;
|
581
|
+
}
|
582
|
+
}
|
583
|
+
return true;
|
584
|
+
}
|
585
|
+
|
586
|
+
|
587
|
+
/**
|
588
|
+
* return true if action has to be executed directly
|
589
|
+
**/
|
590
|
+
function isDirect (todo){
|
591
|
+
var action = ival(todo, 'action');
|
592
|
+
for(var i = 0; i < _directs.length; i++){
|
593
|
+
if (_directs[i] === action) {
|
594
|
+
return true;
|
595
|
+
}
|
596
|
+
}
|
597
|
+
return false;
|
598
|
+
}
|
599
|
+
|
600
|
+
//-----------------------------------------------------------------------//
|
601
|
+
// Objects tools
|
602
|
+
//-----------------------------------------------------------------------//
|
603
|
+
|
604
|
+
/**
|
605
|
+
* return the real key by an insensitive seach
|
606
|
+
**/
|
607
|
+
function ikey (object, key){
|
608
|
+
if (key.toLowerCase){
|
609
|
+
key = key.toLowerCase();
|
610
|
+
for(var k in object){
|
611
|
+
if (k.toLowerCase && (k.toLowerCase() == key)) {
|
612
|
+
return k;
|
613
|
+
}
|
614
|
+
}
|
615
|
+
}
|
616
|
+
return false;
|
617
|
+
}
|
618
|
+
|
619
|
+
/**
|
620
|
+
* return the value of real key by an insensitive seach
|
621
|
+
**/
|
622
|
+
function ival (object, key, def){
|
623
|
+
var k = ikey(object, key);
|
624
|
+
return k ? object[k] : def;
|
625
|
+
}
|
626
|
+
|
627
|
+
/**
|
628
|
+
* return true if at least one key is set in object
|
629
|
+
* nb: keys in lowercase
|
630
|
+
**/
|
631
|
+
function hasKey (object, keys){
|
632
|
+
var n, k;
|
633
|
+
if (!object || !keys) {
|
634
|
+
return false;
|
635
|
+
}
|
636
|
+
keys = array(keys);
|
637
|
+
for(n in object){
|
638
|
+
if (n.toLowerCase){
|
639
|
+
n = n.toLowerCase();
|
640
|
+
for(k in keys){
|
641
|
+
if (n == keys[k]) {
|
642
|
+
return true;
|
643
|
+
}
|
644
|
+
}
|
645
|
+
}
|
646
|
+
}
|
647
|
+
return false;
|
648
|
+
}
|
649
|
+
|
650
|
+
/**
|
651
|
+
* return a standard object
|
652
|
+
* nb: include in lowercase
|
653
|
+
**/
|
654
|
+
function extractObject (todo, include, result/* = {} */){
|
655
|
+
if (hasKey(todo, _properties) || hasKey(todo, include)){ // #1 classical object definition
|
656
|
+
var i, k;
|
657
|
+
// get defined properties values from todo
|
658
|
+
for(i=0; i<_properties.length; i++){
|
659
|
+
k = ikey(todo, _properties[i]);
|
660
|
+
result[ _properties[i] ] = k ? todo[k] : {};
|
661
|
+
}
|
662
|
+
if (include && include.length){
|
663
|
+
for(i=0; i<include.length; i++){
|
664
|
+
if(k = ikey(todo, include[i])){
|
665
|
+
result[ include[i] ] = todo[k];
|
666
|
+
}
|
667
|
+
}
|
668
|
+
}
|
669
|
+
return result;
|
670
|
+
} else { // #2 simplified object (all excepted "action" are options properties)
|
671
|
+
result.options= {};
|
672
|
+
for(k in todo){
|
673
|
+
if (k !== 'action'){
|
674
|
+
result.options[k] = todo[k];
|
675
|
+
}
|
676
|
+
}
|
677
|
+
return result;
|
678
|
+
}
|
679
|
+
}
|
680
|
+
|
681
|
+
/**
|
682
|
+
* identify object from object list or parameters list : [ objectName:{data} ] or [ otherObject:{}, ] or [ object properties ]
|
683
|
+
* nb: include, exclude in lowercase
|
684
|
+
**/
|
685
|
+
function getObject(name, todo, include, exclude){
|
686
|
+
var iname = ikey(todo, name),
|
687
|
+
i, result = {}, keys=['map'];
|
688
|
+
// include callback from high level
|
689
|
+
result['callback'] = ival(todo, 'callback');
|
690
|
+
include = array(include);
|
691
|
+
exclude = array(exclude);
|
692
|
+
if (iname) {
|
693
|
+
return extractObject(todo[iname], include, result);
|
694
|
+
}
|
695
|
+
if (exclude && exclude.length){
|
696
|
+
for(i=0; i<exclude.length; i++) {
|
697
|
+
keys.push(exclude[i]);
|
698
|
+
}
|
699
|
+
}
|
700
|
+
if (!hasKey(todo, keys)){
|
701
|
+
result = extractObject(todo, include, result);
|
702
|
+
}
|
703
|
+
// initialize missing properties
|
704
|
+
for(i=0; i<_properties.length; i++){
|
705
|
+
if (_properties[i] in result){
|
706
|
+
continue;
|
707
|
+
}
|
708
|
+
result[ _properties[i] ] = {};
|
709
|
+
}
|
710
|
+
return result;
|
711
|
+
}
|
712
|
+
|
713
|
+
//-----------------------------------------------------------------------//
|
714
|
+
// Service tools
|
715
|
+
//-----------------------------------------------------------------------//
|
716
|
+
|
717
|
+
function getGeocoder(){
|
718
|
+
if (!geocoder) {
|
719
|
+
geocoder = new google.maps.Geocoder();
|
720
|
+
}
|
721
|
+
return geocoder;
|
722
|
+
}
|
723
|
+
|
724
|
+
function getDirectionsService(){
|
725
|
+
if (!directionsService) {
|
726
|
+
directionsService = new google.maps.DirectionsService();
|
727
|
+
}
|
728
|
+
return directionsService;
|
729
|
+
}
|
730
|
+
|
731
|
+
function getElevationService(){
|
732
|
+
if (!elevationService) {
|
733
|
+
elevationService = new google.maps.ElevationService();
|
734
|
+
}
|
735
|
+
return elevationService;
|
736
|
+
}
|
737
|
+
|
738
|
+
function getMaxZoomService(){
|
739
|
+
if (!maxZoomService) {
|
740
|
+
maxZoomService = new google.maps.MaxZoomService();
|
741
|
+
}
|
742
|
+
return maxZoomService;
|
743
|
+
}
|
744
|
+
|
745
|
+
function getDistanceMatrixService(){
|
746
|
+
if (!distanceMatrixService) {
|
747
|
+
distanceMatrixService = new google.maps.DistanceMatrixService();
|
748
|
+
}
|
749
|
+
return distanceMatrixService;
|
750
|
+
}
|
751
|
+
|
752
|
+
//-----------------------------------------------------------------------//
|
753
|
+
// Unit tools
|
754
|
+
//-----------------------------------------------------------------------//
|
755
|
+
|
756
|
+
/**
|
757
|
+
* return true if mixed is usable as number
|
758
|
+
**/
|
759
|
+
function numeric(mixed){
|
760
|
+
return (typeof(mixed) === 'number' || typeof(mixed) === 'string') && mixed !== '' && !isNaN(mixed);
|
761
|
+
}
|
762
|
+
|
763
|
+
/**
|
764
|
+
* convert data to array
|
765
|
+
**/
|
766
|
+
function array(mixed){
|
767
|
+
var k, a = [];
|
768
|
+
if (mixed !== undefined){
|
769
|
+
if (typeof(mixed) === 'object'){
|
770
|
+
if (typeof(mixed.length) === 'number') {
|
771
|
+
a = mixed;
|
772
|
+
} else {
|
773
|
+
for(k in mixed) {
|
774
|
+
a.push(mixed[k]);
|
775
|
+
}
|
776
|
+
}
|
777
|
+
} else{
|
778
|
+
a.push(mixed);
|
779
|
+
}
|
780
|
+
}
|
781
|
+
return a;
|
782
|
+
}
|
783
|
+
|
784
|
+
/**
|
785
|
+
* convert mixed [ lat, lng ] objet to google.maps.LatLng
|
786
|
+
**/
|
787
|
+
function toLatLng (mixed, emptyReturnMixed, noFlat){
|
788
|
+
var empty = emptyReturnMixed ? mixed : null;
|
789
|
+
if (!mixed || (typeof(mixed) === 'string')){
|
790
|
+
return empty;
|
791
|
+
}
|
792
|
+
// defined latLng
|
793
|
+
if (mixed.latLng) {
|
794
|
+
return toLatLng(mixed.latLng);
|
795
|
+
}
|
796
|
+
// google.maps.LatLng object
|
797
|
+
if (typeof(mixed.lat) === 'function') {
|
798
|
+
return mixed;
|
799
|
+
}
|
800
|
+
// {lat:X, lng:Y} object
|
801
|
+
else if ( numeric(mixed.lat) ) {
|
802
|
+
return new google.maps.LatLng(mixed.lat, mixed.lng);
|
803
|
+
}
|
804
|
+
// [X, Y] object
|
805
|
+
else if ( !noFlat && mixed.length){ // and "no flat" object allowed
|
806
|
+
if ( !numeric(mixed[0]) || !numeric(mixed[1]) ) {
|
807
|
+
return empty;
|
808
|
+
}
|
809
|
+
return new google.maps.LatLng(mixed[0], mixed[1]);
|
810
|
+
}
|
811
|
+
return empty;
|
812
|
+
}
|
813
|
+
|
814
|
+
/**
|
815
|
+
* convert mixed [ sw, ne ] object by google.maps.LatLngBounds
|
816
|
+
**/
|
817
|
+
function toLatLngBounds(mixed, flatAllowed, emptyReturnMixed){
|
818
|
+
var ne, sw, empty;
|
819
|
+
if (!mixed) {
|
820
|
+
return null;
|
821
|
+
}
|
822
|
+
empty = emptyReturnMixed ? mixed : null;
|
823
|
+
if (typeof(mixed.getCenter) === 'function') {
|
824
|
+
return mixed;
|
825
|
+
}
|
826
|
+
if (mixed.length){
|
827
|
+
if (mixed.length == 2){
|
828
|
+
ne = toLatLng(mixed[0]);
|
829
|
+
sw = toLatLng(mixed[1]);
|
830
|
+
} else if (mixed.length == 4){
|
831
|
+
ne = toLatLng([mixed[0], mixed[1]]);
|
832
|
+
sw = toLatLng([mixed[2], mixed[3]]);
|
833
|
+
}
|
834
|
+
} else {
|
835
|
+
if ( ('ne' in mixed) && ('sw' in mixed) ){
|
836
|
+
ne = toLatLng(mixed.ne);
|
837
|
+
sw = toLatLng(mixed.sw);
|
838
|
+
} else if ( ('n' in mixed) && ('e' in mixed) && ('s' in mixed) && ('w' in mixed) ){
|
839
|
+
ne = toLatLng([mixed.n, mixed.e]);
|
840
|
+
sw = toLatLng([mixed.s, mixed.w]);
|
841
|
+
}
|
842
|
+
}
|
843
|
+
if (ne && sw){
|
844
|
+
return new google.maps.LatLngBounds(sw, ne);
|
845
|
+
}
|
846
|
+
return empty;
|
847
|
+
}
|
848
|
+
|
849
|
+
/***************************************************************************/
|
850
|
+
/* GMAP3 */
|
851
|
+
/***************************************************************************/
|
852
|
+
|
853
|
+
function Gmap3($this){
|
854
|
+
|
855
|
+
var stack = new Stack(),
|
856
|
+
store = new Store(),
|
857
|
+
map = null,
|
858
|
+
styles = {},
|
859
|
+
running = false;
|
860
|
+
|
861
|
+
//-----------------------------------------------------------------------//
|
862
|
+
// Stack tools
|
863
|
+
//-----------------------------------------------------------------------//
|
864
|
+
|
865
|
+
/**
|
866
|
+
* store actions to execute in a stack manager
|
867
|
+
**/
|
868
|
+
this._plan = function(list){
|
869
|
+
for(var k = 0; k < list.length; k++) {
|
870
|
+
stack.add(list[k]);
|
871
|
+
}
|
872
|
+
this._run();
|
873
|
+
}
|
874
|
+
|
875
|
+
/**
|
876
|
+
* store one action to execute in a stack manager after the current
|
877
|
+
**/
|
878
|
+
this._planNext = function(todo){
|
879
|
+
stack.addNext(todo);
|
880
|
+
}
|
881
|
+
|
882
|
+
/**
|
883
|
+
* execute action directly
|
884
|
+
**/
|
885
|
+
this._direct = function(todo){
|
886
|
+
var action = ival(todo, 'action');
|
887
|
+
return this[action]($.extend({}, action in _default ? _default[action] : {}, todo.args ? todo.args : todo));
|
888
|
+
}
|
889
|
+
|
890
|
+
/**
|
891
|
+
* called when action in finished, to acknoledge the current in stack and start next one
|
892
|
+
**/
|
893
|
+
this._end = function(){
|
894
|
+
running = false;
|
895
|
+
stack.ack();
|
896
|
+
this._run();
|
897
|
+
},
|
898
|
+
/**
|
899
|
+
* if not running, start next action in stack
|
900
|
+
**/
|
901
|
+
this._run = function(){
|
902
|
+
if (running) {
|
903
|
+
return;
|
904
|
+
}
|
905
|
+
var todo = stack.get();
|
906
|
+
if (!todo) {
|
907
|
+
return;
|
908
|
+
}
|
909
|
+
running = true;
|
910
|
+
this._proceed(todo);
|
911
|
+
}
|
912
|
+
|
913
|
+
//-----------------------------------------------------------------------//
|
914
|
+
// Call tools
|
915
|
+
//-----------------------------------------------------------------------//
|
916
|
+
|
917
|
+
/**
|
918
|
+
* run the appropriated function
|
919
|
+
**/
|
920
|
+
this._proceed = function(todo){
|
921
|
+
todo = todo || {};
|
922
|
+
var action = ival(todo, 'action') || 'init',
|
923
|
+
iaction = action.toLowerCase(),
|
924
|
+
ok = true,
|
925
|
+
target = ival(todo, 'target'),
|
926
|
+
args = ival(todo, 'args'),
|
927
|
+
out;
|
928
|
+
// check if init should be run automatically
|
929
|
+
if ( !map && autoInit(iaction) ){
|
930
|
+
this.init($.extend({}, _default.init, todo.args && todo.args.map ? todo.args.map : todo.map ? todo.map : {}), true);
|
931
|
+
}
|
932
|
+
|
933
|
+
// gmap3 function
|
934
|
+
if (!target && !args && (iaction in this) && (typeof(this[iaction]) === 'function')){
|
935
|
+
this[iaction]($.extend({}, iaction in _default ? _default[iaction] : {}, todo.args ? todo.args : todo)); // call fnc and extends defaults data
|
936
|
+
} else {
|
937
|
+
// "target" object function
|
938
|
+
if (target && (typeof(target) === 'object')){
|
939
|
+
if (ok = (typeof(target[action]) === 'function')){
|
940
|
+
out = target[action].apply(target, todo.args ? todo.args : []);
|
941
|
+
}
|
942
|
+
// google.maps.Map direct function : no result so not rewrited, directly wrapped using array "args" as parameters (ie. setOptions, addMapType, ...)
|
943
|
+
} else if (map){
|
944
|
+
if (ok = (typeof(map[action]) === 'function')){
|
945
|
+
out = map[action].apply(map, todo.args ? todo.args : [] );
|
946
|
+
}
|
947
|
+
}
|
948
|
+
if (!ok && _default.verbose) {
|
949
|
+
alert("unknown action : " + action);
|
950
|
+
}
|
951
|
+
this._callback(out, todo);
|
952
|
+
this._end();
|
953
|
+
}
|
954
|
+
}
|
955
|
+
|
956
|
+
/**
|
957
|
+
* returns the geographical coordinates from an address and call internal or given method
|
958
|
+
**/
|
959
|
+
this._resolveLatLng = function(todo, method, all, attempt){
|
960
|
+
var address = ival(todo, 'address'),
|
961
|
+
params,
|
962
|
+
that = this,
|
963
|
+
fnc = typeof(method) === 'function' ? method : that[method];
|
964
|
+
if ( address ){
|
965
|
+
if (!attempt){ // convert undefined to int
|
966
|
+
attempt = 0;
|
967
|
+
}
|
968
|
+
if (typeof(address) === 'object'){
|
969
|
+
params = address;
|
970
|
+
} else {
|
971
|
+
params = {'address': address};
|
972
|
+
}
|
973
|
+
getGeocoder().geocode(
|
974
|
+
params,
|
975
|
+
function(results, status) {
|
976
|
+
if (status === google.maps.GeocoderStatus.OK){
|
977
|
+
fnc.apply(that, [todo, all ? results : results[0].geometry.location]);
|
978
|
+
} else if ( (status === google.maps.GeocoderStatus.OVER_QUERY_LIMIT) && (attempt < _default.queryLimit.attempt) ){
|
979
|
+
setTimeout(function(){
|
980
|
+
that._resolveLatLng(todo, method, all, attempt+1);
|
981
|
+
},
|
982
|
+
_default.queryLimit.delay + Math.floor(Math.random() * _default.queryLimit.random)
|
983
|
+
);
|
984
|
+
} else {
|
985
|
+
if (_default.verbose){
|
986
|
+
alert('Geocode error : ' + status);
|
987
|
+
}
|
988
|
+
fnc.apply(that, [todo, false]);;
|
989
|
+
}
|
990
|
+
}
|
991
|
+
);
|
992
|
+
} else {
|
993
|
+
fnc.apply(that, [todo, toLatLng(todo, false, true)]);
|
994
|
+
}
|
995
|
+
}
|
996
|
+
|
997
|
+
/**
|
998
|
+
* returns the geographical coordinates from an array of object using "address" and call internal method
|
999
|
+
**/
|
1000
|
+
this._resolveAllLatLng = function(todo, property, method){
|
1001
|
+
var that = this,
|
1002
|
+
i = -1,
|
1003
|
+
solveNext = function(){
|
1004
|
+
do{
|
1005
|
+
i++;
|
1006
|
+
}while( (i < todo[property].length) && !('address' in todo[property][i]) );
|
1007
|
+
if (i < todo[property].length){
|
1008
|
+
(function(todo){
|
1009
|
+
that._resolveLatLng(
|
1010
|
+
todo,
|
1011
|
+
function(todo, latLng){
|
1012
|
+
todo.latLng = latLng;
|
1013
|
+
solveNext.apply(that, []); // solve next or execute exit method
|
1014
|
+
}
|
1015
|
+
);
|
1016
|
+
})(todo[property][i]);
|
1017
|
+
} else {
|
1018
|
+
that[method](todo);
|
1019
|
+
}
|
1020
|
+
};
|
1021
|
+
solveNext();
|
1022
|
+
}
|
1023
|
+
|
1024
|
+
/**
|
1025
|
+
* call a function of framework or google map object of the instance
|
1026
|
+
**/
|
1027
|
+
this._call = function(/* fncName [, ...] */){
|
1028
|
+
var i, fname = arguments[0], args = [];
|
1029
|
+
if ( !arguments.length || !map || (typeof(map[fname]) !== 'function') ){
|
1030
|
+
return;
|
1031
|
+
}
|
1032
|
+
for(i=1; i<arguments.length; i++){
|
1033
|
+
args.push(arguments[i]);
|
1034
|
+
}
|
1035
|
+
return map[fname].apply(map, args);
|
1036
|
+
}
|
1037
|
+
|
1038
|
+
/**
|
1039
|
+
* init if not and manage map subcall (zoom, center)
|
1040
|
+
**/
|
1041
|
+
this._subcall = function(todo, latLng){
|
1042
|
+
var opts = {};
|
1043
|
+
if (!todo.map) return;
|
1044
|
+
if (!latLng) {
|
1045
|
+
latLng = ival(todo.map, 'latlng');
|
1046
|
+
}
|
1047
|
+
if (!map){
|
1048
|
+
if (latLng) {
|
1049
|
+
opts = {center:latLng};
|
1050
|
+
}
|
1051
|
+
this.init($.extend({}, todo.map, opts), true);
|
1052
|
+
} else {
|
1053
|
+
if (todo.map.center && latLng){
|
1054
|
+
this._call("setCenter", latLng);
|
1055
|
+
}
|
1056
|
+
if (todo.map.zoom !== undefined){
|
1057
|
+
this._call("setZoom", todo.map.zoom);
|
1058
|
+
}
|
1059
|
+
if (todo.map.mapTypeId !== undefined){
|
1060
|
+
this._call("setMapTypeId", todo.map.mapTypeId);
|
1061
|
+
}
|
1062
|
+
}
|
1063
|
+
}
|
1064
|
+
|
1065
|
+
/**
|
1066
|
+
* attach an event to a sender
|
1067
|
+
**/
|
1068
|
+
this._attachEvent = function(sender, name, fnc, data, once){
|
1069
|
+
google.maps.event['addListener'+(once?'Once':'')](sender, name, function(event) {
|
1070
|
+
fnc.apply($this, [sender, event, data]);
|
1071
|
+
});
|
1072
|
+
}
|
1073
|
+
|
1074
|
+
/**
|
1075
|
+
* attach events from a container to a sender
|
1076
|
+
* todo[
|
1077
|
+
* events => { eventName => function, }
|
1078
|
+
* onces => { eventName => function, }
|
1079
|
+
* data => mixed data
|
1080
|
+
* ]
|
1081
|
+
**/
|
1082
|
+
this._attachEvents = function(sender, todo){
|
1083
|
+
var name;
|
1084
|
+
if (!todo) {
|
1085
|
+
return
|
1086
|
+
}
|
1087
|
+
if (todo.events){
|
1088
|
+
for(name in todo.events){
|
1089
|
+
if (typeof(todo.events[name]) === 'function'){
|
1090
|
+
this._attachEvent(sender, name, todo.events[name], todo.data, false);
|
1091
|
+
}
|
1092
|
+
}
|
1093
|
+
}
|
1094
|
+
if (todo.onces){
|
1095
|
+
for(name in todo.onces){
|
1096
|
+
if (typeof(todo.onces[name]) === 'function'){
|
1097
|
+
this._attachEvent(sender, name, todo.onces[name], todo.data, true);
|
1098
|
+
}
|
1099
|
+
}
|
1100
|
+
}
|
1101
|
+
}
|
1102
|
+
|
1103
|
+
/**
|
1104
|
+
* execute callback functions
|
1105
|
+
**/
|
1106
|
+
this._callback = function(result, todo){
|
1107
|
+
if (typeof(todo.callback) === 'function') {
|
1108
|
+
todo.callback.apply($this, [result]);
|
1109
|
+
} else if (typeof(todo.callback) === 'object') {
|
1110
|
+
for(var i=0; i<todo.callback.length; i++){
|
1111
|
+
if (typeof(todo.callback[i]) === 'function') {
|
1112
|
+
todo.callback[k].apply($this, [result]);
|
1113
|
+
}
|
1114
|
+
}
|
1115
|
+
}
|
1116
|
+
}
|
1117
|
+
|
1118
|
+
/**
|
1119
|
+
* execute ending functions
|
1120
|
+
**/
|
1121
|
+
this._manageEnd = function(result, todo, internal){
|
1122
|
+
var i, apply;
|
1123
|
+
if (result && (typeof(result) === 'object')){
|
1124
|
+
// attach events
|
1125
|
+
this._attachEvents(result, todo);
|
1126
|
+
// execute "apply"
|
1127
|
+
if (todo.apply && todo.apply.length){
|
1128
|
+
for(i=0; i<todo.apply.length; i++){
|
1129
|
+
apply = todo.apply[i];
|
1130
|
+
// need an existing "action" function in the result object
|
1131
|
+
if(!apply.action || (typeof(result[apply.action]) !== 'function') ) {
|
1132
|
+
continue;
|
1133
|
+
}
|
1134
|
+
if (apply.args) {
|
1135
|
+
result[apply.action].apply(result, apply.args);
|
1136
|
+
} else {
|
1137
|
+
result[apply.action]();
|
1138
|
+
}
|
1139
|
+
}
|
1140
|
+
}
|
1141
|
+
}
|
1142
|
+
if (!internal) {
|
1143
|
+
this._callback(result, todo);
|
1144
|
+
this._end();
|
1145
|
+
}
|
1146
|
+
}
|
1147
|
+
|
1148
|
+
//-----------------------------------------------------------------------//
|
1149
|
+
// gmap3 functions
|
1150
|
+
//-----------------------------------------------------------------------//
|
1151
|
+
|
1152
|
+
/**
|
1153
|
+
* destroy an existing instance
|
1154
|
+
**/
|
1155
|
+
this.destroy = function(todo){
|
1156
|
+
var k;
|
1157
|
+
store.clear();
|
1158
|
+
$this.empty();
|
1159
|
+
for(k in styles){
|
1160
|
+
delete styles[ k ];
|
1161
|
+
}
|
1162
|
+
styles = {};
|
1163
|
+
if (map){
|
1164
|
+
delete map;
|
1165
|
+
}
|
1166
|
+
this._callback(null, todo);
|
1167
|
+
this._end();
|
1168
|
+
}
|
1169
|
+
|
1170
|
+
/**
|
1171
|
+
* Initialize google.maps.Map object
|
1172
|
+
**/
|
1173
|
+
this.init = function(todo, internal){
|
1174
|
+
var o, k, opts;
|
1175
|
+
if (map) { // already initialized
|
1176
|
+
return this._end();
|
1177
|
+
}
|
1178
|
+
|
1179
|
+
o = getObject('map', todo);
|
1180
|
+
if ( (typeof(o.options.center) === 'boolean') && o.options.center) {
|
1181
|
+
return false; // wait for an address resolution
|
1182
|
+
}
|
1183
|
+
opts = $.extend({}, _default.init, o.options);
|
1184
|
+
if (!opts.center) {
|
1185
|
+
opts.center = [_default.init.center.lat, _default.init.center.lng];
|
1186
|
+
}
|
1187
|
+
opts.center = toLatLng(opts.center);
|
1188
|
+
map = new _default.classes.Map($this.get(0), opts);
|
1189
|
+
|
1190
|
+
// add previous added styles
|
1191
|
+
for(k in styles) {
|
1192
|
+
map.mapTypes.set(k, styles[k]);
|
1193
|
+
}
|
1194
|
+
|
1195
|
+
this._manageEnd(map, o, internal);
|
1196
|
+
return true;
|
1197
|
+
}
|
1198
|
+
|
1199
|
+
/**
|
1200
|
+
* returns the geographical coordinates from an address
|
1201
|
+
**/
|
1202
|
+
this.getlatlng = function(todo){
|
1203
|
+
this._resolveLatLng(todo, '_getLatLng', true);
|
1204
|
+
},
|
1205
|
+
|
1206
|
+
this._getLatLng = function(todo, results){
|
1207
|
+
this._manageEnd(results, todo);
|
1208
|
+
},
|
1209
|
+
|
1210
|
+
|
1211
|
+
/**
|
1212
|
+
* returns address from latlng
|
1213
|
+
**/
|
1214
|
+
this.getaddress = function(todo, attempt){
|
1215
|
+
var latLng = toLatLng(todo, false, true),
|
1216
|
+
address = ival(todo, 'address'),
|
1217
|
+
params = latLng ? {latLng:latLng} : ( address ? (typeof(address) === 'string' ? {address:address} : address) : null),
|
1218
|
+
callback = ival(todo, 'callback'),
|
1219
|
+
that = this;
|
1220
|
+
if (!attempt){ // convert undefined to int
|
1221
|
+
attempt = 0;
|
1222
|
+
}
|
1223
|
+
if (params && typeof(callback) === 'function') {
|
1224
|
+
getGeocoder().geocode(
|
1225
|
+
params,
|
1226
|
+
function(results, status) {
|
1227
|
+
if ( (status === google.maps.GeocoderStatus.OVER_QUERY_LIMIT) && (attempt < _default.queryLimit.attempt) ){
|
1228
|
+
setTimeout(function(){
|
1229
|
+
that.getaddress(todo, attempt+1);
|
1230
|
+
},
|
1231
|
+
_default.queryLimit.delay + Math.floor(Math.random() * _default.queryLimit.random)
|
1232
|
+
);
|
1233
|
+
} else {
|
1234
|
+
var out = status === google.maps.GeocoderStatus.OK ? results : false;
|
1235
|
+
callback.apply($this, [out, status]);
|
1236
|
+
if (!out && _default.verbose){
|
1237
|
+
alert('Geocode error : ' + status);
|
1238
|
+
}
|
1239
|
+
that._end();
|
1240
|
+
}
|
1241
|
+
}
|
1242
|
+
);
|
1243
|
+
} else {
|
1244
|
+
this._end();
|
1245
|
+
}
|
1246
|
+
}
|
1247
|
+
|
1248
|
+
/**
|
1249
|
+
* return a route
|
1250
|
+
**/
|
1251
|
+
this.getroute = function(todo){
|
1252
|
+
var callback = ival(todo, 'callback'),
|
1253
|
+
that = this;
|
1254
|
+
if ( (typeof(callback) === 'function') && todo.options ) {
|
1255
|
+
todo.options.origin = toLatLng(todo.options.origin, true);
|
1256
|
+
todo.options.destination = toLatLng(todo.options.destination, true);
|
1257
|
+
getDirectionsService().route(
|
1258
|
+
todo.options,
|
1259
|
+
function(results, status) {
|
1260
|
+
var out = status == google.maps.DirectionsStatus.OK ? results : false;
|
1261
|
+
callback.apply($this, [out, status]);
|
1262
|
+
that._end();
|
1263
|
+
}
|
1264
|
+
);
|
1265
|
+
} else {
|
1266
|
+
this._end();
|
1267
|
+
}
|
1268
|
+
}
|
1269
|
+
|
1270
|
+
/**
|
1271
|
+
* return the elevation of a location
|
1272
|
+
**/
|
1273
|
+
this.getelevation = function(todo){
|
1274
|
+
var fnc, path, samples, i,
|
1275
|
+
locations = [],
|
1276
|
+
callback = ival(todo, 'callback'),
|
1277
|
+
latLng = ival(todo, 'latlng'),
|
1278
|
+
that = this;
|
1279
|
+
|
1280
|
+
if (typeof(callback) === 'function'){
|
1281
|
+
fnc = function(results, status){
|
1282
|
+
var out = status === google.maps.ElevationStatus.OK ? results : false;
|
1283
|
+
callback.apply($this, [out, status]);
|
1284
|
+
that._end();
|
1285
|
+
};
|
1286
|
+
if (latLng){
|
1287
|
+
locations.push(toLatLng(latLng));
|
1288
|
+
} else {
|
1289
|
+
locations = ival(todo, 'locations') || [];
|
1290
|
+
if (locations){
|
1291
|
+
locations = array(locations);
|
1292
|
+
for(i=0; i<locations.length; i++){
|
1293
|
+
locations[i] = toLatLng(locations[i]);
|
1294
|
+
}
|
1295
|
+
}
|
1296
|
+
}
|
1297
|
+
if (locations.length){
|
1298
|
+
getElevationService().getElevationForLocations({locations:locations}, fnc);
|
1299
|
+
} else {
|
1300
|
+
path = ival(todo, 'path');
|
1301
|
+
samples = ival(todo, 'samples');
|
1302
|
+
if (path && samples){
|
1303
|
+
for(i=0; i<path.length; i++){
|
1304
|
+
locations.push(toLatLng(path[i]));
|
1305
|
+
}
|
1306
|
+
if (locations.length){
|
1307
|
+
getElevationService().getElevationAlongPath({path:locations, samples:samples}, fnc);
|
1308
|
+
}
|
1309
|
+
}
|
1310
|
+
}
|
1311
|
+
} else {
|
1312
|
+
this._end();
|
1313
|
+
}
|
1314
|
+
}
|
1315
|
+
|
1316
|
+
/**
|
1317
|
+
* return the distance between an origin and a destination
|
1318
|
+
*
|
1319
|
+
**/
|
1320
|
+
this.getdistance = function(todo){
|
1321
|
+
var i,
|
1322
|
+
callback = ival(todo, 'callback'),
|
1323
|
+
that = this;
|
1324
|
+
if ( (typeof(callback) === 'function') && todo.options && todo.options.origins && todo.options.destinations ) {
|
1325
|
+
// origins and destinations are array containing one or more address strings and/or google.maps.LatLng objects
|
1326
|
+
todo.options.origins = array(todo.options.origins);
|
1327
|
+
for(i=0; i<todo.options.origins.length; i++){
|
1328
|
+
todo.options.origins[i] = toLatLng(todo.options.origins[i], true);
|
1329
|
+
}
|
1330
|
+
todo.options.destinations = array(todo.options.destinations);
|
1331
|
+
for(i=0; i<todo.options.destinations.length; i++){
|
1332
|
+
todo.options.destinations[i] = toLatLng(todo.options.destinations[i], true);
|
1333
|
+
}
|
1334
|
+
getDistanceMatrixService().getDistanceMatrix(
|
1335
|
+
todo.options,
|
1336
|
+
function(results, status) {
|
1337
|
+
var out = status == google.maps.DistanceMatrixStatus.OK ? results : false;
|
1338
|
+
callback.apply($this, [out, status]);
|
1339
|
+
that._end();
|
1340
|
+
}
|
1341
|
+
);
|
1342
|
+
} else {
|
1343
|
+
this._end();
|
1344
|
+
}
|
1345
|
+
}
|
1346
|
+
|
1347
|
+
/**
|
1348
|
+
* Add a marker to a map after address resolution
|
1349
|
+
* if [infowindow] add an infowindow attached to the marker
|
1350
|
+
**/
|
1351
|
+
this.addmarker = function(todo){
|
1352
|
+
this._resolveLatLng(todo, '_addMarker');
|
1353
|
+
}
|
1354
|
+
|
1355
|
+
this._addMarker = function(todo, latLng, internal){
|
1356
|
+
var result, oi, to,
|
1357
|
+
o = getObject('marker', todo, 'to');
|
1358
|
+
if (!internal){
|
1359
|
+
if (!latLng) {
|
1360
|
+
this._manageEnd(false, o);
|
1361
|
+
return;
|
1362
|
+
}
|
1363
|
+
this._subcall(todo, latLng);
|
1364
|
+
} else if (!latLng){
|
1365
|
+
return;
|
1366
|
+
}
|
1367
|
+
if (o.to){
|
1368
|
+
to = store.refToObj(o.to);
|
1369
|
+
result = to && (typeof(to.add) === 'function');
|
1370
|
+
if (result){
|
1371
|
+
to.add(latLng, todo);
|
1372
|
+
if (typeof(to.redraw) === 'function'){
|
1373
|
+
to.redraw();
|
1374
|
+
}
|
1375
|
+
}
|
1376
|
+
if (!internal){
|
1377
|
+
this._manageEnd(result, o);
|
1378
|
+
}
|
1379
|
+
} else {
|
1380
|
+
o.options.position = latLng;
|
1381
|
+
o.options.map = map;
|
1382
|
+
result = new _default.classes.Marker(o.options);
|
1383
|
+
if (hasKey(todo, 'infowindow')){
|
1384
|
+
oi = getObject('infowindow', todo['infowindow'], 'open');
|
1385
|
+
// if "open" is not defined, add it in first position
|
1386
|
+
if ( (oi.open === undefined) || oi.open ){
|
1387
|
+
oi.apply = array(oi.apply);
|
1388
|
+
oi.apply.unshift({action:'open', args:[map, result]});
|
1389
|
+
}
|
1390
|
+
oi.action = 'addinfowindow';
|
1391
|
+
this._planNext(oi);
|
1392
|
+
}
|
1393
|
+
if (!internal){
|
1394
|
+
store.add('marker', result, o);
|
1395
|
+
this._manageEnd(result, o);
|
1396
|
+
}
|
1397
|
+
}
|
1398
|
+
return result;
|
1399
|
+
}
|
1400
|
+
|
1401
|
+
/**
|
1402
|
+
* add markers (without address resolution)
|
1403
|
+
**/
|
1404
|
+
this.addmarkers = function(todo){
|
1405
|
+
if (ival(todo, 'clusters')){
|
1406
|
+
this._resolveAllLatLng(todo, 'markers', '_addclusteredmarkers');
|
1407
|
+
} else {
|
1408
|
+
this._resolveAllLatLng(todo, 'markers', '_addmarkers');
|
1409
|
+
}
|
1410
|
+
}
|
1411
|
+
|
1412
|
+
this._addmarkers = function(todo){
|
1413
|
+
var result, o, i, latLng, marker, options = {}, tmp, to,
|
1414
|
+
markers = ival(todo, 'markers');
|
1415
|
+
this._subcall(todo);
|
1416
|
+
if (typeof(markers) !== 'object') {
|
1417
|
+
return this._end();
|
1418
|
+
}
|
1419
|
+
o = getObject('marker', todo, ['to', 'markers']);
|
1420
|
+
|
1421
|
+
if (o.to){
|
1422
|
+
to = store.refToObj(o.to);
|
1423
|
+
result = to && (typeof(to.add) === 'function');
|
1424
|
+
if (result){
|
1425
|
+
for(i=0; i<markers.length; i++){
|
1426
|
+
if (latLng = toLatLng(markers[i])) {
|
1427
|
+
to.add(latLng, markers[i]);
|
1428
|
+
}
|
1429
|
+
}
|
1430
|
+
if (typeof(to.redraw) === 'function'){
|
1431
|
+
to.redraw();
|
1432
|
+
}
|
1433
|
+
}
|
1434
|
+
this._manageEnd(result, o);
|
1435
|
+
} else {
|
1436
|
+
$.extend(true, options, o.options);
|
1437
|
+
options.map = map;
|
1438
|
+
result = [];
|
1439
|
+
for(i=0; i<markers.length; i++){
|
1440
|
+
if (latLng = toLatLng(markers[i])){
|
1441
|
+
if (markers[i].options){
|
1442
|
+
tmp = {};
|
1443
|
+
$.extend(true, tmp, options, markers[i].options);
|
1444
|
+
o.options = tmp;
|
1445
|
+
} else {
|
1446
|
+
o.options = options;
|
1447
|
+
}
|
1448
|
+
o.options.position = latLng;
|
1449
|
+
marker = new _default.classes.Marker(o.options);
|
1450
|
+
result.push(marker);
|
1451
|
+
o.data = markers[i].data;
|
1452
|
+
o.tag = markers[i].tag;
|
1453
|
+
store.add('marker', marker, o);
|
1454
|
+
this._manageEnd(marker, o, true);
|
1455
|
+
}
|
1456
|
+
}
|
1457
|
+
o.options = options; // restore previous for futur use
|
1458
|
+
this._callback(result, todo);
|
1459
|
+
this._end();
|
1460
|
+
}
|
1461
|
+
}
|
1462
|
+
|
1463
|
+
this._addclusteredmarkers = function(todo){
|
1464
|
+
var clusterer, i, latLng, storeId,
|
1465
|
+
that = this,
|
1466
|
+
radius = ival(todo, 'radius'),
|
1467
|
+
maxZoom = ival(todo, 'maxZoom'),
|
1468
|
+
markers = ival(todo, 'markers'),
|
1469
|
+
styles = ival(todo, 'clusters');
|
1470
|
+
|
1471
|
+
if (!map.getBounds()){ // map not initialised => bounds not available
|
1472
|
+
// wait for map
|
1473
|
+
google.maps.event.addListenerOnce(
|
1474
|
+
map,
|
1475
|
+
'bounds_changed',
|
1476
|
+
function() {
|
1477
|
+
that._addclusteredmarkers(todo);
|
1478
|
+
}
|
1479
|
+
);
|
1480
|
+
return;
|
1481
|
+
}
|
1482
|
+
|
1483
|
+
if (typeof(radius) === 'number'){
|
1484
|
+
clusterer = new Clusterer();
|
1485
|
+
for(i=0 ; i<markers.length; i++){
|
1486
|
+
latLng = toLatLng(markers[i]);
|
1487
|
+
clusterer.add(latLng, markers[i]);
|
1488
|
+
}
|
1489
|
+
storeId = this._initClusters(todo, clusterer, radius, maxZoom, styles);
|
1490
|
+
}
|
1491
|
+
|
1492
|
+
this._callback(storeId, todo);
|
1493
|
+
this._end();
|
1494
|
+
}
|
1495
|
+
|
1496
|
+
|
1497
|
+
this._initClusters = function(todo, clusterer, radius, maxZoom, styles){
|
1498
|
+
var that = this;
|
1499
|
+
|
1500
|
+
clusterer.setRedraw(function(force){
|
1501
|
+
var same, clusters = clusterer.clusters(map, radius, maxZoom, force);
|
1502
|
+
if (clusters){
|
1503
|
+
same = clusterer.freeDiff(clusters);
|
1504
|
+
that._displayClusters(todo, clusterer, clusters, same, styles);
|
1505
|
+
}
|
1506
|
+
});
|
1507
|
+
|
1508
|
+
clusterer.events(
|
1509
|
+
google.maps.event.addListener(
|
1510
|
+
map,
|
1511
|
+
'zoom_changed',
|
1512
|
+
function() {
|
1513
|
+
clusterer.redraw(true);
|
1514
|
+
}
|
1515
|
+
),
|
1516
|
+
google.maps.event.addListener(
|
1517
|
+
map,
|
1518
|
+
'bounds_changed',
|
1519
|
+
function() {
|
1520
|
+
clusterer.redraw();
|
1521
|
+
}
|
1522
|
+
)
|
1523
|
+
);
|
1524
|
+
|
1525
|
+
clusterer.redraw();
|
1526
|
+
return store.add('cluster', clusterer, todo);
|
1527
|
+
}
|
1528
|
+
|
1529
|
+
this._displayClusters = function(todo, clusterer, clusters, same, styles){
|
1530
|
+
var k, i, ii, m, done, obj, shadow, cluster, options, tmp, w, h,
|
1531
|
+
atodo,
|
1532
|
+
ctodo = hasKey(todo, 'cluster') ? getObject('', ival(todo, 'cluster')) : {},
|
1533
|
+
mtodo = hasKey(todo, 'marker') ? getObject('', ival(todo, 'marker')) : {};
|
1534
|
+
for(i=0; i<clusters.length; i++){
|
1535
|
+
if (i in same){
|
1536
|
+
continue;
|
1537
|
+
}
|
1538
|
+
cluster = clusters[i];
|
1539
|
+
done = false;
|
1540
|
+
if (cluster.idx.length > 1){
|
1541
|
+
// look for the cluster design to use
|
1542
|
+
m = 0;
|
1543
|
+
for(k in styles){
|
1544
|
+
if ( (k > m) && (k <= cluster.idx.length) ){
|
1545
|
+
m = k;
|
1546
|
+
}
|
1547
|
+
}
|
1548
|
+
if (styles[m]){ // cluster defined for the current markers count
|
1549
|
+
w = ival(styles[m], 'width');
|
1550
|
+
h = ival(styles[m], 'height');
|
1551
|
+
|
1552
|
+
// create a custom _addOverlay command
|
1553
|
+
atodo = {};
|
1554
|
+
$.extend(
|
1555
|
+
true,
|
1556
|
+
atodo,
|
1557
|
+
ctodo,
|
1558
|
+
{ options:{
|
1559
|
+
pane: 'overlayLayer',
|
1560
|
+
content:styles[m].content.replace('CLUSTER_COUNT', cluster.idx.length),
|
1561
|
+
offset:{
|
1562
|
+
x: -w/2,
|
1563
|
+
y: -h/2
|
1564
|
+
}
|
1565
|
+
}
|
1566
|
+
}
|
1567
|
+
);
|
1568
|
+
obj = this._addOverlay(atodo, toLatLng(cluster), true);
|
1569
|
+
atodo.options.pane = 'floatShadow';
|
1570
|
+
atodo.options.content = $('<div></div>');
|
1571
|
+
atodo.options.content.width(w);
|
1572
|
+
atodo.options.content.height(h);
|
1573
|
+
shadow = this._addOverlay(atodo, toLatLng(cluster), true);
|
1574
|
+
|
1575
|
+
// store data to the clusterer
|
1576
|
+
ctodo.data = {
|
1577
|
+
latLng: toLatLng(cluster),
|
1578
|
+
markers:[]
|
1579
|
+
};
|
1580
|
+
for(ii=0; ii<cluster.idx.length; ii++){
|
1581
|
+
ctodo.data.markers.push(
|
1582
|
+
clusterer.get(cluster.idx[ii]).marker
|
1583
|
+
);
|
1584
|
+
}
|
1585
|
+
this._attachEvents(shadow, ctodo);
|
1586
|
+
clusterer.store(cluster, obj, shadow);
|
1587
|
+
done = true;
|
1588
|
+
}
|
1589
|
+
}
|
1590
|
+
if (!done){ // cluster not defined (< min count) or = 1 so display all markers of the current cluster
|
1591
|
+
// save the defaults options for the markers
|
1592
|
+
options = {};
|
1593
|
+
$.extend(true, options, mtodo.options);
|
1594
|
+
for(ii = 0; ii <cluster.idx.length; ii++){
|
1595
|
+
m = clusterer.get(cluster.idx[ii]);
|
1596
|
+
mtodo.latLng = m.latLng;
|
1597
|
+
mtodo.data = m.marker.data;
|
1598
|
+
mtodo.tag = m.marker.tag;
|
1599
|
+
if (m.marker.options){
|
1600
|
+
tmp = {};
|
1601
|
+
$.extend(true, tmp, options, m.marker.options);
|
1602
|
+
mtodo.options = tmp;
|
1603
|
+
} else {
|
1604
|
+
mtodo.options = options;
|
1605
|
+
}
|
1606
|
+
obj = this._addMarker(mtodo, mtodo.latLng, true);
|
1607
|
+
this._attachEvents(obj, mtodo);
|
1608
|
+
clusterer.store(cluster, obj);
|
1609
|
+
}
|
1610
|
+
mtodo.options = options; // restore previous for futur use
|
1611
|
+
}
|
1612
|
+
}
|
1613
|
+
}
|
1614
|
+
|
1615
|
+
/**
|
1616
|
+
* add an infowindow after address resolution
|
1617
|
+
**/
|
1618
|
+
this.addinfowindow = function(todo){
|
1619
|
+
this._resolveLatLng(todo, '_addInfoWindow');
|
1620
|
+
}
|
1621
|
+
|
1622
|
+
this._addInfoWindow = function(todo, latLng){
|
1623
|
+
var o, infowindow, args = [];
|
1624
|
+
this._subcall(todo, latLng);
|
1625
|
+
o = getObject('infowindow', todo, ['open', 'anchor']);
|
1626
|
+
if (latLng) {
|
1627
|
+
o.options.position = latLng;
|
1628
|
+
}
|
1629
|
+
infowindow = new _default.classes.InfoWindow(o.options);
|
1630
|
+
if ( (o.open === undefined) || o.open ){
|
1631
|
+
o.apply = array(o.apply);
|
1632
|
+
args.push(map);
|
1633
|
+
if (o.anchor){
|
1634
|
+
args.push(o.anchor);
|
1635
|
+
}
|
1636
|
+
o.apply.unshift({action:'open', args:args});
|
1637
|
+
}
|
1638
|
+
store.add('infowindow', infowindow, o);
|
1639
|
+
this._manageEnd(infowindow, o);
|
1640
|
+
}
|
1641
|
+
|
1642
|
+
|
1643
|
+
/**
|
1644
|
+
* add a polygone / polylin on a map
|
1645
|
+
**/
|
1646
|
+
this.addpolyline = function(todo){
|
1647
|
+
this._addPoly(todo, 'Polyline', 'path');
|
1648
|
+
}
|
1649
|
+
|
1650
|
+
this.addpolygon = function(todo){
|
1651
|
+
this._addPoly(todo, 'Polygon', 'paths');
|
1652
|
+
}
|
1653
|
+
|
1654
|
+
this._addPoly = function(todo, poly, path){
|
1655
|
+
var i,
|
1656
|
+
obj, latLng,
|
1657
|
+
o = getObject(poly.toLowerCase(), todo, path);
|
1658
|
+
if (o[path]){
|
1659
|
+
o.options[path] = [];
|
1660
|
+
for(i=0; i<o[path].length; i++){
|
1661
|
+
if (latLng = toLatLng(o[path][i])){
|
1662
|
+
o.options[path].push(latLng);
|
1663
|
+
}
|
1664
|
+
}
|
1665
|
+
}
|
1666
|
+
obj = new google.maps[poly](o.options);
|
1667
|
+
obj.setMap(map);
|
1668
|
+
store.add(poly.toLowerCase(), obj, o);
|
1669
|
+
this._manageEnd(obj, o);
|
1670
|
+
}
|
1671
|
+
|
1672
|
+
/**
|
1673
|
+
* add a circle
|
1674
|
+
**/
|
1675
|
+
this.addcircle = function(todo){
|
1676
|
+
this._resolveLatLng(todo, '_addCircle');
|
1677
|
+
}
|
1678
|
+
|
1679
|
+
this._addCircle = function(todo, latLng){
|
1680
|
+
var c, o = getObject('circle', todo);
|
1681
|
+
if (!latLng) {
|
1682
|
+
latLng = toLatLng(o.options.center);
|
1683
|
+
}
|
1684
|
+
if (!latLng) {
|
1685
|
+
return this._manageEnd(false, o);
|
1686
|
+
}
|
1687
|
+
this._subcall(todo, latLng);
|
1688
|
+
o.options.center = latLng;
|
1689
|
+
o.options.map = map;
|
1690
|
+
c = new _default.classes.Circle(o.options);
|
1691
|
+
store.add('circle', c, o);
|
1692
|
+
this._manageEnd(c, o);
|
1693
|
+
}
|
1694
|
+
|
1695
|
+
/**
|
1696
|
+
* add a rectangle
|
1697
|
+
**/
|
1698
|
+
this.addrectangle = function(todo){
|
1699
|
+
this._resolveLatLng(todo, '_addRectangle');
|
1700
|
+
}
|
1701
|
+
|
1702
|
+
this._addRectangle = function(todo, latLng ){
|
1703
|
+
var r, o = getObject('rectangle', todo);
|
1704
|
+
o.options.bounds = toLatLngBounds(o.options.bounds, true);
|
1705
|
+
if (!o.options.bounds) {
|
1706
|
+
return this._manageEnd(false, o);
|
1707
|
+
}
|
1708
|
+
this._subcall(todo, o.options.bounds.getCenter());
|
1709
|
+
o.options.map = map;
|
1710
|
+
r = new _default.classes.Rectangle(o.options);
|
1711
|
+
store.add('rectangle', r, o);
|
1712
|
+
this._manageEnd(r, o);
|
1713
|
+
}
|
1714
|
+
|
1715
|
+
/**
|
1716
|
+
* add an overlay to a map after address resolution
|
1717
|
+
**/
|
1718
|
+
this.addoverlay = function(todo){
|
1719
|
+
this._resolveLatLng(todo, '_addOverlay');
|
1720
|
+
}
|
1721
|
+
|
1722
|
+
this._addOverlay = function(todo, latLng, internal){
|
1723
|
+
var ov,
|
1724
|
+
o = getObject('overlay', todo),
|
1725
|
+
opts = $.extend({
|
1726
|
+
pane: 'floatPane',
|
1727
|
+
content: '',
|
1728
|
+
offset:{
|
1729
|
+
x:0,y:0
|
1730
|
+
}
|
1731
|
+
},
|
1732
|
+
o.options),
|
1733
|
+
$div = $('<div></div>'),
|
1734
|
+
listeners = [];
|
1735
|
+
|
1736
|
+
$div
|
1737
|
+
.css('border', 'none')
|
1738
|
+
.css('borderWidth', '0px')
|
1739
|
+
.css('position', 'absolute');
|
1740
|
+
$div.append(opts.content);
|
1741
|
+
|
1742
|
+
function f() {
|
1743
|
+
_default.classes.OverlayView.call(this);
|
1744
|
+
this.setMap(map);
|
1745
|
+
}
|
1746
|
+
|
1747
|
+
f.prototype = new _default.classes.OverlayView();
|
1748
|
+
|
1749
|
+
f.prototype.onAdd = function() {
|
1750
|
+
var panes = this.getPanes();
|
1751
|
+
if (opts.pane in panes) {
|
1752
|
+
$(panes[opts.pane]).append($div);
|
1753
|
+
}
|
1754
|
+
}
|
1755
|
+
f.prototype.draw = function() {
|
1756
|
+
var overlayProjection = this.getProjection(),
|
1757
|
+
ps = overlayProjection.fromLatLngToDivPixel(latLng),
|
1758
|
+
that = this;
|
1759
|
+
|
1760
|
+
$div
|
1761
|
+
.css('left', (ps.x+opts.offset.x) + 'px')
|
1762
|
+
.css('top' , (ps.y+opts.offset.y) + 'px');
|
1763
|
+
|
1764
|
+
$.each( ("dblclick click mouseover mousemove mouseout mouseup mousedown").split(" "), function( i, name ) {
|
1765
|
+
listeners.push(
|
1766
|
+
google.maps.event.addDomListener($div[0], name, function(e) {
|
1767
|
+
google.maps.event.trigger(that, name);
|
1768
|
+
})
|
1769
|
+
);
|
1770
|
+
});
|
1771
|
+
listeners.push(
|
1772
|
+
google.maps.event.addDomListener($div[0], "contextmenu", function(e) {
|
1773
|
+
google.maps.event.trigger(that, "rightclick");
|
1774
|
+
})
|
1775
|
+
);
|
1776
|
+
}
|
1777
|
+
f.prototype.onRemove = function() {
|
1778
|
+
for (var i = 0; i < listeners.length; i++) {
|
1779
|
+
google.maps.event.removeListener(listeners[i]);
|
1780
|
+
}
|
1781
|
+
$div.remove();
|
1782
|
+
}
|
1783
|
+
f.prototype.hide = function() {
|
1784
|
+
$div.hide();
|
1785
|
+
}
|
1786
|
+
f.prototype.show = function() {
|
1787
|
+
$div.show();
|
1788
|
+
}
|
1789
|
+
f.prototype.toggle = function() {
|
1790
|
+
if ($div) {
|
1791
|
+
if ($div.is(':visible')){
|
1792
|
+
this.show();
|
1793
|
+
} else {
|
1794
|
+
this.hide();
|
1795
|
+
}
|
1796
|
+
}
|
1797
|
+
}
|
1798
|
+
f.prototype.toggleDOM = function() {
|
1799
|
+
if (this.getMap()) {
|
1800
|
+
this.setMap(null);
|
1801
|
+
} else {
|
1802
|
+
this.setMap(map);
|
1803
|
+
}
|
1804
|
+
}
|
1805
|
+
f.prototype.getDOMElement = function() {
|
1806
|
+
return $div[0];
|
1807
|
+
}
|
1808
|
+
ov = new f();
|
1809
|
+
if (!internal){
|
1810
|
+
store.add('overlay', ov, o);
|
1811
|
+
this._manageEnd(ov, o);
|
1812
|
+
}
|
1813
|
+
return ov;
|
1814
|
+
}
|
1815
|
+
|
1816
|
+
/**
|
1817
|
+
* add a fix panel to a map
|
1818
|
+
**/
|
1819
|
+
this.addfixpanel = function(todo){
|
1820
|
+
var o = getObject('fixpanel', todo),
|
1821
|
+
x=y=0, $c, $div;
|
1822
|
+
if (o.options.content){
|
1823
|
+
$c = $(o.options.content);
|
1824
|
+
|
1825
|
+
if (o.options.left !== undefined){
|
1826
|
+
x = o.options.left;
|
1827
|
+
} else if (o.options.right !== undefined){
|
1828
|
+
x = $this.width() - $c.width() - o.options.right;
|
1829
|
+
} else if (o.options.center){
|
1830
|
+
x = ($this.width() - $c.width()) / 2;
|
1831
|
+
}
|
1832
|
+
|
1833
|
+
if (o.options.top !== undefined){
|
1834
|
+
y = o.options.top;
|
1835
|
+
} else if (o.options.bottom !== undefined){
|
1836
|
+
y = $this.height() - $c.height() - o.options.bottom;
|
1837
|
+
} else if (o.options.middle){
|
1838
|
+
y = ($this.height() - $c.height()) / 2
|
1839
|
+
}
|
1840
|
+
|
1841
|
+
$div = $('<div></div>')
|
1842
|
+
.css('position', 'absolute')
|
1843
|
+
.css('top', y+'px')
|
1844
|
+
.css('left', x+'px')
|
1845
|
+
.css('z-index', '1000')
|
1846
|
+
.append($c);
|
1847
|
+
|
1848
|
+
$this.first().prepend($div);
|
1849
|
+
this._attachEvents(map, o);
|
1850
|
+
store.add('fixpanel', $div, o);
|
1851
|
+
this._callback($div, o);
|
1852
|
+
}
|
1853
|
+
this._end();
|
1854
|
+
}
|
1855
|
+
|
1856
|
+
/**
|
1857
|
+
* add a direction renderer to a map
|
1858
|
+
**/
|
1859
|
+
this.adddirectionsrenderer = function(todo, internal){
|
1860
|
+
var dr, o = getObject('directionrenderer', todo, 'panelId');
|
1861
|
+
o.options.map = map;
|
1862
|
+
dr = new google.maps.DirectionsRenderer(o.options);
|
1863
|
+
if (o.panelId) {
|
1864
|
+
dr.setPanel(document.getElementById(o.panelId));
|
1865
|
+
}
|
1866
|
+
store.add('directionrenderer', dr, o);
|
1867
|
+
this._manageEnd(dr, o, internal);
|
1868
|
+
return dr;
|
1869
|
+
}
|
1870
|
+
|
1871
|
+
/**
|
1872
|
+
* set a direction panel to a dom element from its ID
|
1873
|
+
**/
|
1874
|
+
this.setdirectionspanel = function(todo){
|
1875
|
+
var dr = store.get('directionrenderer'),
|
1876
|
+
o = getObject('directionpanel', todo, 'id');
|
1877
|
+
if (dr && o.id) {
|
1878
|
+
dr.setPanel(document.getElementById(o.id));
|
1879
|
+
}
|
1880
|
+
this._manageEnd(dr, o);
|
1881
|
+
}
|
1882
|
+
|
1883
|
+
/**
|
1884
|
+
* set directions on a map (create Direction Renderer if needed)
|
1885
|
+
**/
|
1886
|
+
this.setdirections = function(todo){
|
1887
|
+
var dr = store.get('directionrenderer'),
|
1888
|
+
o = getObject('directions', todo);
|
1889
|
+
if (todo) {
|
1890
|
+
o.options.directions = todo.directions ? todo.directions : (todo.options && todo.options.directions ? todo.options.directions : null);
|
1891
|
+
}
|
1892
|
+
if (o.options.directions) {
|
1893
|
+
if (!dr) {
|
1894
|
+
dr = this.adddirectionsrenderer(o, true);
|
1895
|
+
} else {
|
1896
|
+
dr.setDirections(o.options.directions);
|
1897
|
+
}
|
1898
|
+
}
|
1899
|
+
this._manageEnd(dr, o);
|
1900
|
+
}
|
1901
|
+
|
1902
|
+
/**
|
1903
|
+
* set a streetview to a map
|
1904
|
+
**/
|
1905
|
+
this.setstreetview = function(todo){
|
1906
|
+
var panorama,
|
1907
|
+
o = getObject('streetview', todo, 'id');
|
1908
|
+
if (o.options.position){
|
1909
|
+
o.options.position = toLatLng(o.options.position);
|
1910
|
+
}
|
1911
|
+
panorama = new _default.classes.StreetViewPanorama(document.getElementById(o.id),o.options);
|
1912
|
+
if (panorama){
|
1913
|
+
map.setStreetView(panorama);
|
1914
|
+
}
|
1915
|
+
this._manageEnd(panorama, o);
|
1916
|
+
}
|
1917
|
+
|
1918
|
+
/**
|
1919
|
+
* add a kml layer to a map
|
1920
|
+
**/
|
1921
|
+
this.addkmllayer = function(todo){
|
1922
|
+
var kml,
|
1923
|
+
o = getObject('kmllayer', todo, 'url');
|
1924
|
+
o.options.map = map;
|
1925
|
+
if (typeof(o.url) === 'string'){
|
1926
|
+
kml = new _default.classes.KmlLayer(o.url, o.options);
|
1927
|
+
}
|
1928
|
+
store.add('kmllayer', kml, o);
|
1929
|
+
this._manageEnd(kml, o);
|
1930
|
+
}
|
1931
|
+
|
1932
|
+
/**
|
1933
|
+
* add a traffic layer to a map
|
1934
|
+
**/
|
1935
|
+
this.addtrafficlayer = function(todo){
|
1936
|
+
var o = getObject('trafficlayer', todo),
|
1937
|
+
tl = store.get('trafficlayer');
|
1938
|
+
if (!tl){
|
1939
|
+
tl = new _default.classes.TrafficLayer();
|
1940
|
+
tl.setMap(map);
|
1941
|
+
store.add('trafficlayer', tl, o);
|
1942
|
+
}
|
1943
|
+
this._manageEnd(tl, o);
|
1944
|
+
}
|
1945
|
+
|
1946
|
+
/**
|
1947
|
+
* add a bicycling layer to a map
|
1948
|
+
**/
|
1949
|
+
this.addbicyclinglayer = function(todo){
|
1950
|
+
var o = getObject('bicyclinglayer', todo),
|
1951
|
+
bl = store.get('bicyclinglayer');
|
1952
|
+
if (!bl){
|
1953
|
+
bl = new _default.classes.BicyclingLayer();
|
1954
|
+
bl.setMap(map);
|
1955
|
+
store.add('bicyclinglayer', bl, o);
|
1956
|
+
}
|
1957
|
+
this._manageEnd(bl, o);
|
1958
|
+
}
|
1959
|
+
|
1960
|
+
/**
|
1961
|
+
* add a ground overlay to a map
|
1962
|
+
**/
|
1963
|
+
this.addgroundoverlay = function(todo){
|
1964
|
+
var ov,
|
1965
|
+
o = getObject('groundoverlay', todo, ['bounds', 'url']);
|
1966
|
+
o.bounds = toLatLngBounds(o.bounds);
|
1967
|
+
if (o.bounds && (typeof(o.url) === 'string')){
|
1968
|
+
ov = new _default.classes.GroundOverlay(o.url, o.bounds);
|
1969
|
+
ov.setMap(map);
|
1970
|
+
store.add('groundoverlay', ov, o);
|
1971
|
+
}
|
1972
|
+
this._manageEnd(ov, o);
|
1973
|
+
}
|
1974
|
+
|
1975
|
+
/**
|
1976
|
+
* geolocalise the user and return a LatLng
|
1977
|
+
**/
|
1978
|
+
this.geolatlng = function(todo){
|
1979
|
+
var callback = ival(todo, 'callback');
|
1980
|
+
if (typeof(callback) === 'function') {
|
1981
|
+
if(navigator.geolocation) {
|
1982
|
+
navigator.geolocation.getCurrentPosition(
|
1983
|
+
function(position) {
|
1984
|
+
var out = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
|
1985
|
+
callback.apply($this, [out]);
|
1986
|
+
},
|
1987
|
+
function() {
|
1988
|
+
var out = false;
|
1989
|
+
callback.apply($this, [out]);
|
1990
|
+
}
|
1991
|
+
);
|
1992
|
+
} else if (google.gears) {
|
1993
|
+
google.gears.factory.create('beta.geolocation').getCurrentPosition(
|
1994
|
+
function(position) {
|
1995
|
+
var out = new google.maps.LatLng(position.latitude,position.longitude);
|
1996
|
+
callback.apply($this, [out]);
|
1997
|
+
},
|
1998
|
+
function() {
|
1999
|
+
out = false;
|
2000
|
+
callback.apply($this, [out]);
|
2001
|
+
}
|
2002
|
+
);
|
2003
|
+
} else {
|
2004
|
+
callback.apply($this, [false]);
|
2005
|
+
}
|
2006
|
+
}
|
2007
|
+
this._end();
|
2008
|
+
}
|
2009
|
+
|
2010
|
+
/**
|
2011
|
+
* add a style to a map
|
2012
|
+
**/
|
2013
|
+
this.addstyledmap = function(todo, internal){
|
2014
|
+
var o = getObject('styledmap', todo, ['id', 'style']);
|
2015
|
+
if (o.style && o.id && !styles[o.id]) {
|
2016
|
+
styles[o.id] = new _default.classes.StyledMapType(o.style, o.options);
|
2017
|
+
if (map) {
|
2018
|
+
map.mapTypes.set(o.id, styles[o.id]);
|
2019
|
+
}
|
2020
|
+
}
|
2021
|
+
this._manageEnd(styles[o.id], o, internal);
|
2022
|
+
}
|
2023
|
+
|
2024
|
+
/**
|
2025
|
+
* set a style to a map (add it if needed)
|
2026
|
+
**/
|
2027
|
+
this.setstyledmap = function(todo){
|
2028
|
+
var o = getObject('styledmap', todo, ['id', 'style']);
|
2029
|
+
if (o.id) {
|
2030
|
+
this.addstyledmap(o, true);
|
2031
|
+
if (styles[o.id]) {
|
2032
|
+
map.setMapTypeId(o.id);
|
2033
|
+
this._callback(styles[o.id], todo);
|
2034
|
+
}
|
2035
|
+
}
|
2036
|
+
this._manageEnd(styles[o.id], o);
|
2037
|
+
}
|
2038
|
+
|
2039
|
+
/**
|
2040
|
+
* remove objects from a map
|
2041
|
+
**/
|
2042
|
+
this.clear = function(todo){
|
2043
|
+
var list = array(ival(todo, 'list') || ival(todo, 'name')),
|
2044
|
+
last = ival(todo, 'last', false),
|
2045
|
+
first = ival(todo, 'first', false),
|
2046
|
+
tag = ival(todo, 'tag');
|
2047
|
+
if (tag !== undefined){
|
2048
|
+
tag = array(tag);
|
2049
|
+
}
|
2050
|
+
store.clear(list, last, first, tag);
|
2051
|
+
this._end();
|
2052
|
+
}
|
2053
|
+
|
2054
|
+
/**
|
2055
|
+
* return objects previously created
|
2056
|
+
**/
|
2057
|
+
this.get = function(todo){
|
2058
|
+
var name = ival(todo, 'name') || 'map',
|
2059
|
+
first= ival(todo, 'first'),
|
2060
|
+
all = ival(todo, 'all'),
|
2061
|
+
tag = ival(todo, 'tag');
|
2062
|
+
name = name.toLowerCase();
|
2063
|
+
if (name === 'map'){
|
2064
|
+
return map;
|
2065
|
+
}
|
2066
|
+
if (tag !== undefined){
|
2067
|
+
tag = array(tag);
|
2068
|
+
}
|
2069
|
+
if (first){
|
2070
|
+
return store.get(name, false, tag);
|
2071
|
+
} else if (all){
|
2072
|
+
return store.all(name, tag);
|
2073
|
+
} else {
|
2074
|
+
return store.get(name, true, tag);
|
2075
|
+
}
|
2076
|
+
}
|
2077
|
+
|
2078
|
+
/**
|
2079
|
+
* return the max zoom of a location
|
2080
|
+
**/
|
2081
|
+
this.getmaxzoom = function(todo){
|
2082
|
+
this._resolveLatLng(todo, '_getMaxZoom');
|
2083
|
+
}
|
2084
|
+
|
2085
|
+
this._getMaxZoom = function(todo, latLng){
|
2086
|
+
var callback = ival(todo, 'callback'),
|
2087
|
+
that = this;
|
2088
|
+
if (callback && typeof(callback) === 'function') {
|
2089
|
+
getMaxZoomService().getMaxZoomAtLatLng(
|
2090
|
+
latLng,
|
2091
|
+
function(result) {
|
2092
|
+
var zoom = result.status === google.maps.MaxZoomStatus.OK ? result.zoom : false;
|
2093
|
+
callback.apply($this, [zoom, result.status]);
|
2094
|
+
that._end();
|
2095
|
+
}
|
2096
|
+
);
|
2097
|
+
} else {
|
2098
|
+
this._end();
|
2099
|
+
}
|
2100
|
+
}
|
2101
|
+
|
2102
|
+
/**
|
2103
|
+
* modify default values
|
2104
|
+
**/
|
2105
|
+
this.setdefault = function(todo){
|
2106
|
+
setDefault(todo);
|
2107
|
+
this._end();
|
2108
|
+
}
|
2109
|
+
|
2110
|
+
/**
|
2111
|
+
* autofit a map using its overlays (markers, rectangles ...)
|
2112
|
+
**/
|
2113
|
+
this.autofit = function(todo, internal){
|
2114
|
+
var names, list, obj, i, j,
|
2115
|
+
empty = true,
|
2116
|
+
bounds = new google.maps.LatLngBounds(),
|
2117
|
+
maxZoom = ival(todo, 'maxZoom', null);
|
2118
|
+
|
2119
|
+
names = store.names();
|
2120
|
+
for(i=0; i<names.length; i++){
|
2121
|
+
list = store.all(names[i]);
|
2122
|
+
for(j=0; j<list.length; j++){
|
2123
|
+
obj = list[j];
|
2124
|
+
if (obj.getPosition){
|
2125
|
+
bounds.extend(obj.getPosition());
|
2126
|
+
empty = false;
|
2127
|
+
} else if (obj.getBounds){
|
2128
|
+
bounds.extend(obj.getBounds().getNorthEast());
|
2129
|
+
bounds.extend(obj.getBounds().getSouthWest());
|
2130
|
+
empty = false;
|
2131
|
+
} else if (obj.getPaths){
|
2132
|
+
obj.getPaths().forEach(function(path){
|
2133
|
+
path.forEach(function(latLng){
|
2134
|
+
bounds.extend(latLng);
|
2135
|
+
empty = false;
|
2136
|
+
});
|
2137
|
+
});
|
2138
|
+
} else if (obj.getPath){
|
2139
|
+
obj.getPath().forEach(function(latLng){
|
2140
|
+
bounds.extend(latLng);
|
2141
|
+
empty = false;
|
2142
|
+
});
|
2143
|
+
} else if (obj.getCenter){
|
2144
|
+
bounds.extend(obj.getCenter());
|
2145
|
+
empty = false;
|
2146
|
+
}
|
2147
|
+
}
|
2148
|
+
}
|
2149
|
+
|
2150
|
+
if (!empty && (!map.getBounds() || !map.getBounds().equals(bounds))){
|
2151
|
+
if (maxZoom !== null){
|
2152
|
+
// fitBouds Callback event => detect zoom level and check maxZoom
|
2153
|
+
google.maps.event.addListenerOnce(
|
2154
|
+
map,
|
2155
|
+
'bounds_changed',
|
2156
|
+
function() {
|
2157
|
+
if (this.getZoom() > maxZoom){
|
2158
|
+
this.setZoom(maxZoom);
|
2159
|
+
}
|
2160
|
+
}
|
2161
|
+
);
|
2162
|
+
}
|
2163
|
+
map.fitBounds(bounds);
|
2164
|
+
}
|
2165
|
+
if (!internal){
|
2166
|
+
this._manageEnd(empty ? false : bounds, todo, internal);
|
2167
|
+
}
|
2168
|
+
}
|
2169
|
+
|
2170
|
+
};
|
2171
|
+
|
2172
|
+
//-----------------------------------------------------------------------//
|
2173
|
+
// jQuery plugin
|
2174
|
+
//-----------------------------------------------------------------------//
|
2175
|
+
|
2176
|
+
$.fn.gmap3 = function(){
|
2177
|
+
var i, args, list = [], empty = true, results = [];
|
2178
|
+
// store all arguments in a todo list
|
2179
|
+
for(i=0; i<arguments.length; i++){
|
2180
|
+
args = arguments[i] || {};
|
2181
|
+
// resolve string todo - action without parameters can be simplified as string
|
2182
|
+
if (typeof(args) === 'string'){
|
2183
|
+
args = {action:args};
|
2184
|
+
}
|
2185
|
+
list.push(args);
|
2186
|
+
}
|
2187
|
+
// resolve empty call - run init
|
2188
|
+
if (!list.length) {
|
2189
|
+
list.push({});
|
2190
|
+
}
|
2191
|
+
// loop on each jQuery object
|
2192
|
+
$.each(this, function() {
|
2193
|
+
var $this = $(this),
|
2194
|
+
gmap3 = $this.data('gmap3');
|
2195
|
+
empty = false;
|
2196
|
+
if (!gmap3){
|
2197
|
+
gmap3 = new Gmap3($this);
|
2198
|
+
$this.data('gmap3', gmap3);
|
2199
|
+
}
|
2200
|
+
// direct call : bypass jQuery method (not stackable, return mixed)
|
2201
|
+
if ( (list.length == 1) && (isDirect(list[0])) ){
|
2202
|
+
results.push(gmap3._direct(list[0]));
|
2203
|
+
} else {
|
2204
|
+
gmap3._plan(list);
|
2205
|
+
}
|
2206
|
+
});
|
2207
|
+
// return for direct call (only)
|
2208
|
+
if (results.length){
|
2209
|
+
if (results.length === 1){ // 1 css selector
|
2210
|
+
return results[0];
|
2211
|
+
} else {
|
2212
|
+
return results;
|
2213
|
+
}
|
2214
|
+
}
|
2215
|
+
// manage setDefault call
|
2216
|
+
if (empty && (arguments.length == 2) && (typeof(arguments[0]) === 'string') && (arguments[0].toLowerCase() === 'setdefault')){
|
2217
|
+
setDefault(arguments[1]);
|
2218
|
+
}
|
2219
|
+
return this;
|
2220
|
+
}
|
2221
|
+
|
2222
|
+
}(jQuery));
|