UNPKG

leaflet-routing-machine

Version:
359 lines (307 loc) 9.18 kB
(function() { 'use strict'; var L = require('leaflet'); var GeocoderElement = require('./geocoder-element'); var Waypoint = require('./waypoint'); module.exports = (L.Layer || L.Class).extend({ includes: ((typeof L.Evented !== 'undefined' && L.Evented.prototype) || L.Mixin.Events), options: { dragStyles: [ {color: 'black', opacity: 0.15, weight: 9}, {color: 'white', opacity: 0.8, weight: 6}, {color: 'red', opacity: 1, weight: 2, dashArray: '7,12'} ], draggableWaypoints: true, routeWhileDragging: false, addWaypoints: true, reverseWaypoints: false, addButtonClassName: '', language: 'en', createGeocoderElement: function(wp, i, nWps, plan) { return new GeocoderElement(wp, i, nWps, plan); }, createMarker: function(i, wp) { var options = { draggable: this.draggableWaypoints }, marker = L.marker(wp.latLng, options); return marker; }, geocodersClassName: '' }, 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); return this; }, spliceWaypoints: function() { var args = [arguments[0], arguments[1]], i; for (i = 2; i < arguments.length; i++) { args.push(arguments[i] && arguments[i].hasOwnProperty('latLng') ? arguments[i] : new Waypoint(arguments[i])); } [].splice.apply(this._waypoints, args); // Make sure there's always at least two waypoints while (this._waypoints.length < 2) { this.spliceWaypoints(this._waypoints.length, 0, null); } 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 ' + this.options.geocodersClassName), waypoints = this._waypoints, addWpBtn, reverseBtn; this._geocoderContainer = container; this._geocoderElems = []; if (this.options.addWaypoints) { addWpBtn = L.DomUtil.create('button', 'leaflet-routing-add-waypoint ' + this.options.addButtonClassName, container); addWpBtn.setAttribute('type', 'button'); L.DomEvent.addListener(addWpBtn, 'click', function() { this.spliceWaypoints(waypoints.length, 0, null); }, this); } if (this.options.reverseWaypoints) { reverseBtn = L.DomUtil.create('button', 'leaflet-routing-reverse-waypoints', container); reverseBtn.setAttribute('type', 'button'); L.DomEvent.addListener(reverseBtn, 'click', function() { this._waypoints.reverse(); this.setWaypoints(this._waypoints); }, this); } this._updateGeocoders(); this.on('waypointsspliced', this._updateGeocoders); return container; }, _createGeocoder: function(i) { var geocoder = this.options.createGeocoderElement(this._waypoints[i], i, this._waypoints.length, this.options); geocoder .on('delete', function() { if (i > 0 || this._waypoints.length > 2) { this.spliceWaypoints(i, 1); } else { this.spliceWaypoints(i, 1, new Waypoint()); } }, this) .on('geocoded', function(e) { this._updateMarkers(); this._fireChanged(); this._focusGeocoder(i + 1); this.fire('waypointgeocoded', { waypointIndex: i, waypoint: e.waypoint }); }, this) .on('reversegeocoded', function(e) { this.fire('waypointgeocoded', { waypointIndex: i, waypoint: e.waypoint }); }, this); return geocoder; }, _updateGeocoders: function() { var elems = [], i, geocoderElem; for (i = 0; i < this._geocoderElems.length; i++) { this._geocoderContainer.removeChild(this._geocoderElems[i].getContainer()); } for (i = this._waypoints.length - 1; i >= 0; i--) { geocoderElem = this._createGeocoder(i); this._geocoderContainer.insertBefore(geocoderElem.getContainer(), this._geocoderContainer.firstChild); elems.push(geocoderElem); } this._geocoderElems = elems.reverse(); }, _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, m; if (!this._map) { return; } this._removeMarkers(); for (i = 0; i < this._waypoints.length; i++) { if (this._waypoints[i].latLng) { m = this.options.createMarker(i, this._waypoints[i], this._waypoints.length); if (m) { m.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, trackMouseMove) { var eventLatLng = function(e) { return trackMouseMove ? e.latlng : e.target.getLatLng(); }, dragStart = L.bind(function(e) { this.fire('waypointdragstart', {index: i, latlng: eventLatLng(e)}); }, this), drag = L.bind(function(e) { this._waypoints[i].latLng = eventLatLng(e); this.fire('waypointdrag', {index: i, latlng: eventLatLng(e)}); }, this), dragEnd = L.bind(function(e) { this._waypoints[i].latLng = eventLatLng(e); this._waypoints[i].name = ''; if (this._geocoderElems) { this._geocoderElems[i].update(true); } this.fire('waypointdragend', {index: i, latlng: eventLatLng(e)}); this._fireChanged(); }, this), mouseMove, mouseUp; if (trackMouseMove) { mouseMove = L.bind(function(e) { this._markers[i].setLatLng(e.latlng); drag(e); }, this); mouseUp = L.bind(function(e) { this._map.dragging.enable(); this._map.off('mouseup', mouseUp); this._map.off('mousemove', mouseMove); dragEnd(e); }, this); this._map.dragging.disable(); this._map.on('mousemove', mouseMove); this._map.on('mouseup', mouseUp); dragStart({latlng: this._waypoints[i].latLng}); } else { m.on('dragstart', dragStart); m.on('drag', drag); m.on('dragend', dragEnd); } }, dragNewWaypoint: function(e) { var newWpIndex = e.afterIndex + 1; if (this.options.routeWhileDragging) { this.spliceWaypoints(newWpIndex, 0, e.latlng); this._hookWaypointEvents(this._markers[newWpIndex], newWpIndex, true); } else { this._dragNewWaypoint(newWpIndex, e.latlng); } }, _dragNewWaypoint: function(newWpIndex, initialLatLng) { var wp = new Waypoint(initialLatLng), prevWp = this._waypoints[newWpIndex - 1], nextWp = this._waypoints[newWpIndex], marker = this.options.createMarker(newWpIndex, wp, this._waypoints.length + 1), lines = [], draggingEnabled = this._map.dragging.enabled(), mouseMove = L.bind(function(e) { var i, latLngs; if (marker) { marker.setLatLng(e.latlng); } for (i = 0; i < lines.length; i++) { latLngs = lines[i].getLatLngs(); latLngs.splice(1, 1, e.latlng); lines[i].setLatLngs(latLngs); } L.DomEvent.stop(e); }, this), mouseUp = L.bind(function(e) { var i; if (marker) { this._map.removeLayer(marker); } for (i = 0; i < lines.length; i++) { this._map.removeLayer(lines[i]); } this._map.off('mousemove', mouseMove); this._map.off('mouseup', mouseUp); this.spliceWaypoints(newWpIndex, 0, e.latlng); if (draggingEnabled) { this._map.dragging.enable(); } L.DomEvent.stop(e); }, this), i; if (marker) { marker.addTo(this._map); } for (i = 0; i < this.options.dragStyles.length; i++) { lines.push(L.polyline([prevWp.latLng, initialLatLng, nextWp.latLng], this.options.dragStyles[i]).addTo(this._map)); } if (draggingEnabled) { this._map.dragging.disable(); } this._map.on('mousemove', mouseMove); this._map.on('mouseup', mouseUp); }, _focusGeocoder: function(i) { if (this._geocoderElems[i]) { this._geocoderElems[i].focus(); } else { document.activeElement.blur(); } } }); })();