From 345be39958137986a74ff116f22bdbfed551d8e9 Mon Sep 17 00:00:00 2001 From: otrok7 <50595291+otrok7@users.noreply.github.com> Date: Wed, 6 Dec 2023 22:50:11 +0100 Subject: [PATCH] add spiderify to gMaps --- croutonjs/meetingMap/js/gmapsDelegate.js | 65 ++- croutonjs/meetingMap/js/meeting_map.js | 4 +- croutonjs/meetingMap/js/oms-1.0.3.min.js | 687 +++++++++++++++++++++++ croutonjs/meetingMap/js/osmDelegate.js | 4 +- croutonjs/meetingMap/meeting_map.php | 1 + croutonjs/src/js/crouton-core.js | 4 +- gulpfile.js | 1 + 7 files changed, 753 insertions(+), 13 deletions(-) create mode 100644 croutonjs/meetingMap/js/oms-1.0.3.min.js diff --git a/croutonjs/meetingMap/js/gmapsDelegate.js b/croutonjs/meetingMap/js/gmapsDelegate.js index b83fd706..93262a22 100644 --- a/croutonjs/meetingMap/js/gmapsDelegate.js +++ b/croutonjs/meetingMap/js/gmapsDelegate.js @@ -6,6 +6,8 @@ function MapDelegate(in_config) { var g_icon_shadow = null; var g_icon_shape = null; var gMainMap; + var gOms = null; + var gMarkerClusterer = null; var gInfoWindow; var gIsLoaded = false; var gIsClustering = false; @@ -18,7 +20,6 @@ function MapDelegate(in_config) { gIsLoaded = true; if (typeof config['api_key'] === 'undefined') config['api_key'] = ""; tag.src = "https://maps.googleapis.com/maps/api/js?key=" + config['api_key'] + "&callback=croutonMap.apiLoadedCallback"; - //tag.src = "https://maps.googleapis.com/maps/api/js?callback=croutonMap.apiLoadedCallback"; tag.defer = true; tag.async = true; var firstScriptTag = document.getElementsByTagName('script')[0]; @@ -34,13 +35,14 @@ function MapDelegate(in_config) { var myOptions = { 'mapTypeId': google.maps.MapTypeId.ROADMAP, 'zoomControl': true, - 'minZoom': 6, + 'minZoom': config.minZoom, + 'maxZoom': config.maxZoom, 'mapTypeControl': false, 'streetViewControl': false, 'disableDoubleClickZoom' : true, 'draggableCursor': "pointer", 'scaleControl' : true, - 'fullscreenControl': false, + 'fullscreenControl': config.map_search ? true : false, }; if (inCenter) { myOptions = Object.assign(myOptions, { @@ -79,12 +81,15 @@ function MapDelegate(in_config) { } function fitBounds(locations) { google.maps.event.addListenerOnce(gMainMap, "bounds_changed", function () { - this.setZoom(Math.min(this.getZoom(), 17)); + gMainMap.setZoom(parseInt(Math.min(gMainMap.getZoom(), config.maxZoom))); }); + let start = new google.maps.LatLngBounds(); // avoid occasional timing problem + if (!start) return; const bounds = locations.reduce( function (bounds, m) { + if (bounds === null) return start; return bounds.extend(new google.maps.LatLng(m[0], m[1])); - }, new google.maps.LatLngBounds()); + }, start); gMainMap.fitBounds(bounds); } function setViewToPosition(position, filterMeetings, f) { @@ -171,12 +176,54 @@ function MapDelegate(in_config) { gIsClustering =false; gMarkerClusterer && gMarkerClusterer.setMap(null); gMarkerClusterer = null; + if (gOms) { + gOms.removeAllMarkers(); + gOms.clearListeners('click'); + gOms = null; + } } -var gMarkerClusterer = null; function addClusterLayer() { let markers = gAllMarkers.map((m)=>m.marker); - if (gIsClustering) gMarkerClusterer = new markerClusterer.MarkerClusterer( { 'map': gMainMap, 'markers': markers, 'imagePath': 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m'} ); - else markers.forEach((m)=>m.setMap(gMainMap)); + if (gIsClustering) { + gMarkerClusterer = new markerClusterer.MarkerClusterer( { 'map': gMainMap, 'markers': markers, 'imagePath': 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m'} ); + gOms = new OverlappingMarkerSpiderfier(gMainMap, { + markersWontMove: true, + markersWontHide: true, + }); + gOms.addListener('format', function (marker, status) { + var icon; + if (status === OverlappingMarkerSpiderfier.markerStatus.SPIDERFIED + || status === OverlappingMarkerSpiderfier.markerStatus.SPIDERFIABLE + || status === OverlappingMarkerSpiderfier.markerStatus.UNSPIDERFIED) { + icon = g_icon_image_multi; + } else if (status === OverlappingMarkerSpiderfier.markerStatus.UNSPIDERFIABLE) { + icon = g_icon_image_single; + } else { + icon = null; + } + marker.setIcon(icon); + }); + google.maps.event.addListener(gMainMap, 'zoom_changed', function() { + if (gMainMap.getProjection()=='undefined') return; + google.maps.event.addListenerOnce(gMainMap, 'idle', function() { + if (gMainMap.getProjection()=='undefined') return; + if (gOms == null) return; + var spidered = gOms.markersNearAnyOtherMarker(); + for (var i = 0; i < spidered.length; i ++) { + spidered[i].icon = g_icon_image_multi; + } + }); + }); + + // This is necessary to make the Spiderfy work + gOms.addListener('click', function (marker) { + marker.zIndex = 999; + gInfoWindow.setContent(marker.desc); + gInfoWindow.open(gMainMap, marker); + }); + markers.forEach((marker)=>gOms.addMarker(marker)); + + } else markers.forEach((m)=>m.setMap(gMainMap)); } function createMarker ( inCoords, ///< The long/lat for the marker. multi, @@ -233,9 +280,11 @@ function addControl(div,pos) { switch(pos) { case 'topright': p = google.maps.ControlPosition.TOP_RIGHT; + div.style.margin = "10px 10px 0 0"; break; case 'topleft': p = google.maps.ControlPosition.TOP_LEFT; + div.style.margin = "10px 0 0 10px"; break; } div.index = 1; diff --git a/croutonjs/meetingMap/js/meeting_map.js b/croutonjs/meetingMap/js/meeting_map.js index b5c87ac0..fd600864 100644 --- a/croutonjs/meetingMap/js/meeting_map.js +++ b/croutonjs/meetingMap/js/meeting_map.js @@ -18,6 +18,8 @@ function MeetingMap(inConfig) { config.zoom = config.map_search.zoom; } } + if (!config.maxZoom) config.maxZoom = 17; + if (!config.minZoom) config.minZoom = 6; var gAllMeetings = null; var gMeetingIdsFromCrouton = null; var loadedCallbackFunction = null; @@ -186,7 +188,6 @@ function MeetingMap(inConfig) { }; }; function mapSearchGeocode(resp) { - console.log(resp); let latlng = gDelegate.getGeocodeCenter(resp); crouton.searchByCoordinates(latlng.lat, latlng.lng, config.map_search.width); } @@ -445,7 +446,6 @@ function MeetingMap(inConfig) { marker_html, null ,meetings.map((m)=>parseInt(m.id_bigint))); }; function filterBounds(bounds) { - console.log(bounds); return gAllMeetings.filter((meeting) => gDelegate.contains(bounds, meeting.latitude, meeting.longitude)); } function filterVisible(on=true) { diff --git a/croutonjs/meetingMap/js/oms-1.0.3.min.js b/croutonjs/meetingMap/js/oms-1.0.3.min.js new file mode 100644 index 00000000..811d3645 --- /dev/null +++ b/croutonjs/meetingMap/js/oms-1.0.3.min.js @@ -0,0 +1,687 @@ +// Generated by CoffeeScript 1.12.2 + +/** @preserve OverlappingMarkerSpiderfier +https://github.com/jawj/OverlappingMarkerSpiderfier +Copyright (c) 2011 - 2017 George MacKerron +Released under the MIT licence: http://opensource.org/licenses/mit-license +Note: The Google Maps API v3 must be included *before* this code + */ + +(function() { + var callbackName, callbackRegEx, ref, ref1, scriptTag, tag, + hasProp = {}.hasOwnProperty, + slice = [].slice; + + this['OverlappingMarkerSpiderfier'] = (function() { + var ge, gm, j, len, mt, p, ref, twoPi, x; + + p = _Class.prototype; + + ref = [_Class, p]; + for (j = 0, len = ref.length; j < len; j++) { + x = ref[j]; + x['VERSION'] = '1.0.3'; + } + + twoPi = Math.PI * 2; + + gm = ge = mt = null; + + _Class['markerStatus'] = { + 'SPIDERFIED': 'SPIDERFIED', + 'SPIDERFIABLE': 'SPIDERFIABLE', + 'UNSPIDERFIABLE': 'UNSPIDERFIABLE', + 'UNSPIDERFIED': 'UNSPIDERFIED' + }; + + function _Class(map1, opts) { + var k, lcH, lcU, v; + this.map = map1; + if (opts == null) { + opts = {}; + } + if (this.constructor.hasInitialized == null) { + this.constructor.hasInitialized = true; + gm = google.maps; + ge = gm.event; + mt = gm.MapTypeId; + p['keepSpiderfied'] = false; + p['ignoreMapClick'] = false; + p['markersWontHide'] = false; + p['markersWontMove'] = false; + p['basicFormatEvents'] = false; + p['nearbyDistance'] = 20; + p['circleSpiralSwitchover'] = 9; + p['circleFootSeparation'] = 23; + p['circleStartAngle'] = twoPi / 12; + p['spiralFootSeparation'] = 26; + p['spiralLengthStart'] = 11; + p['spiralLengthFactor'] = 4; + p['spiderfiedZIndex'] = gm.Marker.MAX_ZINDEX + 20000; + p['highlightedLegZIndex'] = gm.Marker.MAX_ZINDEX + 10000; + p['usualLegZIndex'] = gm.Marker.MAX_ZINDEX + 1; + p['legWeight'] = 1.5; + p['legColors'] = { + 'usual': {}, + 'highlighted': {} + }; + lcU = p['legColors']['usual']; + lcH = p['legColors']['highlighted']; + lcU[mt.HYBRID] = lcU[mt.SATELLITE] = '#fff'; + lcH[mt.HYBRID] = lcH[mt.SATELLITE] = '#f00'; + lcU[mt.TERRAIN] = lcU[mt.ROADMAP] = '#444'; + lcH[mt.TERRAIN] = lcH[mt.ROADMAP] = '#f00'; + this.constructor.ProjHelper = function(map) { + return this.setMap(map); + }; + this.constructor.ProjHelper.prototype = new gm.OverlayView(); + this.constructor.ProjHelper.prototype['draw'] = function() {}; + } + for (k in opts) { + if (!hasProp.call(opts, k)) continue; + v = opts[k]; + this[k] = v; + } + this.projHelper = new this.constructor.ProjHelper(this.map); + this.initMarkerArrays(); + this.listeners = {}; + this.formatIdleListener = this.formatTimeoutId = null; + this.addListener('click', function(marker, e) { + return ge.trigger(marker, 'spider_click', e); + }); + this.addListener('format', function(marker, status) { + return ge.trigger(marker, 'spider_format', status); + }); + if (!this['ignoreMapClick']) { + ge.addListener(this.map, 'click', (function(_this) { + return function() { + return _this['unspiderfy'](); + }; + })(this)); + } + ge.addListener(this.map, 'maptypeid_changed', (function(_this) { + return function() { + return _this['unspiderfy'](); + }; + })(this)); + ge.addListener(this.map, 'zoom_changed', (function(_this) { + return function() { + _this['unspiderfy'](); + if (!_this['basicFormatEvents']) { + return _this.formatMarkers(); + } + }; + })(this)); + } + + p.initMarkerArrays = function() { + this.markers = []; + return this.markerListenerRefs = []; + }; + + p['addMarker'] = function(marker, spiderClickHandler) { + marker.setMap(this.map); + return this['trackMarker'](marker, spiderClickHandler); + }; + + p['trackMarker'] = function(marker, spiderClickHandler) { + var listenerRefs; + if (marker['_oms'] != null) { + return this; + } + marker['_oms'] = true; + listenerRefs = [ + ge.addListener(marker, 'click', (function(_this) { + return function(e) { + return _this.spiderListener(marker, e); + }; + })(this)) + ]; + if (!this['markersWontHide']) { + listenerRefs.push(ge.addListener(marker, 'visible_changed', (function(_this) { + return function() { + return _this.markerChangeListener(marker, false); + }; + })(this))); + } + if (!this['markersWontMove']) { + listenerRefs.push(ge.addListener(marker, 'position_changed', (function(_this) { + return function() { + return _this.markerChangeListener(marker, true); + }; + })(this))); + } + if (spiderClickHandler != null) { + listenerRefs.push(ge.addListener(marker, 'spider_click', spiderClickHandler)); + } + this.markerListenerRefs.push(listenerRefs); + this.markers.push(marker); + if (this['basicFormatEvents']) { + this.trigger('format', marker, this.constructor['markerStatus']['UNSPIDERFIED']); + } else { + this.trigger('format', marker, this.constructor['markerStatus']['UNSPIDERFIABLE']); + this.formatMarkers(); + } + return this; + }; + + p.markerChangeListener = function(marker, positionChanged) { + if (this.spiderfying || this.unspiderfying) { + return; + } + if ((marker['_omsData'] != null) && (positionChanged || !marker.getVisible())) { + this['unspiderfy'](positionChanged ? marker : null); + } + return this.formatMarkers(); + }; + + p['getMarkers'] = function() { + return this.markers.slice(0); + }; + + p['removeMarker'] = function(marker) { + this['forgetMarker'](marker); + return marker.setMap(null); + }; + + p['forgetMarker'] = function(marker) { + var i, l, len1, listenerRef, listenerRefs; + if (marker['_omsData'] != null) { + this['unspiderfy'](); + } + i = this.arrIndexOf(this.markers, marker); + if (i < 0) { + return this; + } + listenerRefs = this.markerListenerRefs.splice(i, 1)[0]; + for (l = 0, len1 = listenerRefs.length; l < len1; l++) { + listenerRef = listenerRefs[l]; + ge.removeListener(listenerRef); + } + delete marker['_oms']; + this.markers.splice(i, 1); + this.formatMarkers(); + return this; + }; + + p['removeAllMarkers'] = p['clearMarkers'] = function() { + var l, len1, marker, markers; + markers = this['getMarkers'](); + this['forgetAllMarkers'](); + for (l = 0, len1 = markers.length; l < len1; l++) { + marker = markers[l]; + marker.setMap(null); + } + return this; + }; + + p['forgetAllMarkers'] = function() { + var i, l, len1, len2, listenerRef, listenerRefs, marker, n, ref1; + this['unspiderfy'](); + ref1 = this.markers; + for (i = l = 0, len1 = ref1.length; l < len1; i = ++l) { + marker = ref1[i]; + listenerRefs = this.markerListenerRefs[i]; + for (n = 0, len2 = listenerRefs.length; n < len2; n++) { + listenerRef = listenerRefs[n]; + ge.removeListener(listenerRef); + } + delete marker['_oms']; + } + this.initMarkerArrays(); + return this; + }; + + p['addListener'] = function(eventName, func) { + var base; + ((base = this.listeners)[eventName] != null ? base[eventName] : base[eventName] = []).push(func); + return this; + }; + + p['removeListener'] = function(eventName, func) { + var i; + i = this.arrIndexOf(this.listeners[eventName], func); + if (!(i < 0)) { + this.listeners[eventName].splice(i, 1); + } + return this; + }; + + p['clearListeners'] = function(eventName) { + this.listeners[eventName] = []; + return this; + }; + + p.trigger = function() { + var args, eventName, func, l, len1, ref1, ref2, results; + eventName = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : []; + ref2 = (ref1 = this.listeners[eventName]) != null ? ref1 : []; + results = []; + for (l = 0, len1 = ref2.length; l < len1; l++) { + func = ref2[l]; + results.push(func.apply(null, args)); + } + return results; + }; + + p.generatePtsCircle = function(count, centerPt) { + var angle, angleStep, circumference, i, l, legLength, ref1, results; + circumference = this['circleFootSeparation'] * (2 + count); + legLength = circumference / twoPi; + angleStep = twoPi / count; + results = []; + for (i = l = 0, ref1 = count; 0 <= ref1 ? l < ref1 : l > ref1; i = 0 <= ref1 ? ++l : --l) { + angle = this['circleStartAngle'] + i * angleStep; + results.push(new gm.Point(centerPt.x + legLength * Math.cos(angle), centerPt.y + legLength * Math.sin(angle))); + } + return results; + }; + + p.generatePtsSpiral = function(count, centerPt) { + var angle, i, l, legLength, pt, ref1, results; + legLength = this['spiralLengthStart']; + angle = 0; + results = []; + for (i = l = 0, ref1 = count; 0 <= ref1 ? l < ref1 : l > ref1; i = 0 <= ref1 ? ++l : --l) { + angle += this['spiralFootSeparation'] / legLength + i * 0.0005; + pt = new gm.Point(centerPt.x + legLength * Math.cos(angle), centerPt.y + legLength * Math.sin(angle)); + legLength += twoPi * this['spiralLengthFactor'] / angle; + results.push(pt); + } + return results; + }; + + p.spiderListener = function(marker, e) { + var l, len1, m, mPt, markerPt, markerSpiderfied, nDist, nearbyMarkerData, nonNearbyMarkers, pxSq, ref1; + markerSpiderfied = marker['_omsData'] != null; + if (!(markerSpiderfied && this['keepSpiderfied'])) { + this['unspiderfy'](); + } + if (markerSpiderfied || this.map.getStreetView().getVisible() || this.map.getMapTypeId() === 'GoogleEarthAPI') { + return this.trigger('click', marker, e); + } else { + nearbyMarkerData = []; + nonNearbyMarkers = []; + nDist = this['nearbyDistance']; + pxSq = nDist * nDist; + markerPt = this.llToPt(marker.position); + ref1 = this.markers; + for (l = 0, len1 = ref1.length; l < len1; l++) { + m = ref1[l]; + if (!((m.map != null) && m.getVisible())) { + continue; + } + mPt = this.llToPt(m.position); + if (this.ptDistanceSq(mPt, markerPt) < pxSq) { + nearbyMarkerData.push({ + marker: m, + markerPt: mPt + }); + } else { + nonNearbyMarkers.push(m); + } + } + if (nearbyMarkerData.length === 1) { + return this.trigger('click', marker, e); + } else { + return this.spiderfy(nearbyMarkerData, nonNearbyMarkers); + } + } + }; + + p['markersNearMarker'] = function(marker, firstOnly) { + var l, len1, m, mPt, markerPt, markers, nDist, pxSq, ref1, ref2, ref3; + if (firstOnly == null) { + firstOnly = false; + } + if (this.projHelper.getProjection() == null) { + throw "Must wait for 'idle' event on map before calling markersNearMarker"; + } + nDist = this['nearbyDistance']; + pxSq = nDist * nDist; + markerPt = this.llToPt(marker.position); + markers = []; + ref1 = this.markers; + for (l = 0, len1 = ref1.length; l < len1; l++) { + m = ref1[l]; + if (m === marker || (m.map == null) || !m.getVisible()) { + continue; + } + mPt = this.llToPt((ref2 = (ref3 = m['_omsData']) != null ? ref3.usualPosition : void 0) != null ? ref2 : m.position); + if (this.ptDistanceSq(mPt, markerPt) < pxSq) { + markers.push(m); + if (firstOnly) { + break; + } + } + } + return markers; + }; + + p.markerProximityData = function() { + var i1, i2, l, len1, len2, m, m1, m1Data, m2, m2Data, mData, n, nDist, pxSq, ref1, ref2; + if (this.projHelper.getProjection() == null) { + throw "Must wait for 'idle' event on map before calling markersNearAnyOtherMarker"; + } + nDist = this['nearbyDistance']; + pxSq = nDist * nDist; + mData = (function() { + var l, len1, ref1, ref2, ref3, results; + ref1 = this.markers; + results = []; + for (l = 0, len1 = ref1.length; l < len1; l++) { + m = ref1[l]; + results.push({ + pt: this.llToPt((ref2 = (ref3 = m['_omsData']) != null ? ref3.usualPosition : void 0) != null ? ref2 : m.position), + willSpiderfy: false + }); + } + return results; + }).call(this); + ref1 = this.markers; + for (i1 = l = 0, len1 = ref1.length; l < len1; i1 = ++l) { + m1 = ref1[i1]; + if (!((m1.getMap() != null) && m1.getVisible())) { + continue; + } + m1Data = mData[i1]; + if (m1Data.willSpiderfy) { + continue; + } + ref2 = this.markers; + for (i2 = n = 0, len2 = ref2.length; n < len2; i2 = ++n) { + m2 = ref2[i2]; + if (i2 === i1) { + continue; + } + if (!((m2.getMap() != null) && m2.getVisible())) { + continue; + } + m2Data = mData[i2]; + if (i2 < i1 && !m2Data.willSpiderfy) { + continue; + } + if (this.ptDistanceSq(m1Data.pt, m2Data.pt) < pxSq) { + m1Data.willSpiderfy = m2Data.willSpiderfy = true; + break; + } + } + } + return mData; + }; + + p['markersNearAnyOtherMarker'] = function() { + var i, l, len1, m, mData, ref1, results; + mData = this.markerProximityData(); + ref1 = this.markers; + results = []; + for (i = l = 0, len1 = ref1.length; l < len1; i = ++l) { + m = ref1[i]; + if (mData[i].willSpiderfy) { + results.push(m); + } + } + return results; + }; + + p.setImmediate = function(func) { + return window.setTimeout(func, 0); + }; + + p.formatMarkers = function() { + if (this['basicFormatEvents']) { + return; + } + if (this.formatTimeoutId != null) { + return; + } + return this.formatTimeoutId = this.setImmediate((function(_this) { + return function() { + _this.formatTimeoutId = null; + if (_this.projHelper.getProjection() != null) { + return _this._formatMarkers(); + } else { + if (_this.formatIdleListener != null) { + return; + } + return _this.formatIdleListener = ge.addListenerOnce(_this.map, 'idle', function() { + return _this._formatMarkers(); + }); + } + }; + })(this)); + }; + + p._formatMarkers = function() { + var i, l, len1, len2, marker, n, proximities, ref1, results, results1, status; + if (this['basicFormatEvents']) { + results = []; + for (l = 0, len1 = markers.length; l < len1; l++) { + marker = markers[l]; + status = marker['_omsData'] != null ? 'SPIDERFIED' : 'UNSPIDERFIED'; + results.push(this.trigger('format', marker, this.constructor['markerStatus'][status])); + } + return results; + } else { + proximities = this.markerProximityData(); + ref1 = this.markers; + results1 = []; + for (i = n = 0, len2 = ref1.length; n < len2; i = ++n) { + marker = ref1[i]; + status = marker['_omsData'] != null ? 'SPIDERFIED' : proximities[i].willSpiderfy ? 'SPIDERFIABLE' : 'UNSPIDERFIABLE'; + results1.push(this.trigger('format', marker, this.constructor['markerStatus'][status])); + } + return results1; + } + }; + + p.makeHighlightListenerFuncs = function(marker) { + return { + highlight: (function(_this) { + return function() { + return marker['_omsData'].leg.setOptions({ + strokeColor: _this['legColors']['highlighted'][_this.map.mapTypeId], + zIndex: _this['highlightedLegZIndex'] + }); + }; + })(this), + unhighlight: (function(_this) { + return function() { + return marker['_omsData'].leg.setOptions({ + strokeColor: _this['legColors']['usual'][_this.map.mapTypeId], + zIndex: _this['usualLegZIndex'] + }); + }; + })(this) + }; + }; + + p.spiderfy = function(markerData, nonNearbyMarkers) { + var bodyPt, footLl, footPt, footPts, highlightListenerFuncs, leg, marker, md, nearestMarkerDatum, numFeet, spiderfiedMarkers; + this.spiderfying = true; + numFeet = markerData.length; + bodyPt = this.ptAverage((function() { + var l, len1, results; + results = []; + for (l = 0, len1 = markerData.length; l < len1; l++) { + md = markerData[l]; + results.push(md.markerPt); + } + return results; + })()); + footPts = numFeet >= this['circleSpiralSwitchover'] ? this.generatePtsSpiral(numFeet, bodyPt).reverse() : this.generatePtsCircle(numFeet, bodyPt); + spiderfiedMarkers = (function() { + var l, len1, results; + results = []; + for (l = 0, len1 = footPts.length; l < len1; l++) { + footPt = footPts[l]; + footLl = this.ptToLl(footPt); + nearestMarkerDatum = this.minExtract(markerData, (function(_this) { + return function(md) { + return _this.ptDistanceSq(md.markerPt, footPt); + }; + })(this)); + marker = nearestMarkerDatum.marker; + leg = new gm.Polyline({ + map: this.map, + path: [marker.position, footLl], + strokeColor: this['legColors']['usual'][this.map.mapTypeId], + strokeWeight: this['legWeight'], + zIndex: this['usualLegZIndex'] + }); + marker['_omsData'] = { + usualPosition: marker.getPosition(), + usualZIndex: marker.getZIndex(), + leg: leg + }; + if (this['legColors']['highlighted'][this.map.mapTypeId] !== this['legColors']['usual'][this.map.mapTypeId]) { + highlightListenerFuncs = this.makeHighlightListenerFuncs(marker); + marker['_omsData'].hightlightListeners = { + highlight: ge.addListener(marker, 'mouseover', highlightListenerFuncs.highlight), + unhighlight: ge.addListener(marker, 'mouseout', highlightListenerFuncs.unhighlight) + }; + } + this.trigger('format', marker, this.constructor['markerStatus']['SPIDERFIED']); + marker.setPosition(footLl); + marker.setZIndex(Math.round(this['spiderfiedZIndex'] + footPt.y)); + results.push(marker); + } + return results; + }).call(this); + delete this.spiderfying; + this.spiderfied = true; + return this.trigger('spiderfy', spiderfiedMarkers, nonNearbyMarkers); + }; + + p['unspiderfy'] = function(markerNotToMove) { + var l, len1, listeners, marker, nonNearbyMarkers, ref1, status, unspiderfiedMarkers; + if (markerNotToMove == null) { + markerNotToMove = null; + } + if (this.spiderfied == null) { + return this; + } + this.unspiderfying = true; + unspiderfiedMarkers = []; + nonNearbyMarkers = []; + ref1 = this.markers; + for (l = 0, len1 = ref1.length; l < len1; l++) { + marker = ref1[l]; + if (marker['_omsData'] != null) { + marker['_omsData'].leg.setMap(null); + if (marker !== markerNotToMove) { + marker.setPosition(marker['_omsData'].usualPosition); + } + marker.setZIndex(marker['_omsData'].usualZIndex); + listeners = marker['_omsData'].hightlightListeners; + if (listeners != null) { + ge.removeListener(listeners.highlight); + ge.removeListener(listeners.unhighlight); + } + delete marker['_omsData']; + if (marker !== markerNotToMove) { + status = this['basicFormatEvents'] ? 'UNSPIDERFIED' : 'SPIDERFIABLE'; + this.trigger('format', marker, this.constructor['markerStatus'][status]); + } + unspiderfiedMarkers.push(marker); + } else { + nonNearbyMarkers.push(marker); + } + } + delete this.unspiderfying; + delete this.spiderfied; + this.trigger('unspiderfy', unspiderfiedMarkers, nonNearbyMarkers); + return this; + }; + + p.ptDistanceSq = function(pt1, pt2) { + var dx, dy; + dx = pt1.x - pt2.x; + dy = pt1.y - pt2.y; + return dx * dx + dy * dy; + }; + + p.ptAverage = function(pts) { + var l, len1, numPts, pt, sumX, sumY; + sumX = sumY = 0; + for (l = 0, len1 = pts.length; l < len1; l++) { + pt = pts[l]; + sumX += pt.x; + sumY += pt.y; + } + numPts = pts.length; + return new gm.Point(sumX / numPts, sumY / numPts); + }; + + p.llToPt = function(ll) { + return this.projHelper.getProjection().fromLatLngToDivPixel(ll); + }; + + p.ptToLl = function(pt) { + return this.projHelper.getProjection().fromDivPixelToLatLng(pt); + }; + + p.minExtract = function(set, func) { + var bestIndex, bestVal, index, item, l, len1, val; + for (index = l = 0, len1 = set.length; l < len1; index = ++l) { + item = set[index]; + val = func(item); + if ((typeof bestIndex === "undefined" || bestIndex === null) || val < bestVal) { + bestVal = val; + bestIndex = index; + } + } + return set.splice(bestIndex, 1)[0]; + }; + + p.arrIndexOf = function(arr, obj) { + var i, l, len1, o; + if (arr.indexOf != null) { + return arr.indexOf(obj); + } + for (i = l = 0, len1 = arr.length; l < len1; i = ++l) { + o = arr[i]; + if (o === obj) { + return i; + } + } + return -1; + }; + + return _Class; + + })(); + + callbackRegEx = /(\?.*(&|&)|\?)spiderfier_callback=(\w+)/; + + scriptTag = document.currentScript; + + if (scriptTag == null) { + scriptTag = ((function() { + var j, len, ref, ref1, results; + ref = document.getElementsByTagName('script'); + results = []; + for (j = 0, len = ref.length; j < len; j++) { + tag = ref[j]; + if ((ref1 = tag.getAttribute('src')) != null ? ref1.match(callbackRegEx) : void 0) { + results.push(tag); + } + } + return results; + })())[0]; + } + + if (scriptTag != null) { + callbackName = (ref = scriptTag.getAttribute('src')) != null ? (ref1 = ref.match(callbackRegEx)) != null ? ref1[3] : void 0 : void 0; + if (callbackName) { + if (typeof window[callbackName] === "function") { + window[callbackName](); + } + } + } + + if (typeof window['spiderfier_callback'] === "function") { + window['spiderfier_callback'](); + } + +}).call(this); diff --git a/croutonjs/meetingMap/js/osmDelegate.js b/croutonjs/meetingMap/js/osmDelegate.js index d8164da2..68db07bd 100644 --- a/croutonjs/meetingMap/js/osmDelegate.js +++ b/croutonjs/meetingMap/js/osmDelegate.js @@ -33,8 +33,8 @@ function MapDelegate(config) { function createMap(inDiv, inCenter) { if (! inCenter ) return null; myOptions = { - 'minZoom': 6, - 'maxZoom': 17, + 'minZoom': config.minZoom, + 'maxZoom': config.maxZoom, 'doubleClickZoom' : false, 'scrollWheelZoom' : false }; diff --git a/croutonjs/meetingMap/meeting_map.php b/croutonjs/meetingMap/meeting_map.php index 0b800350..ed0b55a1 100644 --- a/croutonjs/meetingMap/meeting_map.php +++ b/croutonjs/meetingMap/meeting_map.php @@ -48,6 +48,7 @@ public function enqueueFrontendFiles() wp_enqueue_script("gmapsDelegate", plugin_dir_url(__FILE__)."js/gmapsDelegate.js", false, filemtime(plugin_dir_path(__FILE__)."js/gmapsDelegate.js"), false); wp_enqueue_script("meeting_map", plugin_dir_url(__FILE__)."js/meeting_map.js", false, filemtime(plugin_dir_path(__FILE__)."js/meeting_map.js"), false); wp_enqueue_script("google.markercluster", plugin_dir_url(__FILE__)."js/google.markercluster.min.js", false, filemtime(plugin_dir_path(__FILE__)."js/google.markercluster.min.js"), false); + wp_enqueue_script("google.oms", plugin_dir_url(__FILE__)."js/oms-1.0.3.min.js", false, filemtime(plugin_dir_path(__FILE__)."js/oms-1.0.3.min.js"), false); } else { wp_enqueue_style("leaflet", plugin_dir_url(__FILE__)."css/leaflet.css", false, filemtime(plugin_dir_path(__FILE__)."css/leaflet.css"), false); wp_enqueue_style("leaflet-markercluster-default", plugin_dir_url(__FILE__)."css/MarkerCluster.Default.css", false, filemtime(plugin_dir_path(__FILE__)."css/MarkerCluster.Default.css"), false); diff --git a/croutonjs/src/js/crouton-core.js b/croutonjs/src/js/crouton-core.js index c0f8fd69..95ac0c28 100644 --- a/croutonjs/src/js/crouton-core.js +++ b/croutonjs/src/js/crouton-core.js @@ -85,7 +85,9 @@ function Crouton(config) { tileOptions: { attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA', maxZoom: 18 - } + }, + minZoom: 6, + maxZoom: 17 }; self.setConfig(config); diff --git a/gulpfile.js b/gulpfile.js index f700fba3..472b8e3a 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -36,6 +36,7 @@ let jsFilesGoogleMap = [ 'meeting_map.js', 'gmapsDelegate.js', 'google.markercluster.min.js', + 'oms-1.0.3.min.js', ]; let jsFilesCroutonMapWithFullPath = jsFilesCroutonMap.map((f)=>'croutonjs/meetingMap/js/'+f); let jsFilesGoogleMapWithFullPath = jsFilesGoogleMap.map((f)=>'croutonjs/meetingMap/js/'+f);