leaflet-routing-machine
Version:
228 lines (188 loc) • 6.57 kB
JavaScript
(function() {
'use strict';
var L = require('leaflet');
var Formatter = require('./formatter');
var ItineraryBuilder = require('./itinerary-builder');
module.exports = L.Control.extend({
includes: ((typeof L.Evented !== 'undefined' && L.Evented.prototype) || L.Mixin.Events),
options: {
pointMarkerStyle: {
radius: 5,
color: '#03f',
fillColor: 'white',
opacity: 1,
fillOpacity: 0.7
},
summaryTemplate: '<h2>{name}</h2><h3>{distance}, {time}</h3>',
timeTemplate: '{time}',
containerClassName: '',
alternativeClassName: '',
minimizedClassName: '',
itineraryClassName: '',
totalDistanceRoundingSensitivity: -1,
show: true,
collapsible: undefined,
collapseBtn: function(itinerary) {
var collapseBtn = L.DomUtil.create('span', itinerary.options.collapseBtnClass);
L.DomEvent.on(collapseBtn, 'click', itinerary._toggle, itinerary);
itinerary._container.insertBefore(collapseBtn, itinerary._container.firstChild);
},
collapseBtnClass: 'leaflet-routing-collapse-btn'
},
initialize: function(options) {
L.setOptions(this, options);
this._formatter = this.options.formatter || new Formatter(this.options);
this._itineraryBuilder = this.options.itineraryBuilder || new ItineraryBuilder({
containerClassName: this.options.itineraryClassName
});
},
onAdd: function(map) {
var collapsible = this.options.collapsible;
collapsible = collapsible || (collapsible === undefined && map.getSize().x <= 640);
this._container = L.DomUtil.create('div', 'leaflet-routing-container leaflet-bar ' +
(!this.options.show ? 'leaflet-routing-container-hide ' : '') +
(collapsible ? 'leaflet-routing-collapsible ' : '') +
this.options.containerClassName);
this._altContainer = this.createAlternativesContainer();
this._container.appendChild(this._altContainer);
L.DomEvent.disableClickPropagation(this._container);
L.DomEvent.addListener(this._container, 'mousewheel', function(e) {
L.DomEvent.stopPropagation(e);
});
if (collapsible) {
this.options.collapseBtn(this);
}
return this._container;
},
onRemove: function() {
},
createAlternativesContainer: function() {
return L.DomUtil.create('div', 'leaflet-routing-alternatives-container');
},
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 = this._createAlternative(alt, i);
this._altContainer.appendChild(altDiv);
this._altElements.push(altDiv);
}
this._selectRoute({route: this._routes[0], alternatives: this._routes.slice(1)});
return this;
},
show: function() {
L.DomUtil.removeClass(this._container, 'leaflet-routing-container-hide');
},
hide: function() {
L.DomUtil.addClass(this._container, 'leaflet-routing-container-hide');
},
_toggle: function() {
var collapsed = L.DomUtil.hasClass(this._container, 'leaflet-routing-container-hide');
this[collapsed ? 'show' : 'hide']();
},
_createAlternative: function(alt, i) {
var altDiv = L.DomUtil.create('div', 'leaflet-routing-alt ' +
this.options.alternativeClassName +
(i > 0 ? ' leaflet-routing-alt-minimized ' + this.options.minimizedClassName : '')),
template = this.options.summaryTemplate,
data = L.extend({
name: alt.name,
distance: this._formatter.formatDistance(alt.summary.totalDistance, this.options.totalDistanceRoundingSensitivity),
time: this._formatter.formatTime(alt.summary.totalTime)
}, alt);
altDiv.innerHTML = typeof(template) === 'function' ? template(data) : L.Util.template(template, data);
L.DomEvent.addListener(altDiv, 'click', this._onAltClicked, this);
this.on('routeselected', this._selectAlt, this);
altDiv.appendChild(this._createItineraryContainer(alt));
return altDiv;
},
_clearAlts: function() {
var el = this._altContainer;
while (el && el.firstChild) {
el.removeChild(el.firstChild);
}
this._altElements = [];
},
_createItineraryContainer: function(r) {
var container = this._itineraryBuilder.createContainer(),
steps = this._itineraryBuilder.createStepsContainer(),
i,
instr,
step,
distance,
text,
icon;
container.appendChild(steps);
for (i = 0; i < r.instructions.length; i++) {
instr = r.instructions[i];
text = this._formatter.formatInstruction(instr, i);
distance = this._formatter.formatDistance(instr.distance);
icon = this._formatter.getIconName(instr, i);
step = this._itineraryBuilder.createStep(text, distance, icon, steps);
if(instr.index) {
this._addRowListeners(step, r.coordinates[instr.index]);
}
}
return container;
},
_addRowListeners: function(row, coordinate) {
L.DomEvent.addListener(row, 'mouseover', function() {
this._marker = L.circleMarker(coordinate,
this.options.pointMarkerStyle).addTo(this._map);
}, this);
L.DomEvent.addListener(row, 'mouseout', function() {
if (this._marker) {
this._map.removeLayer(this._marker);
delete this._marker;
}
}, this);
L.DomEvent.addListener(row, 'click', function(e) {
this._map.panTo(coordinate);
L.DomEvent.stopPropagation(e);
}, this);
},
_onAltClicked: function(e) {
var altElem = e.target || window.event.srcElement;
while (!L.DomUtil.hasClass(altElem, 'leaflet-routing-alt')) {
altElem = altElem.parentElement;
}
var j = this._altElements.indexOf(altElem);
var alts = this._routes.slice();
var route = alts.splice(j, 1)[0];
this.fire('routeselected', {
route: route,
alternatives: alts
});
},
_selectAlt: function(e) {
var altElem,
j,
n,
classFn;
altElem = this._altElements[e.route.routesIndex];
if (L.DomUtil.hasClass(altElem, 'leaflet-routing-alt-minimized')) {
for (j = 0; j < this._altElements.length; j++) {
n = this._altElements[j];
classFn = j === e.route.routesIndex ? 'removeClass' : 'addClass';
L.DomUtil[classFn](n, 'leaflet-routing-alt-minimized');
if (this.options.minimizedClassName) {
L.DomUtil[classFn](n, this.options.minimizedClassName);
}
if (j !== e.route.routesIndex) n.scrollTop = 0;
}
}
L.DomEvent.stop(e);
},
_selectRoute: function(routes) {
if (this._marker) {
this._map.removeLayer(this._marker);
delete this._marker;
}
this.fire('routeselected', routes);
}
});
})();