// 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.