Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Directions module #313

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions source/mxn.(provider).directions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
mxn.register('{{api_id}}', {

Directions: {

init: function() {
// TODO: Add provider code
// this.routers[this.api] = new <directions object>;
},

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);
}
}
});
68 changes: 68 additions & 0 deletions source/mxn.directions.js
Original file line number Diff line number Diff line change
@@ -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);
}
};

})();
79 changes: 79 additions & 0 deletions source/mxn.google.directions.js
Original file line number Diff line number Diff line change
@@ -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);
}
}
});
104 changes: 104 additions & 0 deletions source/mxn.googlev3.directions.js
Original file line number Diff line number Diff line change
@@ -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);
}
}
});