// Packaging/modules magic dance. This code is inserted before all other
// code when the dist is built.
(function (factory) {
var L;
if (typeof define === 'function' && define.amd) {
// AMD
define(['leaflet'], factory);
} else if (typeof module !== 'undefined') {
// Node/CommonJS
L = require('leaflet');
module.exports = factory(L);
} else {
// Browser globals
if (typeof window.L === 'undefined')
throw 'Leaflet must be loaded first';
factory(window.L);
}
}(function (L) {
(function() {
'use strict';
L.Routing = L.Routing || {};
L.Routing.Autocomplete = L.Class.extend({
options: {
timeout: 500
},
initialize: function(elem, callback, context, options) {
L.setOptions(this, options);
this._elem = elem;
this._resultFn = options.resultFn ? L.Util.bind(options.resultFn, options.resultContext) : null;
this._autocomplete = options.autocompleteFn ? L.Util.bind(options.autocompleteFn, options.autocompleteContext) : null;
this._selectFn = L.Util.bind(callback, context);
this._container = L.DomUtil.create('div', 'leaflet-routing-geocoder-result');
this._resultTable = L.DomUtil.create('table', '', this._container);
L.DomEvent.addListener(this._elem, 'keypress', this._keyPressed, this);
L.DomEvent.addListener(this._elem, 'keydown', this._keyDown, this);
L.DomEvent.addListener(this._elem, 'blur', function() {
if (this._isOpen) {
// TODO: setTimeout here looks like a hack, but is needed
// to get click events to fire before hiding the container.
setTimeout(L.Util.bind(function() { this.close(); }, this), 100);
}
}, this);
},
close: function() {
L.DomUtil.removeClass(this._container, 'leaflet-routing-geocoder-result-open');
this._isOpen = false;
},
_open: function() {
var sibling = this._elem.nextSibling;
if (!this._container.parentElement) {
if (sibling) {
this._elem.parentElement.insertBefore(this._container, sibling);
} else {
this._elem.parentElement.appendChild(this._container);
}
this._container.style.left = this._elem.offsetLeft + 'px';
this._container.style.top = (this._elem.offsetTop + this._elem.offsetHeight) + 'px';
this._container.style.width = this._elem.offsetWidth + 'px';
}
L.DomUtil.addClass(this._container, 'leaflet-routing-geocoder-result-open');
this._isOpen = true;
},
_setResults: function(results) {
var i,
tr,
td;
delete this._selection;
this._results = results;
while (this._resultTable.firstChild) {
this._resultTable.removeChild(this._resultTable.firstChild);
}
for (i = 0; i < results.length; i++) {
tr = L.DomUtil.create('tr', '', this._resultTable);
tr.setAttribute('data-result-index', i);
td = L.DomUtil.create('td', '', tr);
td.textContent = results[i].name;
L.DomEvent.addListener(td, 'click', this._resultSelected(results[i]), this);
}
if (results.length > 0) {
this._open();
// Select the first entry
this._select(1);
}
},
_resultSelected: function(r) {
return function() {
this.close();
this._selectFn(r);
};
},
_keyPressed: function(e) {
var index;
if (this._isOpen && e.keyCode === 13 && this._selection) {
index = parseInt(this._selection.getAttribute('data-result-index'), 10);
this._resultSelected(this._results[index]).call(this);
L.DomEvent.preventDefault(e);
return;
}
if (e.keyCode === 13) {
this._complete(this._resultFn, true);
}
if (this._autocomplete) {
if (this._timer) {
clearTimeout(this._timer);
}
this._timer = setTimeout(L.Util.bind(function() { this._complete(this._autocomplete); }, this),
this.options.timeout);
}
},
_select: function(dir) {
var sel = this._selection;
if (sel) {
L.DomUtil.removeClass(sel.firstChild, 'leaflet-routing-geocoder-selected');
sel = sel[dir > 0 ? 'nextSibling' : 'previousSibling'];
}
if (!sel) {
sel = this._resultTable[dir > 0 ? 'firstChild' : 'lastChild'];
}
if (sel) {
L.DomUtil.addClass(sel.firstChild, 'leaflet-routing-geocoder-selected');
this._selection = sel;
}
},
_keyDown: function(e) {
if (this._isOpen) {
switch (e.keyCode) {
// Up
case 38:
this._select(-1);
L.DomEvent.preventDefault(e);
return;
// Up
case 40:
this._select(1);
L.DomEvent.preventDefault(e);
return;
}
}
},
_complete: function(completeFn, trySelect) {
completeFn(this._elem.value, function(results) {
if (trySelect && results.length === 1) {
this._resultSelected(results[0]);
} else {
this._setResults(results);
}
}, this);
}
});
})();
(function() {
'use strict';
L.Routing = L.Routing || {};
L.Routing._jsonpCallbackId = 0;
L.Routing._jsonp = function(url, callback, context, jsonpParam) {
var callbackId = '_l_routing_machine_' + (L.Routing._jsonpCallbackId++),
script;
url += '&' + jsonpParam + '=' + callbackId;
window[callbackId] = L.Util.bind(callback, context);
script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
script.id = callbackId;
document.getElementsByTagName('head')[0].appendChild(script);
};
L.Routing.OSRM = L.Class.extend({
options: {
serviceUrl: '//router.project-osrm.org/viaroute',
geometryPrecision: 6
},
initialize: function(options) {
L.Util.setOptions(this, options);
this._hints = {
locations: {}
};
},
route: function(waypoints, callback, context) {
var url = this._buildRouteUrl(waypoints);
L.Routing._jsonp(url, function(data) {
this._routeDone(data, waypoints, callback, context);
}, this, 'jsonp');
},
_routeDone: function(response, waypoints, callback, context) {
context = context || callback;
if (response.status !== 0) {
callback.call(context, {
status: response.status,
message: response.message
});
return;
}
var alts = [{
name: response.route_name.join(', '),
coordinates: this._decode(response.route_geometry, this.options.geometryPrecision),
instructions: this._convertInstructions(response.route_instructions),
summary: this._convertSummary(response.route_summary),
waypoints: response.via_points
}],
i;
if (response.alternative_geometries) {
for (i = 0; i < response.alternative_geometries.length; i++) {
alts.push({
name: response.alternative_names[i].join(', '),
coordinates: this._decode(response.alternative_geometries[i], this.options.geometryPrecision),
instructions: this._convertInstructions(response.alternative_instructions[i]),
summary: this._convertSummary(response.alternative_summaries[i]),
waypoints: response.via_points
});
}
}
this._saveHintData(response, waypoints);
callback.call(context, null, alts);
},
_buildRouteUrl: function(waypoints) {
var locs = [],
locationKey,
hint;
for (var i = 0; i < waypoints.length; i++) {
locationKey = this._locationKey(waypoints[i].latLng);
locs.push('loc=' + locationKey);
hint = this._hints.locations[locationKey];
if (hint) {
locs.push('hint=' + hint);
}
}
return this.options.serviceUrl + '?' +
'instructions=true&' +
locs.join('&') +
(this._hints.checksum !== undefined ? '&checksum=' + this._hints.checksum : '');
},
_locationKey: function(location) {
return location.lat + ',' + location.lng;
},
_saveHintData: function(route, waypoints) {
var hintData = route.hint_data,
loc;
this._hints = {
checksum: hintData.checksum,
locations: {}
};
for (var i = hintData.locations.length - 1; i >= 0; i--) {
loc = waypoints[i].latLng;
this._hints.locations[this._locationKey(loc)] = hintData.locations[i];
}
},
// Adapted from
// https://github.com/DennisSchiefer/Project-OSRM-Web/blob/develop/WebContent/routing/OSRM.RoutingGeometry.js
_decode: function(encoded, precision) {
var len = encoded.length,
index=0,
lat=0,
lng = 0,
array = [];
precision = Math.pow(10, -precision);
while (index < len) {
var b,
shift = 0,
result = 0;
do {
b = encoded.charCodeAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
var dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = encoded.charCodeAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
var dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
lng += dlng;
//array.push( {lat: lat * precision, lng: lng * precision} );
array.push( [lat * precision, lng * precision] );
}
return array;
},
_convertSummary: function(osrmSummary) {
return {
totalDistance: osrmSummary.total_distance,
totalTime: osrmSummary.total_time
};
},
_convertInstructions: function(osrmInstructions) {
var result = [],
i,
instr,
type,
driveDir;
for (i = 0; i < osrmInstructions.length; i++) {
instr = osrmInstructions[i];
type = this._drivingDirectionType(instr[0]);
driveDir = instr[0].split('-');
if (type) {
result.push({
type: type,
distance: instr[2],
time: instr[4],
road: instr[1],
direction: instr[6],
exit: driveDir.length > 1 ? driveDir[1] : undefined,
index: instr[3]
});
}
}
return result;
},
_drivingDirectionType: function(d) {
switch (parseInt(d, 10)) {
case 1:
return 'Straight';
case 2:
return 'SlightRight';
case 3:
return 'Right';
case 4:
return 'SharpRight';
case 5:
return 'TurnAround';
case 6:
return 'SharpLeft';
case 7:
return 'Left';
case 8:
return 'SlightRight';
case 9:
return 'WaypointReached';
case 10:
// TODO: "Head on"
// https://github.com/DennisOSRM/Project-OSRM/blob/master/DataStructures/TurnInstructions.h#L48
return 'Straight';
case 11:
case 12:
return 'Roundabout';
case 15:
return 'DestinationReached';
default:
return null;
}
}
});
L.Routing.osrm = function(options) {
return new L.Routing.OSRM(options);
};
})();
(function() {
'use strict';
L.Routing = L.Routing || {};
L.Routing.Line = L.Class.extend({
includes: L.Mixin.Events,
options: {
styles: [
{color: 'black', opacity: 0.15, weight: 7},
{color: 'white', opacity: 0.8, weight: 4},
{color: 'orange', opacity: 1, weight: 2}
],
addWaypoints: true
},
initialize: function(route, options) {
L.Util.setOptions(this, options);
this._route = route;
this._wpIndices = this._findWaypointIndices();
},
addTo: function(map) {
map.addLayer(this);
},
onAdd: function(map) {
var geom = this._route.coordinates,
i,
pl;
this._map = map;
this._layers = [];
for (i = 0; i < this.options.styles.length; i++) {
pl = L.polyline(geom, this.options.styles[i])
.addTo(map);
if (this.options.addWaypoints) {
pl.on('mousedown', this._onLineTouched, this);
}
this._layers.push(pl);
}
},
onRemove: function(map) {
var i;
for (i = 0; i < this._layers.length; i++) {
map.removeLayer(this._layers[i]);
}
delete this._map;
},
getBounds: function() {
return L.latLngBounds(this._route.coordinates);
},
_findWaypointIndices: function() {
var wps = this._route.waypoints,
indices = [],
i;
for (i = 0; i < wps.length; i++) {
indices.push(this._findClosestRoutePoint(L.latLng(wps[i])));
}
return indices;
},
_findClosestRoutePoint: function(latlng) {
var minDist = Number.MAX_VALUE,
minIndex,
i,
d;
for (i = this._route.coordinates.length - 1; i >= 0 ; i--) {
// TODO: maybe do this in pixel space instead?
d = latlng.distanceTo(this._route.coordinates[i]);
if (d < minDist) {
minIndex = i;
minDist = d;
}
}
return minIndex;
},
_findNearestWpBefore: function(i) {
var j = this._wpIndices.length - 1;
while (j >= 0 && this._wpIndices[j] > i) {
j--;
}
return j;
},
_onLineTouched: function(e) {
var afterIndex = this._findNearestWpBefore(this._findClosestRoutePoint(e.latlng));
this.fire('linetouched', {
afterIndex: afterIndex,
latlng: e.latlng
});
},
});
L.Routing.line = function(route, options) {
return new L.Routing.Line(route, options);
};
})();
(function() {
'use strict';
L.Routing = L.Routing || {};
L.Routing.Itinerary = L.Control.extend({
includes: L.Mixin.Events,
options: {
units: 'metric',
pointMarkerStyle: {
radius: 5,
color: '#03f',
fillColor: 'white',
opacity: 1,
fillOpacity: 0.7
}
},
initialize: function(options) {
L.setOptions(this, options);
},
onAdd: function() {
this._container = L.DomUtil.create('div', 'leaflet-routing-container leaflet-bar');
L.DomEvent.disableClickPropagation(this._container);
L.DomEvent.addListener(this._container, 'mousewheel', function(e) {
L.DomEvent.stopPropagation(e);
});
return this._container;
},
onRemove: function() {
},
setAlternatives: function(routes) {
var i,
alt,
altDiv;
this._clearAlts();
this._routes = routes;
for (i = 0; i < this._routes.length; i++) {
alt = this._routes[i];
altDiv = L.DomUtil.create('div', 'leaflet-routing-alt' +
(i > 0 ? ' leaflet-routing-alt-minimized' : ''),
this._container);
altDiv.innerHTML = '
' + alt.name + '
' +
'' + this._formatDistance(alt.summary.totalDistance) +
', ' + this._formatTime(alt.summary.totalTime) + '
';
L.DomEvent.addListener(altDiv, 'click', this._onAltClicked, this);
altDiv.appendChild(this._createItineraryTable(alt));
this._altElements.push(altDiv);
}
this.fire('routeselected', {route: this._routes[0]});
},
_clearAlts: function() {
var i,
alt;
// TODO: this is really inelegant
for (i = 0; this._container && i < this._container.children.length; i++) {
alt = this._container.children[i];
if (L.DomUtil.hasClass(alt, 'leaflet-routing-alt')) {
this._container.removeChild(alt);
i--;
}
}
this._altElements = [];
},
_createItineraryTable: function(r) {
var table = L.DomUtil.create('table', ''),
body = L.DomUtil.create('tbody', '', table),
i,
instr,
row,
td;
for (i = 0; i < r.instructions.length; i++) {
instr = r.instructions[i];
row = L.DomUtil.create('tr', '', body);
td = L.DomUtil.create('td', '', row);
td.appendChild(document.createTextNode(this._instruction(instr, i)));
td = L.DomUtil.create('td', '', row);
td.appendChild(document.createTextNode(this._formatDistance(instr.distance)));
this._addRowListeners(row, r.coordinates[instr.index]);
}
return table;
},
_addRowListeners: function(row, coordinate) {
var _this = this,
marker;
L.DomEvent.addListener(row, 'mouseover', function() {
marker = L.circleMarker(coordinate,
_this.options.pointMarkerStyle).addTo(_this._map);
});
L.DomEvent.addListener(row, 'mouseout', function() {
if (marker) {
_this._map.removeLayer(marker);
marker = null;
}
});
L.DomEvent.addListener(row, 'click', function(e) {
_this._map.panTo(coordinate);
L.DomEvent.stopPropagation(e);
});
},
_onAltClicked: function(e) {
var altElem,
j,
n,
isCurrentSelection;
altElem = e.target;
while (!L.DomUtil.hasClass(altElem, 'leaflet-routing-alt')) {
altElem = altElem.parentElement;
}
if (L.DomUtil.hasClass(altElem, 'leaflet-routing-alt-minimized')) {
for (j = 0; j < this._altElements.length; j++) {
n = this._altElements[j];
isCurrentSelection = altElem === n;
L.DomUtil[isCurrentSelection ? 'removeClass' : 'addClass'](n, 'leaflet-routing-alt-minimized');
if (isCurrentSelection) {
// TODO: don't fire if the currently active is clicked
this.fire('routeselected', {route: this._routes[j]});
}
}
}
L.DomEvent.stop(e);
},
_formatDistance: function(d /* Number (meters) */) {
var v;
if (this.options.units === 'imperial') {
d = d / 1.609344;
if (d >= 1000) {
return (this._round(d) / 1000) + ' mi';
} else {
return this._round(d / 1.760) + ' yd';
}
} else {
v = this._round(d);
return v >= 1000 ? ((v / 1000) + ' km') : (v + ' m');
}
},
_round: function(d) {
var pow10 = Math.pow(10, (Math.floor(d) + '').length - 1),
r = Math.floor(d / pow10 * 2),
p = r % 2 ? pow10 / 2 : pow10;
return Math.round(d / p) * p;
},
_formatTime: function(t /* Number (seconds) */) {
if (t > 86400) {
return Math.round(t / 3600) + ' h';
} else if (t > 3600) {
return Math.floor(t / 3600) + ' h ' +
Math.round((t % 3600) / 60) + ' min';
} else if (t > 300) {
return Math.round(t / 60) + ' min';
} else if (t > 60) {
return Math.floor(t / 60) + ' min ' +
(t % 60) + ' s';
} else {
return t + ' s';
}
},
_instruction: function(instr, i) {
if (instr.type !== undefined) {
return L.Util.template(this._getInstructionTemplate(instr, i),
L.extend({exit: this._formatOrder(instr.exit), dir: this._dir[instr.direction]},
instr));
} else {
return instr.text;
}
},
_getInstructionTemplate: function(instr, i) {
switch (instr.type) {
case 'Straight':
return (i === 0 ? 'Head' : 'Continue') + ' {dir}' + (instr.road ? ' on {road}' : '');
case 'SlightRight':
return 'Slight right' + (instr.road ? ' onto {road}' : '');
case 'Right':
return 'Right' + (instr.road ? ' onto {road}' : '');
case 'SharpRight':
return 'Sharp right' + (instr.road ? ' onto {road}' : '');
case 'TurnAround':
return 'Turn around';
case 'SharpLeft':
return 'Sharp left' + (instr.road ? ' onto {road}' : '');
case 'Left':
return 'Left' + (instr.road ? ' onto {road}' : '');
case 'SlightLeft':
return 'Slight left' + (instr.road ? ' onto {road}' : '');
case 'WaypointReached':
return 'Waypoint reached';
case 'Roundabout':
return 'Take the {exit} exit in the roundabout';
case 'DestinationReached':
return 'Destination reached';
}
},
_formatOrder: function(n) {
var i = n % 10 - 1,
suffix = ['st', 'nd', 'rd'];
return suffix[i] ? n + suffix[i] : n + 'th';
},
_dir: {
N: 'north',
NE: 'northeast',
E: 'east',
SE: 'southeast',
S: 'south',
SW: 'southwest',
W: 'west',
NW: 'northwest'
}
});
L.Routing.Itinerary._instructions = {
};
L.Routing.itinerary = function(router) {
return new L.Routing.Itinerary(router);
};
})();
(function() {
'use strict';
var Waypoint = L.Class.extend({
initialize: function(latLng, name) {
this.latLng = latLng;
this.name = name;
}
});
L.Routing = L.Routing || {};
L.Routing.Plan = L.Class.extend({
includes: L.Mixin.Events,
options: {
dragStyles: [
{color: 'black', opacity: 0.15, weight: 7},
{color: 'white', opacity: 0.8, weight: 4},
{color: 'orange', opacity: 1, weight: 2, dashArray: '7,12'}
],
draggableWaypoints: true,
addWaypoints: true
},
initialize: function(waypoints, options) {
L.Util.setOptions(this, options);
this._waypoints = [];
this.setWaypoints(waypoints);
},
isReady: function() {
var i;
for (i = 0; i < this._waypoints.length; i++) {
if (!this._waypoints[i].latLng) {
return false;
}
}
return true;
},
getWaypoints: function() {
var i,
wps = [];
for (i = 0; i < this._waypoints.length; i++) {
wps.push(this._waypoints[i]);
}
return wps;
},
setWaypoints: function(waypoints) {
var args = [0, this._waypoints.length].concat(waypoints);
this.spliceWaypoints.apply(this, args);
},
spliceWaypoints: function() {
var args = [arguments[0], arguments[1]],
i,
wp;
for (i = 2; i < arguments.length; i++) {
args.push(arguments[i] && arguments[i].latLng ? arguments[i] : new Waypoint(arguments[i]));
}
[].splice.apply(this._waypoints, args);
while (this._waypoints.length < 2) {
wp = new Waypoint();
this._waypoints.push(wp);
args.push(wp);
}
this._updateMarkers();
this._fireChanged.apply(this, args);
},
onAdd: function(map) {
this._map = map;
this._updateMarkers();
},
onRemove: function() {
var i;
this._removeMarkers();
if (this._newWp) {
for (i = 0; i < this._newWp.lines.length; i++) {
this._map.removeLayer(this._newWp.lines[i]);
}
}
delete this._map;
},
createGeocoders: function() {
var container = L.DomUtil.create('div', 'leaflet-routing-geocoders'),
waypoints = this._waypoints,
i,
geocoderElem,
addWpBtn;
this._geocoderContainer = container;
this._geocoderElems = [];
for (i = 0; i < waypoints.length; i++) {
geocoderElem = this._createGeocoder(i);
container.appendChild(geocoderElem);
this._geocoderElems.push(geocoderElem);
}
addWpBtn = L.DomUtil.create('button', '', container);
addWpBtn.setAttribute('type', 'button');
addWpBtn.innerHTML = '+';
L.DomEvent.addListener(addWpBtn, 'click', function() {
this.spliceWaypoints(waypoints.length, 0, null);
}, this);
this.on('waypointsspliced', this._updateGeocoders);
return container;
},
_createGeocoder: function(i) {
var geocoderElem;
geocoderElem = L.DomUtil.create('input', '');
geocoderElem.placeholder = this._geocoderPlaceholder(i);
this._updateWaypointName(i);
L.DomEvent.addListener(geocoderElem, 'click', function() {
this.select();
}, geocoderElem);
new L.Routing.Autocomplete(geocoderElem, function(r) {
geocoderElem.value = r.name;
this._waypoints[i].name = r.name;
this._waypoints[i].latLng = r.center;
this._updateMarkers();
this._fireChanged();
}, this, {
resultFn: this.options.geocoder.geocode,
resultContext: this.options.geocoder,
autocompleteFn: this.options.geocoder.suggest,
autocompleteContext: this.options.geocoder
});
return geocoderElem;
},
_updateGeocoders: function(e) {
var newElems = [],
i,
geocoderElem,
beforeElem;
for (i = e.added.length - 1; i >= 0 ; i--) {
geocoderElem = this._createGeocoder(e.index + i);
if (e.index >= this._geocoderElems.length) {
// lastChild is the "add new wp" button
beforeElem = this._geocoderContainer.lastChild;
} else {
beforeElem = this._geocoderElems[e.index];
}
this._geocoderContainer.insertBefore(geocoderElem, beforeElem);
newElems.push(geocoderElem);
}
newElems.reverse();
for (i = e.index; i < e.index + e.nRemoved; i++) {
this._geocoderContainer.removeChild(this._geocoderElems[i]);
}
newElems.splice(0, 0, e.index, e.nRemoved);
[].splice.apply(this._geocoderElems, newElems);
for (i = 0; i < this._geocoderElems.length; i++) {
this._geocoderElems[i].placeholder = this._geocoderPlaceholder(i);
}
},
_geocoderPlaceholder: function(i) {
return i === 0 ?
'Start' :
(i < this._geocoderElems.length - 1 ?
'Via ' + i :
'End');
},
_updateWaypointName: function(i, force) {
var wp = this._waypoints[i];
function updateGeocoder() {
var value = wp && wp.name ? wp.name : '';
if (this._geocoderElems[i]) {
this._geocoderElems[i].value = value;
}
}
if (wp.latLng && (force || !wp.name)) {
if (this.options.geocoder && this.options.geocoder.reverse) {
this.options.geocoder.reverse(wp.latLng, 67108864 /* zoom 18 */, function(rs) {
if (rs.length > 0 && rs[0].center.distanceTo(wp.latLng) < 200) {
wp.name = rs[0].name;
} else {
wp.name = '';
}
updateGeocoder.call(this);
}, this);
} else {
wp.name = '';
}
updateGeocoder.call(this);
}
},
_removeMarkers: function() {
var i;
if (this._markers) {
for (i = 0; i < this._markers.length; i++) {
if (this._markers[i]) {
this._map.removeLayer(this._markers[i]);
}
}
}
this._markers = [];
},
_updateMarkers: function() {
var i,
icon,
options,
m;
if (!this._map) {
return;
}
this._removeMarkers();
for (i = 0; i < this._waypoints.length; i++) {
if (this._waypoints[i].latLng) {
icon = (typeof(this.options.waypointIcon) === 'function') ?
this.options.waypointIcon(i, this._waypoints[i].name, this._waypoints.length) :
this.options.waypointIcon;
options = {
draggable: true
};
if (icon) {
options.icon = icon;
}
m = L.marker(this._waypoints[i].latLng, options).addTo(this._map);
if (this.options.draggableWaypoints) {
this._hookWaypointEvents(m, i);
}
} else {
m = null;
}
this._markers.push(m);
}
},
_fireChanged: function() {
this.fire('waypointschanged', {waypoints: this.getWaypoints()});
if (arguments.length >= 2) {
this.fire('waypointsspliced', {
index: Array.prototype.shift.call(arguments),
nRemoved: Array.prototype.shift.call(arguments),
added: arguments
});
}
},
_hookWaypointEvents: function(m, i) {
m.on('dragstart', function(e) {
this.fire('waypointdragstart', this._createWaypointEvent(i, e));
}, this);
m.on('drag', function(e) {
this.fire('waypointdrag', this._createWaypointEvent(i, e));
}, this);
m.on('dragend', function(e) {
this.fire('waypointdragend', this._createWaypointEvent(i, e));
this._waypoints[i].latLng = e.target.getLatLng();
this._waypoints[i].name = '';
this._updateWaypointName(i, true);
this._fireChanged();
}, this);
},
_createWaypointEvent: function(i, e) {
return {index: i, latlng: e.target.getLatLng()};
},
dragNewWaypoint: function(e) {
var i;
this._newWp = {
afterIndex: e.afterIndex,
marker: L.marker(e.latlng).addTo(this._map),
lines: []
};
for (i = 0; i < this.options.dragStyles.length; i++) {
this._newWp.lines.push(L.polyline([
this._waypoints[e.afterIndex].latLng,
e.latlng,
this._waypoints[e.afterIndex + 1].latLng
], this.options.dragStyles[i]).addTo(this._map));
}
this._markers.splice(e.afterIndex + 1, 0, this._newWp.marker);
this._map.on('mousemove', this._onDragNewWp, this);
this._map.on('mouseup', this._onWpRelease, this);
},
_onDragNewWp: function(e) {
var i;
this._newWp.marker.setLatLng(e.latlng);
for (i = 0; i < this._newWp.lines.length; i++) {
this._newWp.lines[i].spliceLatLngs(1, 1, e.latlng);
}
},
_onWpRelease: function(e) {
var i;
this._map.off('mouseup', this._onWpRelease, this);
this._map.off('mousemove', this._onDragNewWp, this);
for (i = 0; i < this._newWp.lines.length; i++) {
this._map.removeLayer(this._newWp.lines[i]);
}
this.spliceWaypoints(this._newWp.afterIndex + 1, 0, e.latlng);
delete this._newWp;
}
});
L.Routing.plan = function(waypoints, options) {
return new L.Routing.Plan(waypoints, options);
};
})();
(function() {
'use strict';
L.Routing.Control = L.Routing.Itinerary.extend({
options: {
fitSelectedRoutes: true
},
initialize: function(options) {
L.Util.setOptions(this, options);
this._router = this.options.router || new L.Routing.OSRM();
this._plan = this.options.plan || L.Routing.plan(undefined, { geocoder: this.options.geocoder });
if (this.options.geocoder) {
this._plan.options.geocoder = this.options.geocoder;
}
if (this.options.waypoints) {
this._plan.setWaypoints(this.options.waypoints);
}
L.Routing.Itinerary.prototype.initialize.call(this, options);
this.on('routeselected', this._routeSelected, this);
this._plan.on('waypointschanged', this._route, this);
this._route();
},
onAdd: function(map) {
var container = L.Routing.Itinerary.prototype.onAdd.call(this, map);
this._map = map;
this._map.addLayer(this._plan);
if (this.options.geocoder) {
container.insertBefore(this._plan.createGeocoders(), container.firstChild);
}
return container;
},
onRemove: function(map) {
if (this._line) {
map.removeLayer(this._line);
}
map.removeLayer(this._plan);
return L.Routing.Itinerary.prototype.onRemove.call(this, map);
},
getWaypoints: function() {
return this._plan.getWaypoints();
},
setWaypoints: function(waypoints) {
this._plan.setWaypoints(waypoints);
},
spliceWaypoints: function() {
var removed = this._plan.spliceWaypoints.apply(this._plan, arguments);
return removed;
},
getPlan: function() {
return this._plan;
},
_routeSelected: function(e) {
var route = e.route;
this._clearLine();
this._line = L.Routing.line(route, this.options.lineOptions);
this._line.addTo(this._map);
this._hookEvents(this._line);
if (this.options.fitSelectedRoutes) {
this._map.fitBounds(this._line.getBounds());
}
},
_hookEvents: function(l) {
l.on('linetouched', function(e) {
this._plan.dragNewWaypoint(e);
}, this);
},
_route: function() {
this._clearLine();
this._clearAlts();
if (this._plan.isReady()) {
this._router.route(this._plan.getWaypoints(), function(err, routes) {
if (err) {
console.log(err);
return;
}
this.setAlternatives(routes);
}, this);
}
},
_clearLine: function() {
if (this._line) {
this._map.removeLayer(this._line);
delete this._line;
}
}
});
L.Routing.control = function(options) {
return new L.Routing.Control(options);
};
})();
return L.Routing;
}));
// Packaging/modules magic dance end. This code is inserted after all other
// code when the dist is built.