diff --git a/source/mxn.(provider).directions.js b/source/mxn.(provider).directions.js new file mode 100644 index 0000000..721b186 --- /dev/null +++ b/source/mxn.(provider).directions.js @@ -0,0 +1,30 @@ +mxn.register('{{api_id}}', { + +Directions: { + + init: function() { + // TODO: Add provider code + // this.routers[this.api] = new ; + }, + + getRouteFromQuery: function(origin, destination) { + // TODO: Add provider code + }, + + getRouteFromWayPoints: function(wayPoints) { + // TODO: Add provider code + }, + + getRoute_callback: function(route) { + var response = {}; + + // TODO: Add provider code + // response.polyline = polyline; + // response.directions = directions; + // response.distance = distance; + // response.duration = duration; + + this.callback(response); + } +} +}); \ No newline at end of file diff --git a/source/mxn.directions.js b/source/mxn.directions.js new file mode 100644 index 0000000..bddd3cf --- /dev/null +++ b/source/mxn.directions.js @@ -0,0 +1,68 @@ +(function(){ + + /** + * Initialise our provider. This function should only be called + * from within mapstraction code, not exposed as part of the API. + * @private + */ + var init = function() { + this.invoker.go('init'); + }; + + /** + * @name mxn.Directions + * @constructor + * @param {String} api The API to use + * @param {Function} callback The function to call when a route request returns: function({ polyline{}, directions[], distance(meters), duration(seconds)}) + * @param {Function} error_callback The optional function to call when a route request fails + * @exports Directions as mxn.Directions + */ + var Directions = mxn.Directions = function (api, callback, error_callback) { + this.routers = {}; + this.api = api; + this.callback = callback; + this.error_callback = error_callback || function() {}; + + // set up our invoker for calling API methods + this.invoker = new mxn.Invoker(this, 'Directions', function(){ return this.api; }); + init.apply(this); + }; + + mxn.addProxyMethods(Directions, [ + + /** + * Gets a route between two textual points. + * @name mxn.Routing#getRouteFromQuery + * @function + * @param {String} origin: origin of route + * @param {String} destination: destination of route + */ + 'getRouteFromQuery', + + /** + * Gets a route between multiple waypoints. + * @name mxn.Routing#getRouteFromWayPoints + * @function + * @param {Array} wayPoints: list of locations to route between, must be >= 2 + */ + 'getRouteFromWayPoints', + + 'getRoute_callback', + + ]); + + /** + * Change the directions API in use + * @name mxn.Directions#swap + * @param {String} api The API to swap to + */ + Directions.prototype.swap = function(api) { + if (this.api == api) { return; } + + this.api = api; + if (!this.routers.hasOwnProperty(this.api)) { + init.apply(this); + } + }; + +})(); \ No newline at end of file diff --git a/source/mxn.google.directions.js b/source/mxn.google.directions.js new file mode 100644 index 0000000..3b881dd --- /dev/null +++ b/source/mxn.google.directions.js @@ -0,0 +1,79 @@ +mxn.register('google', { + +Directions: { + + init: function() { + var self = this; + var router = new GDirections(); + + // Error event + GEvent.addListener(router, "error", function() { + + // Google geocoding status messages + var reasons = []; + reasons[G_GEO_SUCCESS] = "Success"; + reasons[G_GEO_MISSING_ADDRESS] = "Missing Address: The address was either missing or had no value."; + reasons[G_GEO_UNKNOWN_ADDRESS] = "Unknown Address: No corresponding geographic location could be found for the specified address."; + reasons[G_GEO_UNAVAILABLE_ADDRESS] = "Unavailable Address: The geocode for the given address cannot be returned due to legal or contractual reasons."; + reasons[G_GEO_BAD_KEY] = "Bad Key: The API key is either invalid or does not match the domain for which it was given"; + reasons[G_GEO_TOO_MANY_QUERIES] = "Too Many Queries: The daily geocoding quota for this site has been exceeded."; + reasons[G_GEO_SERVER_ERROR] = "Server error: The geocoding request could not be successfully processed."; + + var code = router.getStatus().code; + var response = "Error: " + (reasons[code] || "Unknown error returned (" + code + ")"); + + self.error_callback(response); + }); + + // Directions returned event + GEvent.addListener(router, "load", function() { + self.getRoute_callback(); + }); + + this.routers[this.api] = router; + }, + + getRouteFromQuery: function(origin, destination) { + var router = this.routers[this.api]; + router.load(origin + " to " + destination, { getPolyline: true, getSteps: true }); + }, + + getRouteFromWayPoints: function(waypoints) { + var router = this.routers[this.api]; + var points = new Array(); + + for (var i = 0; i < wayPoints.length; i++) { + points.push(wayPoints[i].toProprietary(this.api).toUrlValue(6)); + } + + router.loadFromWaypoints(points, { getPolyline: true, getSteps: true }); + }, + + getRoute_callback: function() { + var router = this.routers[this.api]; + + // Polyline + var polyline = new mxn.Polyline(); + polyline.api = this.api; + polyline.fromProprietary(router.getPolyline()); + + // Directions + var directions = []; + + if (router.getNumRoutes() > 0) { + for (var i = 0; i < router.getRoute(0).getNumSteps(); i++) { + directions[i] = router.getRoute(0).getStep(i).getDescriptionHtml(); + } + } + + var response = { + polyline: polyline, + directions: directions, + distance: router.getDistance().meters, + duration: router.getDuration().seconds + }; + + this.callback(response); + } +} +}); \ No newline at end of file diff --git a/source/mxn.googlev3.directions.js b/source/mxn.googlev3.directions.js new file mode 100644 index 0000000..fdfa638 --- /dev/null +++ b/source/mxn.googlev3.directions.js @@ -0,0 +1,104 @@ +mxn.register('googlev3', { + +Directions: { + + init: function() { + this.routers[this.api] = new google.maps.DirectionsService(); + }, + + getRouteFromQuery: function(origin, destination) { + var self = this; + var router = this.routers[this.api]; + + var request = { + origin: origin, + destination: destination, + travelMode: google.maps.TravelMode.DRIVING + } + + router.route(request, function(response) { + if (!response) { + self.error_callback("Unknown error occurred"); + } else if (response.status != "OK") { + self.error_callback(response.status); + } else if (response.routes.length < 1) { + self.error_callback("No routes returned"); + } else { + self.getRoute_callback(response); + } + }); + }, + + getRouteFromWayPoints: function(wayPoints) { + var self = this; + var router = this.routers[this.api]; + var points = []; + + for (var i = 1; i < wayPoints.length-1; i++) { + points.push({ + location: wayPoints[i].toProprietary(this.api).toUrlValue(6), + stopover: false + }); + } + + var request = { + origin: wayPoints[0].toProprietary(this.api).toUrlValue(6), + destination: wayPoints[wayPoints.length-1].toProprietary(this.api).toUrlValue(6), + travelMode: google.maps.TravelMode.DRIVING, + waypoints: points + } + + router.route(request, function(response) { + if (!response) { + self.error_callback("Unknown error occurred"); + } else if (response.status != "OK") { + self.error_callback(response.status); + } else if (response.routes.length < 1) { + self.error_callback("No routes returned"); + } else { + self.getRoute_callback(response.routes[0]); + } + }); + }, + + getRoute_callback: function(route) { + + // Polyline + var gPoints = route.overview_path; + var points = []; + + for (var i = 0; i < gPoints.length; i++) { + var point = new mxn.LatLonPoint(); + point.fromProprietary(this.api, gPoints[i]); + points.push(point); + } + + var polyline = new mxn.Polyline(points); + + // Other bits + var directions = []; + var distance = 0; + var duration = 0; + + for (var i = 0; i < route.legs.length; i++) { + var leg = route.legs[i]; + distance += leg.distance.value; + duration += leg.duration.value; + + for (var j = 0; j < leg.steps.length; j++) { + var step = leg.steps[j]; + directions[directions.length] = step.instructions; + } + } + + var response = { + polyline: polyline, + directions: directions, + distance: distance, + duration: duration + }; + + this.callback(response); + } +} +}); \ No newline at end of file