226 lines
6.3 KiB
JavaScript
226 lines
6.3 KiB
JavaScript
(function() {
|
|
'use strict';
|
|
|
|
var L = require('leaflet');
|
|
var Formatter = require('./formatter');
|
|
var ItineraryBuilder = require('./itinerary-builder');
|
|
|
|
module.exports = L.Control.extend({
|
|
includes: 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);
|
|
|
|
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);
|
|
}
|
|
});
|
|
})();
|