Newer
Older
* Drupal to Google Maps API bridge.
*/
/*global jQuery, Drupal, GLatLng, GSmallZoomControl, GLargeMapControl, GMap2 */
/*global GMapTypeControl, GSmallMapControl, G_HYBRID_MAP, G_NORMAL_MAP */
/*global G_PHYSICAL_MAP, G_SATELLITE_MAP, GHierarchicalMapTypeControl */
/*global GKeyboardHandler, GLatLngBounds, GMenuMapTypeControl, GEvent */
/*global GOverviewMapControl, GScaleControl, GUnload */
(function () { // BEGIN closure
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
var handlers = {};
var maps = {};
var ajaxoffset = 0;
Drupal.gmap = {
/**
* Retrieve a map object for use by a non-widget.
* Use this if you need to be able to fire events against a certain map
* which you have the mapid for.
* Be a good GMap citizen! Remember to send change()s after modifying variables!
*/
getMap: function (mapid) {
if (maps[mapid]) {
return maps[mapid];
}
else {
// Perhaps the user passed a widget id instead?
mapid = mapid.split('-').slice(1, -1).join('-');
if (maps[mapid]) {
return maps[mapid];
}
}
return false;
},
unloadMap: function (mapid) {
delete maps[mapid];
},
addHandler: function (handler, callback) {
if (!handlers[handler]) {
handlers[handler] = [];
}
handlers[handler].push(callback);
},
globalChange: function (name, userdata) {
for (var mapid in Drupal.settings.gmap) {
if (Drupal.settings.gmap.hasOwnProperty(mapid)) {
// Skip maps that are set up but not shown, etc.
if (maps[mapid]) {
maps[mapid].change(name, -1, userdata);
}
}
}
},
setup: function (settings) {
var obj = this;
var initcallback = function (mapid) {
return (function () {
maps[mapid].change("bootstrap_options", -1);
maps[mapid].change("boot", -1);
maps[mapid].change("init", -1);
// Send some changed events to fire up the rest of the initial settings..
maps[mapid].change("maptypechange", -1);
maps[mapid].change("controltypechange", -1);
maps[mapid].change("alignchange", -1);
// Set ready to put the event system into action.
maps[mapid].ready = true;
maps[mapid].change("ready", -1);
});
};
if (settings || (Drupal.settings && Drupal.settings.gmap)) {
var mapid = obj.id.split('-');
if (Drupal.settings['gmap_remap_widgets']) {
if (Drupal.settings['gmap_remap_widgets'][obj.id]) {
jQuery.each(Drupal.settings['gmap_remap_widgets'][obj.id].classes, function () {
jQuery(obj).addClass(this);
});
mapid = Drupal.settings['gmap_remap_widgets'][obj.id].id.split('-');
}
}
var instanceid = mapid.pop();
mapid.shift();
mapid = mapid.join('-');
var control = instanceid.replace(/\d+$/, '');
// Lazy init the map object.
if (!maps[mapid]) {
if (settings) {
maps[mapid] = new Drupal.gmap.map(settings);
}
else {
maps[mapid] = new Drupal.gmap.map(Drupal.settings.gmap[mapid]);
}
// Prepare the initialization callback.
var callback = initcallback(mapid);
setTimeout(callback, 0);
}
if (handlers[control]) {
for (var i = 0; i < handlers[control].length; i++) {
handlers[control][i].call(maps[mapid], obj);
}
}
else {
// Element with wrong class?
}
}
}
};
jQuery.fn.createGMap = function (settings, mapid) {
return this.each(function () {
if (!mapid) {
mapid = 'auto' + ajaxoffset + 'ajax';
ajaxoffset++;
}
settings.id = mapid;
jQuery(this)
.attr('id', 'gmap-' + mapid + '-gmap0')
.css('width', settings.width)
.css('height', settings.height)
.addClass('gmap-control')
.addClass('gmap-gmap')
.addClass('gmap')
.addClass('gmap-map')
.addClass('gmap-' + mapid + '-gmap')
.addClass('gmap-processed')
.each(function () {
Drupal.gmap.setup.call(this, settings)
});
});
};
})(); // END closure
Drupal.gmap.factory = {};
Drupal.gmap.map = function (v) {
this.vars = v;
this.map = undefined;
this.ready = false;
var _bindings = {};
* Register interest in a change.
this.bind = function (name, callback) {
if (!_bindings[name]) {
_bindings[name] = [];
return _bindings[name].push(callback) - 1;
};
/**
* Change notification.
* Interested parties can act on changes.
*/
this.change = function (name, id, userdata) {
var c;
if (_bindings[name]) {
for (c = 0; c < _bindings[name].length; c++) {
if (c !== id) {
_bindings[name][c](userdata);
}
}
}
if (name !== 'all') {
this.change('all', -1, name, userdata);
}
};
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/**
* Deferred change notification.
* This will cause a change notification to be tacked on to the *end* of the event queue.
*/
this.deferChange = function (name, id, userdata) {
var obj = this;
// This will move the function call to the end of the event loop.
setTimeout(function () {
obj.change(name, id, userdata);
}, 0);
};
this.getMapTypeName = function (type) {
if (type == 'map' || type == 'roadmap') return 'Map';
if (type == 'hybrid') return 'Hybrid';
if (type == 'physical' || type == 'terrain') return 'Physical';
if (type == 'satellite') return 'Satellite';
};
this.getMapTypeId = function (type) {
if (type == 'Map' || type == 'Roadmap') return google.maps.MapTypeId.ROADMAP;
if (type == 'Hybrid') return google.maps.MapTypeId.HYBRID;
if (type == 'Physical' || type == 'Terrain') return google.maps.MapTypeId.TERRAIN;
if (type == 'Satellite') return google.maps.MapTypeId.SATELLITE;
};
};
////////////////////////////////////////
// Map widget //
////////////////////////////////////////
Drupal.gmap.addHandler('gmap', function (elem) {
var obj = this;
var _ib = {};
// Respond to incoming zooms
_ib.zoom = obj.bind("zoom", function (zoom) {
obj.map.setZoom(obj.vars.zoom);
});
// Respond to incoming moves
_ib.move = obj.bind("move", function () {
obj.map.panTo(new google.maps.LatLng(obj.vars.latitude, obj.vars.longitude));
});
// Respond to incoming width changes.
_ib.width = obj.bind("widthchange", function (w) {
obj.map.getDiv().style.width = w;
google.maps.event.trigger(obj.map);
});
// Send out outgoing width changes.
// N/A
// Respond to incoming height changes.
_ib.height = obj.bind("heightchange", function (h) {
obj.map.getDiv().style.height = h;
google.maps.event.trigger(obj.map);
});
// Send out outgoing height changes.
// N/A
// Respond to incoming control type changes.
_ib.ctc = obj.bind("controltypechange", function () {
if (obj.vars.controltype === 'Small') {
obj.map.setOptions({zoomControlOptions: {style: google.maps.ZoomControlStyle.SMALL}});
else if (obj.vars.controltype === 'Large') {
obj.map.setOptions({zoomControlOptions: {style: google.maps.ZoomControlStyle.LARGE}});
// obsolete
else if (obj.vars.controltype === 'Android') {
obj.map.setOptions({zoomControlOptions: {style: google.maps.ZoomControlStyle.SMALL}});
// Send out outgoing control type changes.
// N/A
// Respond to incoming map type changes.
_ib.mtc = obj.bind("maptypechange", function () {
obj.map.setMapTypeId(obj.getMapTypeId(obj.vars.maptype));
});
// Send out outgoing map type changes.
// N/A
obj.bind("bootstrap_options", function () {
// Bootup options.
var opts = {}; // Object literal google.maps.MapOptions
obj.opts = opts;
// Disable default UI for custom options
opts.disableDefaultUI = true;
// Set draggable property
if (obj.vars.behavior.nodrag) {
opts.draggable = false;
}
else if (obj.vars.behavior.nokeyboard) {
opts.keyboardShortcuts = false;
// Set default map type (set to road map if nothing selected)
switch (obj.vars.maptype) {
case 'Hybrid':
opts.mapTypeId = google.maps.MapTypeId.HYBRID;
break;
case 'Physical':
opts.mapTypeId = google.maps.MapTypeId.TERRAIN;
break;
case 'Satellite':
opts.mapTypeId = google.maps.MapTypeId.SATELLITE;
break;
case 'Map':
default:
opts.mapTypeId = google.maps.MapTypeId.ROADMAP;
break;
}
// Null out the enabled types.
opts.mapTypeIds = [];
if (obj.vars.baselayers.Map) {
opts.mapTypeIds.push(google.maps.MapTypeId.ROADMAP);
}
if (obj.vars.baselayers.Hybrid) {
opts.mapTypeIds.push(google.maps.MapTypeId.HYBRID);
}
if (obj.vars.baselayers.Physical) {
opts.mapTypeIds.push(google.maps.MapTypeId.TERRAIN);
}
if (obj.vars.baselayers.Satellite) {
opts.mapTypeIds.push(google.maps.MapTypeId.SATELLITE);
}
if (obj.vars.draggableCursor) {
opts.draggableCursor = obj.vars.draggableCursor;
}
if (obj.vars.draggingCursor) {
opts.draggingCursor = obj.vars.draggingCursor;
}
if (obj.vars.backgroundColor) {
opts.backgroundColor = obj.vars.backgroundColor;
}
// Map type control
opts.mapTypeControl = true;
opts.mapTypeControlOptions = {};
if (obj.vars.mtc === 'standard') {
opts.mapTypeControlOptions.style = google.maps.MapTypeControlStyle.DEFAULT;
}
else if (obj.vars.mtc === 'horiz') {
opts.mapTypeControlOptions.style = google.maps.MapTypeControlStyle.HORIZONTAL_BAR;
}
else if (obj.vars.mtc === 'menu') {
opts.mapTypeControlOptions.style = google.maps.MapTypeControlStyle.DROPDOWN_MENU;
}
else if (obj.vars.mtc === 'none') {
opts.mapTypeControl = false;
}
// Navigation control type
if (obj.vars.controltype !== 'None') {
opts.zoomControl = true;
}
if (obj.vars.pancontrol) {
opts.panControl = true;
}
if (obj.vars.controltype === 'Small') {
obj.zoomControlOptions = {style: google.maps.ZoomControlStyle.SMALL};
}
else if (obj.vars.controltype === 'Large') {
obj.zoomControlOptions = {style: google.maps.ZoomControlStyle.LARGE};
// Set scale control visibility
opts.scaleControl = obj.vars.behavior.scale;
// Scroll wheel control
if (obj.vars.behavior.nomousezoom) {
opts.scrollwheel = false;
}
// Disable double-click zoom
if (obj.vars.behavior.nocontzoom) {
opts.disableDoubleClickZoom = true;
}
// Overview Map
if (obj.vars.behavior.overview) {
opts.overviewMapControl = true;
opts.overviewMapControlOptions = {opened: true};
}
obj.bind("boot", function () {
obj.map = new google.maps.Map(elem, obj.opts);
//console.log(obj.map);
});
obj.bind("init", function () {
var map = obj.map;
// Not implemented in API v3
// if (obj.vars.behavior.overview) {
// map.addControl(new GOverviewMapControl());
// }
// if (obj.vars.behavior.googlebar) {
// map.enableGoogleBar();
// }
if (obj.vars.extent) {
var c = obj.vars.extent;
var extent = new google.maps.LatLngBounds(new google.maps.LatLng(c[0][0], c[0][1]), new google.maps.LatLng(c[1][0], c[1][1]));
obj.vars.latitude = extent.getCenter().lat();
obj.vars.longitude = extent.getCenter().lng();
obj.vars.zoom = map.getBoundsZoomLevel(extent);
}
if (obj.vars.behavior.collapsehack) {
// Modify collapsable fieldsets to make maps check dom state when the resize handle
// is clicked. This may not necessarily be the correct thing to do in all themes,
// hence it being a behavior.
setTimeout(function () {
var r = function () {
var coord = map.getCenter();
google.maps.event.trigger(map, "resize");
map.setCenter(new google.maps.LatLng(coord.lat(), coord.lng()), obj.vars.zoom);
};
jQuery(elem).parents('fieldset.collapsible').children('legend').children('a').click(r);
jQuery('.vertical-tab-button', jQuery(elem).parents('.vertical-tabs')).children('a').click(r);
jQuery(window).bind('hashchange', r);
// Would be nice, but doesn't work.
//$(elem).parents('fieldset.collapsible').children('.fieldset-wrapper').scroll(r);
}, 0);
}
map.setCenter(new google.maps.LatLng(obj.vars.latitude, obj.vars.longitude));
map.setZoom(obj.vars.zoom);
// Send out outgoing zooms
google.maps.event.addListener(map, "zoom_changed", function () {
obj.vars.zoom = map.getZoom();
obj.change("zoom", _ib.zoom);
});
// Send out outgoing moves
google.maps.event.addListener(map, "center_changed", function () {
var coord = map.getCenter();
obj.vars.latitude = coord.lat();
obj.vars.longitude = coord.lng();
obj.change("move", _ib.move);
});
// Send out outgoing map type changes.
google.maps.event.addListener(map, "maptypeid_changed", function () {
// If the map isn't ready yet, ignore it.
if (obj.ready) {
obj.vars.maptype = obj.getMapTypeName(map.getMapTypeId());
obj.change("maptypechange", _ib.mtc);
}
});
/*
google.maps.event.addListener(map, 'click', function(event) {
alert(Drupal.gmap.getIcon("big blue", 0));
var marker = new google.maps.Marker({
position: event.latLng,
map: map
});
google.maps.event.addListener(marker, 'click', function() {
marker.setMap(null);
});
});
*/
});
////////////////////////////////////////
// Zoom widget //
////////////////////////////////////////
var obj = this;
// Respond to incoming zooms
var binding = obj.bind("zoom", function () {
elem.value = obj.vars.zoom;
});
// Send out outgoing zooms
jQuery(elem).change(function () {
obj.vars.zoom = parseInt(elem.value, 10);
obj.change("zoom", binding);
});
});
////////////////////////////////////////
// Latitude widget //
////////////////////////////////////////
Drupal.gmap.addHandler('latitude', function (elem) {
// var obj = this;
// // Respond to incoming movements.
// var binding = obj.bind("move", function () {
// elem.value = '' + obj.vars.latitude;
// });
// // Send out outgoing movements.
// $(elem).change(function () {
// obj.vars.latitude = Number(this.value);
// obj.change("move", binding);
// });
});
////////////////////////////////////////
// Longitude widget //
////////////////////////////////////////
Drupal.gmap.addHandler('longitude', function (elem) {
// var obj = this;
// // Respond to incoming movements.
// var binding = obj.bind("move", function () {
// elem.value = '' + obj.vars.longitude;
// });
// // Send out outgoing movements.
// $(elem).change(function () {
// obj.vars.longitude = Number(this.value);
// obj.change("move", binding);
// });
});
////////////////////////////////////////
// Latlon widget //
////////////////////////////////////////
var obj = this;
// Respond to incoming movements.
var binding = obj.bind("move", function () {
elem.value = '' + obj.vars.latitude + ',' + obj.vars.longitude;
});
// Send out outgoing movements.
jQuery(elem).change(function () {
var t = this.value.split(',');
obj.vars.latitude = Number(t[0]);
obj.vars.longitude = Number(t[1]);
obj.change("move", binding);
});
});
////////////////////////////////////////
// Maptype widget //
////////////////////////////////////////
Drupal.gmap.addHandler('maptype', function (elem) {
var obj = this;
// Respond to incoming movements.
var binding = obj.bind("maptypechange", function () {
elem.value = obj.vars.maptype;
// Send out outgoing movements.
jQuery(elem).change(function () {
obj.vars.maptype = elem.value;
obj.change("maptypechange", binding);
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
});
(function () { // BEGIN CLOSURE
var re = /([0-9.]+)\s*(em|ex|px|in|cm|mm|pt|pc|%)/;
var normalize = function (str) {
var ar;
if ((ar = re.exec(str.toLowerCase()))) {
return ar[1] + ar[2];
}
return null;
};
////////////////////////////////////////
// Width widget //
////////////////////////////////////////
Drupal.gmap.addHandler('width', function (elem) {
var obj = this;
// Respond to incoming width changes.
var binding = obj.bind("widthchange", function (w) {
elem.value = normalize(w);
});
// Send out outgoing width changes.
jQuery(elem).change(function () {
var n;
if ((n = normalize(elem.value))) {
elem.value = n;
obj.change('widthchange', binding, n);
}
});
obj.bind('init', function () {
jQuery(elem).change();
});
////////////////////////////////////////
// Height widget //
////////////////////////////////////////
Drupal.gmap.addHandler('height', function (elem) {
var obj = this;
// Respond to incoming height changes.
var binding = obj.bind("heightchange", function (h) {
elem.value = normalize(h);
});
// Send out outgoing height changes.
jQuery(elem).change(function () {
var n;
if ((n = normalize(elem.value))) {
elem.value = n;
obj.change('heightchange', binding, n);
}
});
obj.bind('init', function () {
jQuery(elem).change();
});
})(); // END CLOSURE
////////////////////////////////////////
// Control type widget //
////////////////////////////////////////
Drupal.gmap.addHandler('controltype', function (elem) {
var obj = this;
// Respond to incoming height changes.
var binding = obj.bind("controltypechange", function () {
elem.value = obj.vars.controltype;
});
// Send out outgoing height changes.
jQuery(elem).change(function () {
obj.vars.controltype = elem.value
obj.change("controltypechange", binding);
});
// // Map cleanup.
// if (Drupal.jsEnabled) {
// $(document).unload(GUnload);
// }
Drupal.behaviors.GMap = {
attach: function (context, settings) {
if (Drupal.settings && Drupal.settings['gmap_remap_widgets']) {
jQuery.each(Drupal.settings['gmap_remap_widgets'], function (key, val) {
jQuery('#' + key).addClass('gmap-control');
});
}
jQuery('.gmap-gmap:not(.gmap-processed)', context).addClass('gmap-processed').each(function () {
Drupal.gmap.setup.call(this)
});
jQuery('.gmap-control:not(.gmap-processed)', context).addClass('gmap-processed').each(function () {
Drupal.gmap.setup.call(this)
});
},
detach: function (context, settings) {
jQuery('.gmap-processed', context).each(function (element) {
//find mapid
var id = jQuery(this).attr('id');
var mapid = id.split('-', 2);
//unload map
Drupal.gmap.unloadMap(mapid[1]);
});
}