From: Matthias Schmidt Date: Sun, 2 Jul 2017 14:08:06 +0000 (+0200) Subject: Add route planner support for maps X-Git-Tag: 3.1.0_Alpha_1~307 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=84de180d4f033af4ddbfbec307d441da7b1e3a68;p=GitHub%2FWoltLab%2FWCF.git Add route planner support for maps Close #2321 --- diff --git a/com.woltlab.wcf/templates/googleMapsJavaScript.tpl b/com.woltlab.wcf/templates/googleMapsJavaScript.tpl index f9ed67ed00..a475c25d73 100644 --- a/com.woltlab.wcf/templates/googleMapsJavaScript.tpl +++ b/com.woltlab.wcf/templates/googleMapsJavaScript.tpl @@ -5,6 +5,17 @@ $(function() { WCF.Language.addObject({ 'wcf.map.noLocationSuggestions': '{lang}wcf.map.noLocationSuggestions{/lang}', + 'wcf.map.route.error.not_found': '{lang}wcf.map.route.error.not_found{/lang}', + 'wcf.map.route.error.over_query_limit': '{lang}wcf.map.route.error.over_query_limit{/lang}', + 'wcf.map.route.error.request_denied': '{lang}wcf.map.route.error.request_denied{/lang}', + 'wcf.map.route.origin': '{lang}wcf.map.route.origin{/lang}', + 'wcf.map.route.planner': '{lang}wcf.map.route.planner{/lang}', + 'wcf.map.route.travelMode': '{lang}wcf.map.route.travelMode{/lang}', + 'wcf.map.route.travelMode.bicycling': '{lang}wcf.map.route.travelMode.bicycling{/lang}', + 'wcf.map.route.travelMode.driving': '{lang}wcf.map.route.travelMode.driving{/lang}', + 'wcf.map.route.travelMode.transit': '{lang}wcf.map.route.travelMode.transit{/lang}', + 'wcf.map.route.travelMode.walking': '{lang}wcf.map.route.travelMode.walking{/lang}', + 'wcf.map.route.viewOnGoogleMaps': '{lang}wcf.map.route.viewOnGoogleMaps{/lang}', 'wcf.map.showLocationSuggestions': '{lang}wcf.map.showLocationSuggestions{/lang}', 'wcf.map.useLocationSuggestion': '{lang}wcf.map.useLocationSuggestion{/lang}' }); diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Controller/Map/Route/Planner.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Controller/Map/Route/Planner.js new file mode 100644 index 0000000000..4b5025acdc --- /dev/null +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Controller/Map/Route/Planner.js @@ -0,0 +1,217 @@ +/** + * Map route planner based on Google Maps. + * + * @author Matthias Schmidt + * @copyright 2001-2017 WoltLab GmbH + * @license GNU Lesser General Public License + * @module WoltLabSuite/Core/Controller/Map/Route/Planner + */ +define([ + 'Dom/Traverse', + 'Dom/Util', + 'Language', + 'Ui/Dialog', + 'WoltLabSuite/Core/Ajax/Status' +], function( + DomTraverse, + DomUtil, + Language, + UiDialog, + AjaxStatus +) { + /** + * @constructor + */ + function Planner(buttonId, destination) { + this._button = elById(buttonId); + if (this._button === null) { + throw new Error("Unknown button with id '" + buttonId + "'"); + } + + this._button.addEventListener('click', this._openDialog.bind(this)); + + this._destination = destination; + } + Planner.prototype = { + /** + * Sets up the route planner dialog. + */ + _dialogSetup: function() { + return { + id: this._button.id + 'Dialog', + options: { + onShow: this._initDialog.bind(this), + title: Language.get('wcf.map.route.planner') + }, + source: '' + + '' + + '
' + + '
' + Language.get('wcf.map.route.origin') + '
' + + '
' + + '
' + + '
' + + '
' + Language.get('wcf.map.route.travelMode') + '
' + + '
' + + '' + + '
' + + '
' + } + }, + + /** + * Calculates the route based on the given result of a location search. + * + * @param {object} data + */ + _calculateRoute: function(data) { + var dialog = UiDialog.getDialog(this).dialog; + + if (data.label) { + this._originInput.value = data.label; + } + + if (this._map === undefined) { + this._map = new google.maps.Map(elByClass('googleMap', dialog)[0], { + disableDoubleClickZoom: WCF.Location.GoogleMaps.Settings.get('disableDoubleClickZoom'), + draggable: WCF.Location.GoogleMaps.Settings.get('draggable'), + mapTypeId: google.maps.MapTypeId.ROADMAP, + scaleControl: WCF.Location.GoogleMaps.Settings.get('scaleControl'), + scrollwheel: WCF.Location.GoogleMaps.Settings.get('scrollwheel') + }); + + this._directionsService = new google.maps.DirectionsService(); + this._directionsRenderer = new google.maps.DirectionsRenderer(); + + this._directionsRenderer.setMap(this._map); + this._directionsRenderer.setPanel(elByClass('googleMapsDirections', dialog)[0]); + + this._googleLink = elByClass('googleMapsDirectionsGoogleLink', dialog)[0]; + } + + var request = { + destination: this._destination, + origin: data.location, + provideRouteAlternatives: true, + travelMode: google.maps.TravelMode[this._travelMode.value.toUpperCase()] + }; + + AjaxStatus.show(); + this._directionsService.route(request, this._setRoute.bind(this)); + + elAttr(this._googleLink, 'href', this._getGoogleMapsLink(data.location, this._travelMode.value)); + + this._lastOrigin = data.location; + }, + + /** + * Returns the Google Maps link based on the given optional directions origin + * and optional travel mode. + * + * @param {google.maps.LatLng} origin + * @param {string} travelMode + * @return {string} + */ + _getGoogleMapsLink: function(origin, travelMode) { + if (origin) { + var link = 'https://www.google.com/maps/dir/?api=1' + + '&origin=' + origin.lat() + ',' + origin.lng() + '' + + '&destination=' + this._destination.lat() + ',' + this._destination.lng(); + + if (travelMode) { + link += '&travelmode=' + travelMode; + } + + return link; + } + + return 'https://www.google.com/maps/search/?api=1&query=' + this._destination.lat() + ',' + this._destination.lng(); + }, + + /** + * Initializes the route planning dialog. + */ + _initDialog: function() { + if (!this._didInitDialog) { + var dialog = UiDialog.getDialog(this).dialog; + + // make input element a location search + this._originInput = elBySel('input[name="origin"]', dialog); + new WCF.Location.GoogleMaps.LocationSearch(this._originInput, this._calculateRoute.bind(this)); + + this._travelMode = elBySel('select[name="travelMode"]', dialog); + this._travelMode.addEventListener('change', this._updateRoute.bind(this)); + + this._didInitDialog = true; + } + }, + + /** + * Opens the route planning dialog. + */ + _openDialog: function() { + UiDialog.open(this); + }, + + /** + * Handles the response of the direction service. + * + * @param {object} result + * @param {string} status + */ + _setRoute: function(result, status) { + AjaxStatus.hide(); + + if (status == 'OK') { + elShow(this._map.getDiv().parentNode); + + google.maps.event.trigger(this._map, 'resize'); + + this._directionsRenderer.setDirections(result); + + elShow(DomTraverse.parentByTag(this._travelMode, 'DL')); + elShow(this._googleLink); + + if (this._errorMessage) { + elHide(this._errorMessage); + } + } + else { + // map irrelevant errors to not found error + if (status !== 'OVER_QUERY_LIMIT' && status !== 'REQUEST_DENIED') { + status = 'NOT_FOUND'; + } + + if (this._errorMessage === undefined) { + this._errorMessage = elCreate('small'); + this._errorMessage.classList = 'innerError'; + + DomUtil.insertAfter(this._errorMessage, this._originInput); + } + else { + elShow(this._errorMessage); + } + + this._errorMessage.textContent = Language.get('wcf.map.route.error.' + status.toLowerCase()); + } + }, + + /** + * Updates the route after the travel mode has been changed. + */ + _updateRoute: function() { + this._calculateRoute({ + location: this._lastOrigin + }); + } + }; + + return Planner; +}); diff --git a/wcfsetup/install/files/style/ui/googleMap.scss b/wcfsetup/install/files/style/ui/googleMap.scss index 09deb51776..9f7db6de30 100644 --- a/wcfsetup/install/files/style/ui/googleMap.scss +++ b/wcfsetup/install/files/style/ui/googleMap.scss @@ -43,3 +43,25 @@ .googleMapsUseLocationSuggestionLink { font-size: $wcfFontSizeSmall; } + +.googleMapsDirectionsContainer { + display: flex; + width: 100%; + + .googleMap { + flex: 0 0 50%; + } + + .googleMapsDirections { + flex: 0 0 50%; + height: 400px; + padding-left: 10px; + overflow-y: scroll; + } +} + +.googleMapsDirectionsGoogleLinkContainer { + display: block; + margin-top: 5px; + text-align: right; +} diff --git a/wcfsetup/install/lang/de.xml b/wcfsetup/install/lang/de.xml index 479de0d8fd..e3aec1dfd1 100644 --- a/wcfsetup/install/lang/de.xml +++ b/wcfsetup/install/lang/de.xml @@ -2881,6 +2881,18 @@ Fehler sind beispielsweise: + + + + + + + + + + + + diff --git a/wcfsetup/install/lang/en.xml b/wcfsetup/install/lang/en.xml index 7f26692d27..3b48bda782 100644 --- a/wcfsetup/install/lang/en.xml +++ b/wcfsetup/install/lang/en.xml @@ -2823,6 +2823,18 @@ Errors are: + + + + + + + + + + + +