check-in bower_components

This commit is contained in:
Norbert Renner 2014-01-27 18:46:51 +01:00
parent 4cc16bccd0
commit 9e08e74132
101 changed files with 90960 additions and 0 deletions

View file

@ -0,0 +1,286 @@
/*
* L.Routing.Draw class
*
* Responsible for drawing and contine drawing
*
* @dependencies L, L.Routing
*
* @usage new L.Routing.Draw(map, options);
*/
L.Routing.Draw = L.Handler.extend({
// INCLUDES
includes: [L.Mixin.Events]
// OPTIONS
,options: {}
/**
* Draw Constructor
*
* @access public
*
* @param <> parent - parent class instance
* @param <Oject> options - routing options
*
* @return void
*
* @todo fetch last waypoint
*/
,initialize: function (parent, options) {
this._parent = parent;
this._map = parent._map;
this._enabled = false;
L.Util.setOptions(this, options);
}
/**
* Enable drawing
*
* @access public
*
* @event map.routing:draw-start
* @event map.routing:draw-new
* @event map.routing:draw-continue
*
* @return void
*/
,enable: function() {
if (this._enabled) { return; }
this._enabled = true;
this._hidden = false;
this._dragging = false;
this._addHooks();
this.fire('enabled');
this._map.fire('routing:draw-start');
if (this._parent._segments._layers.length === 0) {
this._map.fire('routing:draw-new');
} else {
this._map.fire('routing:draw-continue');
}
}
/**
* Disable drawing
*
* @access public
*
* @event map.routing:draw-end
*
* @return void
*/
,disable: function() {
if (!this._enabled) { return; }
this._enabled = false;
this._removeHooks();
this.fire('disabled');
this._map.fire('routing:draw-end');
}
/**
* Add hooks
*
* @access private
*
* @return void
*
* @todo hide and style the trailer!
*/
,_addHooks: function() {
if (!this._map) { return; }
// Visible Marker
if (!this._marker) {
this._marker = new L.Marker(this._map.getCenter(), {
icon: this.options.icons.normal
,zIndexOffset: this.options.zIndexOffset
,clickable: false
});
}
// Trailing line
if (!this._trailer) {
var ll = this._map.getCenter();
this._trailer = new L.Polyline([ll, ll], {
opacity: 0.2
,clickable: false
});
}
this._parent.on('waypoint:mouseover', this._catchWaypointEvent, this);
this._parent.on('waypoint:mouseout' , this._catchWaypointEvent, this);
this._parent.on('waypoint:dragstart', this._catchWaypointEvent, this);
this._parent.on('waypoint:dragend' , this._catchWaypointEvent, this);
this._parent.on('segment:mouseover' , this._catchWaypointEvent, this);
this._parent.on('segment:mouseout' , this._catchWaypointEvent, this);
this._parent.on('segment:dragstart' , this._catchWaypointEvent, this);
this._parent.on('segment:dragend' , this._catchWaypointEvent, this);
this._map.on('mousemove', this._onMouseMove, this);
this._map.on('click', this._onMouseClick, this);
this._marker.addTo(this._map);
this._trailer.addTo(this._map);
}
/**
* Remove hooks
*
* This method is invoked after the `disable()` has been called and removes
* all the hooks set up using the `_addHooks()` method.
*
* @access private
*
* @return void
*/
,_removeHooks: function() {
if (!this._map) { return; }
this._parent.off('waypoint:mouseover', this._catchWaypointEvent, this);
this._parent.off('waypoint:mouseout' , this._catchWaypointEvent, this);
this._parent.off('waypoint:dragstart', this._catchWaypointEvent, this);
this._parent.off('waypoint:dragend' , this._catchWaypointEvent, this);
this._parent.off('segment:mouseover' , this._catchWaypointEvent, this);
this._parent.off('segment:mouseout' , this._catchWaypointEvent, this);
this._parent.off('segment:dragstart' , this._catchWaypointEvent, this);
this._parent.off('segment:dragend' , this._catchWaypointEvent, this);
this._map.off('click', this._onMouseClick, this);
this._map.off('mousemove', this._onMouseMove, this);
this._map.removeLayer(this._marker);
this._map.removeLayer(this._trailer);
delete this._marker;
delete this._trailer;
}
/**
* Handle waypoint events
*
* @access private
*
* @param <L.Event> e - waypoint event
*
* @return void
*/
,_catchWaypointEvent: function(e) {
var type = e.type.split(':')[1];
if (this._hidden) {
if (this._dragging) {
if (type === 'dragend') {
this._dragging = false;
}
} else {
if (type === 'mouseout') {
this._show();
} else if (type === 'dragstart') {
this._dragging = true;
}
}
} else {
if (type === 'mouseover') {
this._hide();
}
}
}
/**
* Hide HUD
*
* Call this method in order to quickly hide graphical drawing elements for
* instance hoovering over draggable objects which should tempoarily disable
* dragging.
*
* @access private
*
* @return void
*/
,_hide: function() {
this._hidden = true;
this._marker.setOpacity(0.0);
this._trailer.setStyle({opacity: 0.0});
}
/**
* Show HUD
*
* Call this method to restore graphical drawing elements after they have been
* hidden.
*
* @access private
*
* @return void
*/
,_show: function() {
this._hidden = false;
this._marker.setOpacity(1.0);
this._trailer.setStyle({opacity: 0.2});
}
/**
* Mouse move handler
*
* @access private
*
* @param <L.Event> e - mouse move event
*
* @return void
*/
,_onMouseMove : function(e) {
if (this._hidden) { return; }
var latlng = e.latlng;
var last = this._parent.getLast();
if (this.options.snapping) {
latlng = L.LineUtil.snapToLayers(latlng, null, this.options.snapping);
}
this._marker.setLatLng(latlng);
if (last !== null) {
this._trailer.setLatLngs([last.getLatLng(), latlng]);
};
}
/**
* Mouse click handler
*
* @access private
*
* @param <L.Event> e - mouse click event
*
* @event map.routing:new-waypoint
*
* @return void
*/
,_onMouseClick: function(e) {
if (this._hidden) { return; }
var marker, latlng, last;
latlng = e.latlng;
if (this.options.snapping) {
latlng = L.LineUtil.snapToLayers(latlng, null, this.options.snapping);
}
marker = new L.Marker(latlng);
last = this._parent.getLast();
this._trailer.setLatLngs([latlng, latlng]);
this._parent.addWaypoint(marker, last, null, function(err, data) {
// console.log(err, data);
});
}
});

View file

@ -0,0 +1,387 @@
/*
* L.Routing.Edit class
*
* Responsible handle edits
*
* @dependencies L, L.Routing
*
* @usage new L.Routing.Draw(map, options);
*/
L.Routing.Edit = L.Handler.extend({
// INCLUDES
includes: [L.Mixin.Events]
// OPTIONS
,options: {}
/**
* Edit Constructor
*
* @access public
*
* @param <> parent - parent class instance
* @param <Oject> options - routing options
*
* @return void
*
* @todo fetch last waypoint
*/
,initialize: function (parent, options) {
this._parent = parent;
this._map = parent._map;
this._enabled = false;
L.Util.setOptions(this, options);
}
/**
* Enable drawing
*
* @access public
*
* @event map.routing:edit-start
*
* @return void
*/
,enable: function() {
if (this._enabled) { return; }
this._enabled = true;
this._addHooks();
this.fire('enabled');
this._map.fire('routing:edit-start');
}
/**
* Disable drawing
*
* @access public
*
* @event map.draw:edit-end
*
* @return void
*/
,disable: function() {
if (!this._enabled) { return; }
this._enabled = false;
this._removeHooks();
this.fire('disabled');
this._map.fire('routing:edit-end');
}
/**
* Add hooks
*
* This method is invoked when `enable()` is called and sets up all
* necessary hooks such as:
* * text selection
* * key listeners
* * mouse marker
*
* @access private
*
* @return void
*
* @todo hide and style the trailer!
*/
,_addHooks: function() {
if (!this._map) { return; }
if (!this._mouseMarker) {
this._mouseMarker = L.marker(this._map.getCenter(), {
icon: L.divIcon({
className: 'line-mouse-marker'
,iconAnchor: [5, 5]
,iconSize: [10, 10]
})
,clickable: true
,draggable: true
,opacity: 0
,zIndexOffset: this.options.zIndexOffset
});
}
this._mouseMarker.addTo(this._map);
if (!this._trailer1) {
var ll = this._map.getCenter();
var style = {opacity: 0.0,clickable: false};
this._trailer1 = new L.Polyline([ll, ll], style);
this._trailer2 = new L.Polyline([ll, ll], style);
}
this._trailer1.addTo(this._map);
this._trailer2.addTo(this._map);
this._parent.on('segment:mouseover' , this._segmentOnMouseover, this);
this._mouseMarker.on('dragstart' , this._segmentOnDragstart, this);
this._mouseMarker.on('drag' , this._segmentOnDrag, this);
this._mouseMarker.on('dragend' , this._segmentOnDragend, this);
this._parent.on('waypoint:dragstart', this._waypointOnDragstart, this);
this._parent.on('waypoint:drag' , this._waypointOnDrag, this);
this._parent.on('waypoint:dragend' , this._waypointOnDragend, this);
}
/**
* Remove hooks
*
* This method is invoked after the `disable()` has been called and removes
* all the hooks set up using the `_addHooks()` method.
*
* @access private
*
* @return void
*/
,_removeHooks: function() {
if (!this._map) { return; }
// this._trailer1.addTo(this._map);
// this._trailer2.addTo(this._map);
this._parent.off('segment:mouseover' , this._segmentOnMouseover, this);
this._mouseMarker.off('dragstart' , this._segmentOnDragstart, this);
this._mouseMarker.off('drag' , this._segmentOnDrag, this);
this._mouseMarker.off('dragend' , this._segmentOnDragend, this);
this._parent.off('waypoint:dragstart', this._waypointOnDragstart, this);
this._parent.off('waypoint:drag' , this._waypointOnDrag, this);
this._parent.off('waypoint:dragend' , this._waypointOnDragend, this);
}
/**
* Fired when the mouse first enters a segment
*
* @access private
*
* @param <L.Event> e - mouse over event
*
* @return void
*/
,_segmentOnMouseover: function(e) {
this._mouseMarker.setOpacity(1.0);
this._map.on('mousemove', this._segmentOnMousemove, this);
}
/**
* Fired when the mouse leaves a segement
*
* @access private
*
* @param <L.Event> e - mouse move event
*
* @return void
*/
,_segmentOnMouseout: function(e) {
if (this._dragging) { return; }
this._mouseMarker.setOpacity(0.0);
this._map.off('mousemove', this._segmentOnMousemove, this);
this.fire('segment:mouseout');
}
/**
* Fired when the mouse is moved
*
* This method is fired continously when mouse is moved in edition mode.
*
* @access private
*
* @param <L.Event> e - mouse move event
*
* @return void
*/
,_segmentOnMousemove: function(e) {
if (this._dragging) { return; }
var latlng = L.LineUtil.snapToLayers(e.latlng, null, {
layers: [this._parent._segments]
,sensitivity: 40
,vertexonly: false
});
if (latlng._feature === null) {
this._segmentOnMouseout(e);
} else {
this._mouseMarker._snapping = latlng._feature._routing;
this._mouseMarker.setLatLng(latlng);
}
}
/**
* Mouse marker dragstart
*
* @access private
*
* @param <L.Event> e - mouse dragstart event
*
* @return void
*/
,_segmentOnDragstart: function(e) {
var latlng = e.target.getLatLng();
var next = e.target._snapping.nextMarker;
var prev = e.target._snapping.prevMarker;
this._setTrailers(latlng, next, prev, true);
this._dragging = true;
this.fire('segment:dragstart');
}
/**
* Fired when a marker is dragged
*
* This method is fired continously when dragging a marker and snapps the
* marker to the snapping layer.
*
* @access private
*
* @param <L.Event> e - mouse drag event
*
* @return void
*/
,_segmentOnDrag: function(e) {
var latlng = e.target.getLatLng();
var next = e.target._snapping.nextMarker;
var prev = e.target._snapping.prevMarker;
if (this.options.snapping) {
latlng = L.LineUtil.snapToLayers(latlng, null, this.options.snapping);
}
e.target.setLatLng(latlng);
this._setTrailers(latlng, next, prev);
}
/**
* Mouse marker dragend
*
* @access private
*
* @param <L.Event> e - mouse dragend event
*
* @return void
*/
,_segmentOnDragend: function(e) {
var next = this._mouseMarker._snapping.nextMarker;
var prev = this._mouseMarker._snapping.prevMarker;
var latlng = this._mouseMarker.getLatLng();
this._parent.addWaypoint(latlng, prev, next, function(err, data) {
//console.log(err, data);
});
this._dragging = false;
this._setTrailers(null, null, null, false);
this.fire('segment:dragend');
}
/**
* Fired when marker drag start
*
* @access private
*
* @param <L.Event> e - mouse dragend event
*
* @return void
*/
,_waypointOnDragstart: function(e) {
var next = e.marker._routing.nextMarker;
var prev = e.marker._routing.prevMarker;
this._setTrailers(e.marker.getLatLng(), next, prev, true);
}
/**
* Fired while dragging marker
*
* @access private
*
* @access private
*
* @param <L.Event> e - mouse drag event
*
* @return void
*/
,_waypointOnDrag: function(e) {
var latlng = e.marker._latlng;
var next = e.marker._routing.nextMarker;
var prev = e.marker._routing.prevMarker;
if (this.options.snapping) {
latlng = L.LineUtil.snapToLayers(latlng, null, this.options.snapping);
}
e.marker.setLatLng(latlng);
this._setTrailers(latlng, next, prev);
}
/**
* Fired when marker drag ends
*
* @access private
*
* @param <L.Event> e - mouse dragend event
*
* @return void
*/
,_waypointOnDragend: function(e) {
this._setTrailers(null, null, null, false);
this._parent.routeWaypoint(e.marker, function(err, data) {
//console.log('_waypointOnDragend.cb', err, data);
});
}
/**
* Fired when marker is clicked
*
* This method is fired when a marker is clicked by the user. It will then
* procede to remove the marker and reroute any connected line segments.
*
* @access private
*
* @param <L.Event> e - mouse click event
*
* @return void
*/
,_waypointOnClick: function(e) {
this._parent.removeWaypoint(e.layer, function(err, data) {
//console.log('_waypointOnDragend.cb', err, data);
});
}
/**
* Set trailing guide lines
*
*/
,_setTrailers: function(latlng, next, prev, show) {
if (typeof show !== 'undefined') {
if (show === false) {
this._trailer1.setStyle({opacity: 0.0});
this._trailer2.setStyle({opacity: 0.0});
return;
} else {
if (next !== null) {
this._trailer1.setStyle({opacity: 0.2});
}
if (prev !== null) {
this._trailer2.setStyle({opacity: 0.2});
}
}
}
if (next) {
this._trailer1.setLatLngs([latlng, next.getLatLng()]);
}
if (prev) {
this._trailer2.setLatLngs([latlng, prev.getLatLng()]);
}
}
});

View file

@ -0,0 +1,31 @@
/*
* Leaflet Routing Storage
*
* Storing routable objects
*
* @dependencies L, L.Routing
*
* @usage new L.Routing(options);
*/
(function () {
L.Routing.Storage = L.MultiPolyline.extend({
/**
* Class constructor
*/
initialize: function (latlngs, options) {
this._layers = {};
this._options = options;
this.setLatLngs(latlngs);
this.on('layeradd', function() {
console.log('layeradd', arguments);
}, this);
}
});
L.Routing.storage = function (latlngs, options) {
return new L.MultiPolyline(latlngs, options);
};
}());

View file

@ -0,0 +1,556 @@
/*
* L.Routing main class
*
* Main clase for the Leaflet routing module
*
* @dependencies L
*
* @usage new L.Routing(options);
*
* @todo use L.Class.extend instead?
*/
L.Routing = L.Control.extend({
// INCLUDES
includes: [L.Mixin.Events]
// CONSTANTS
,statics: {
VERSION: '0.0.2-dev'
}
// OPTIONS
,options: {
position: 'topleft'
,icons: {
start: new L.Icon.Default()
,end: new L.Icon.Default()
,normal: new L.Icon.Default()
}
,zIndexOffset: 2000
,routing: {
router: null // function (<L.Latlng> l1, <L.Latlng> l2, <Function> cb)
}
,snapping: {
layers: [] // layers to snap to
,sensitivity: 10 // snapping sensitivity
,vertexonly: false // vertex only snapping
}
}
/**
* Routing Constructor
*
* @access public
*
* @param <Object> options - non-default options
*
* @todo render display of segments and waypoints
*/
,initialize: function (options) {
this._editing = false;
this._drawing = false;
L.Util.setOptions(this, options);
}
/**
* Called when controller is added to map
*
* @access public
*
* @param <L.Map> map - map instance
*
* @return <HTMLElement> container
*/
,onAdd: function (map) {
this._map = map;
this._container = this._map._container;
this._overlayPane = this._map._panes.overlayPane;
this._popupPane = this._map._panes.popupPane;
this._router = this.options.routing.router;
this._segments = new L.FeatureGroup().addTo(map);
this._waypoints = new L.FeatureGroup().addTo(map);
this._waypoints._first = null;
this._waypoints._last = null;
//L.DomUtil.disableTextSelection();
//this._tooltip = new L.Tooltip(this._map);
//this._tooltip.updateContent({ text: L.drawLocal.draw.marker.tooltip.start });
L.DomEvent.addListener(this._container, 'keyup', this._keyupListener, this);
this._draw = new L.Routing.Draw(this, {
icons: this.options.icons
,zIndexOffset: this.options.zIndexOffset
,snapping: this.options.snapping
});
this._edit = new L.Routing.Edit(this, {
icons: this.options.icons
,zIndexOffset: this.options.zIndexOffset
,snapping: this.options.snapping
});
this._edit.enable();
this.on('waypoint:click', this._waypointClickHandler, this)
this._segments.on('mouseover' , this._fireSegmentEvent, this);
this._edit.on('segment:mouseout' , this._fireSegmentEvent, this);
this._edit.on('segment:dragstart', this._fireSegmentEvent, this);
this._edit.on('segment:dragend' , this._fireSegmentEvent, this);
var container = L.DomUtil.create('div', 'leaflet-routing');
return container;
}
/**
* Called when controller is removed from map
*
* @access public
*
* @param <L.Map> map - map instance
*/
,onRemove: function(map) {
//L.DomUtil.create('div', 'leaflet-routing'); <= delete this
this.off('waypoint:click', this._waypointClickHandler, this)
this._segments.off('mouseover' , this._fireSegmentEvent, this);
this._edit.off('segment:mouseout' , this._fireSegmentEvent, this);
this._edit.off('segment:dragstart', this._fireSegmentEvent, this);
this._edit.off('segment:dragend' , this._fireSegmentEvent, this);
this._edit.disable();
this._draw.disable();
L.DomUtil.enableTextSelection();
// this._tooltip.dispose();
// this._tooltip = null;
L.DomEvent.removeListener(this._container, 'keyup', this._keyupListener);
delete this._draw;
delete this._edit;
delete this._map;
delete this._router;
delete this._segments;
delete this._waypoints;
delete this.options;
}
,_waypointClickHandler: function(e) {
this.removeWaypoint(e.marker, function() {
console.log(arguments);
});
}
/**
* Add new waypoint to path
*
* @access public
*
* @param <L.Marker> marker - new waypoint marker (can be ll)
* @param <L.Marker> prev - previous waypoint marker
* @param <L.Marker> next - next waypoint marker
* @param <Function> cb - callback method
*
* @return void
*/
,addWaypoint: function(marker, prev, next, cb) {
if (marker instanceof L.LatLng) {
marker = new L.Marker(marker);
}
marker._routing = {
prevMarker : prev
,nextMarker : next
,prevLine : null
,nextLine : null
,timeoutID : null
};
if (this._waypoints._first === null && this._waypoints._last === null) {
this._waypoints._first = marker;
this._waypoints._last = marker;
} else if (next === null) {
this._waypoints._last = marker;
} else if (prev === null) {
this._waypoints._first = marker;
}
if (marker._routing.prevMarker !== null) {
marker._routing.prevMarker._routing.nextMarker = marker;
marker._routing.prevLine = marker._routing.prevMarker._routing.nextLine;
if (marker._routing.prevLine !== null) {
marker._routing.prevLine._routing.nextMarker = marker;
}
}
if (marker._routing.nextMarker !== null) {
marker._routing.nextMarker._routing.prevMarker = marker;
marker.nextLine = marker._routing.nextMarker._routing.prevLine;
if (marker._routing.nextLine !== null) {
marker._routing.nextLine._routing.prevMarker = marker;
}
}
marker.on('mouseover', this._fireWaypointEvent, this);
marker.on('mouseout' , this._fireWaypointEvent, this);
marker.on('dragstart', this._fireWaypointEvent, this);
marker.on('dragend' , this._fireWaypointEvent, this);
marker.on('drag' , this._fireWaypointEvent, this);
marker.on('click' , this._fireWaypointEvent, this);
this.routeWaypoint(marker, cb);
this._waypoints.addLayer(marker);
marker.dragging.enable();
}
/**
* Remove a waypoint from path
*
* @access public
*
* @param <L.Marker> marker - new waypoint marker (can be ll)
* @param <Function> cb - callback method
*
* @return void
*/
,removeWaypoint: function(marker, cb) {
marker.off('mouseover', this._fireWaypointEvent, this);
marker.off('mouseout' , this._fireWaypointEvent, this);
marker.off('dragstart', this._fireWaypointEvent, this);
marker.off('dragend' , this._fireWaypointEvent, this);
marker.off('drag' , this._fireWaypointEvent, this);
marker.off('click' , this._fireWaypointEvent, this);
var prev = marker._routing.prevMarker;
var next = marker._routing.nextMarker;
if (this._waypoints._first && marker._leaflet_id === this._waypoints._first._leaflet_id) {
this._waypoints._first = next;
}
if (this._waypoints._last && marker._leaflet_id === this._waypoints._last._leaflet_id) {
this._waypoints._last = prev;
}
if (prev !== null) {
prev._routing.nextMarker = next;
prev._routing.nextLine = null;
}
if (next !== null) {
next._routing.prevMarker = prev;
next._routing.prevLine = null;
}
if (marker._routing.nextLine !== null) {
this._segments.removeLayer(marker._routing.nextLine);
}
if (marker._routing.prevLine !== null) {
this._segments.removeLayer(marker._routing.prevLine);
}
this._waypoints.removeLayer(marker);
if (prev !== null) {
this.routeWaypoint(prev, cb);
} else if (next !== null) {
this.routeWaypoint(next, cb);
} else {
this._draw.enable();
cb(null, null);
}
}
/**
* Route with respect to waypoint
*
* @access public
*
* @param <L.Marker> marker - marker to route on
* @param <Function> cb - callback function
*
* @return void
*
* @todo add propper error checking for callback
*/
,routeWaypoint: function(marker, cb) {
var i = 0;
var $this = this;
var callback = function(err, data) {
i++;
if (i === 2) {
$this.fire('routing:routeWaypointEnd');
cb(err, marker);
}
}
this.fire('routing:routeWaypointStart');
this._routeSegment(marker._routing.prevMarker, marker, callback);
this._routeSegment(marker, marker._routing.nextMarker, callback);
}
/**
* Route segment between two markers
*
* @access private
*
* @param <L.Marker> m1 - first waypoint marker
* @param <L.Marker> m2 - second waypoint marker
* @param <Function> cb - callback function (<Error> err, <String> data)
*
* @return void
*
* @todo logic if router fails
*/
,_routeSegment: function(m1, m2, cb) {
var $this = this;
if (m1 === null || m2 === null) {
return cb(null, true);
}
this._router(m1.getLatLng(), m2.getLatLng(), function(err, layer) {
if (typeof layer === 'undefined') {
var layer = new L.Polyline([m1.getLatLng(), m2.getLatLng()]);
}
layer._routing = {
prevMarker: m1
,nextMarker: m2
};
if (m1._routing.nextLine !== null) {
$this._segments.removeLayer(m1._routing.nextLine);
}
$this._segments.addLayer(layer);
m1._routing.nextLine = layer;
m2._routing.prevLine = layer;
return cb(null, layer);
});
}
/**
* Iterate over all segments and execute callback for each segment
*
* @access private
*
* @param <function> callback - function to call for each segment
* @param <object> context - callback execution context (this). Optional, default: this
*
* @return void
*/
,_eachSegment: function(callback, context) {
var thisArg = context || this;
var marker = this.getFirst();
if (marker === null) { return; }
while (marker._routing.nextMarker !== null) {
var m1 = marker;
var m2 = marker._routing.nextMarker;
var line = marker._routing.nextLine;
callback.call(thisArg, m1, m2, line);
marker = marker._routing.nextMarker;
}
}
/**
* Fire events
*
* @access private
*
* @param <L.Event> e - mouse event
*
* @return void
*/
,_fireWaypointEvent: function(e) {
this.fire('waypoint:' + e.type, {marker:e.target});
}
/**
*
*/
,_fireSegmentEvent: function(e) {
if (e.type.split(':').length === 2) {
this.fire(e.type);
} else {
this.fire('segment:' + e.type);
}
}
/**
* Get first waypoint
*
* @access public
*
* @return L.Marker
*/
,getFirst: function() {
return this._waypoints._first;
}
/**
* Get last waypoint
*
* @access public
*
* @return L.Marker
*/
,getLast: function() {
return this._waypoints._last;
}
/**
* Get all waypoints
*
* @access public
*
* @return <L.LatLng[]> all waypoints or empty array if none
*/
,getWaypoints: function() {
var latLngs = [];
this._eachSegment(function(m1) {
latLngs.push(m1.getLatLng());
});
if (this.getLast()) {
latLngs.push(this.getLast().getLatLng());
}
return latLngs;
}
/**
* Concatenates all route segments to a single polyline
*
* @access public
*
* @return <L.Polyline> polyline, with empty _latlngs when no route segments
*/
,toPolyline: function() {
var latLngs = [];
this._eachSegment(function(m1, m2, line) {
latLngs = latLngs.concat(line.getLatLngs());
});
return L.polyline(latLngs);
}
/**
* Export route to GeoJSON
*
* @access public
*
* @param <boolean> enforce2d - enforce 2DGeoJSON
*
* @return <object> GeoJSON object
*
*/
,toGeoJSON: function(enforce2d) {
var geojson = {type: "LineString", properties: {waypoints: []}, coordinates: []};
var current = this._waypoints._first;
if (current === null) { return geojson; }
geojson.properties.waypoints.push([current.getLatLng().lng, current.getLatLng().lat]);
while (current._routing.nextMarker) {
var next = current._routing.nextMarker
geojson.properties.waypoints.push([next.getLatLng().lng, next.getLatLng().lat]);
var tmp = current._routing.nextLine.getLatLngs();
for (var i = 0; i < tmp.length; i++) {
if (tmp[i].alt && (typeof enforce2d === 'undefined' || enforce2d === false)) {
geojson.coordinates.push([tmp[i].lat, tmp[i].lng, tmp[i].alt]);
} else {
geojson.coordinates.push([tmp[i].lat, tmp[i].lng]);
}
}
current = current._routing.nextMarker;
}
return geojson
}
/**
* Start (or continue) drawing
*
* Call this method in order to start or continue drawing. The drawing handler
* will be activate and the user can draw on the map.
*
* @access public
*
* @return void
*
* @todo check enable
*/
,draw: function (enable) {
if (typeof enable === 'undefined') {
var enable = true;
}
if (enable) {
this._draw.enable();
} else {
this._draw.disable();
}
}
/**
* Enable or disable routing
*
* @access public
*
* @return void
*
* @todo check enable
*/
,routing: function (enable) {
throw new Error('Not implemented');
}
/**
* Enable or disable snapping
*
* @access public
*
* @return void
*
* @todo check enable
*/
,snapping: function (enable) {
throw new Error('Not implemented');
}
/**
* Key up listener
*
* * `ESC` to cancel drawing
* * `M` to enable drawing
*
* @access private
*
* @return void
*/
,_keyupListener: function (e) {
if (e.keyCode === 27) {
this._draw.disable();
} else if (e.keyCode === 77) {
this._draw.enable();
}
}
});

View file

@ -0,0 +1,186 @@
L.Util.extend(L.LineUtil, {
/**
* Snap to all layers
*
* @param <Latlng> latlng - original position
* @param <Number> id - leaflet unique id
* @param <Object> opts - snapping options
*
* @return <Latlng> closest point
*/
snapToLayers: function (latlng, id, opts) {
var i, j, keys, feature, res, sensitivity, vertexonly, layers, minDist, minPoint, map;
sensitivity = opts.sensitivity || 10;
vertexonly = opts.vertexonly || false;
layers = opts.layers || [];
minDist = Infinity;
minPoint = latlng;
minPoint._feature = null; // containing layer
map = opts.layers[0]._map; // @todo check for undef
for (i = 0; i < opts.layers.length; i++) {
keys = Object.keys(opts.layers[i]._layers);
for (j = 0; j < keys.length; j++) {
feature = opts.layers[i]._layers[keys[j]];
// Don't even try snapping to itself!
if (id === feature._leaflet_id) { continue; }
// GeometryCollection
if (feature._layers) {
var newLatlng = this.snapToLayers(latlng, id, {
'sensitivity': sensitivity,
'vertexonly': vertexonly,
'layers': [feature]
});
// What if this is the same?
res = {'minDist': latlng.distanceTo(newLatlng), 'minPoint': newLatlng};
// Marker
} else if (feature instanceof L.Marker) {
res = this._snapToLatlngs(latlng, [feature.getLatLng()], map, sensitivity, vertexonly, minDist);
// Polyline
} else if (feature instanceof L.Polyline) {
res = this._snapToLatlngs(latlng, feature.getLatLngs(), map, sensitivity, vertexonly, minDist);
// MultiPolyline
} else if (feature instanceof L.MultiPolyline) {
console.error('Snapping to MultiPolyline is currently unsupported', feature);
res = {'minDist': minDist, 'minPoint': minPoint};
// Polygon
} else if (feature instanceof L.Polygon) {
res = this._snapToPolygon(latlng, feature, map, sensitivity, vertexonly, minDist);
// MultiPolygon
} else if (feature instanceof L.MultiPolygon) {
res = this._snapToMultiPolygon(latlng, feature, map, sensitivity, vertexonly, minDist);
// Unknown
} else {
console.error('Unsupported snapping feature', feature);
res = {'minDist': minDist, 'minPoint': minPoint};
}
if (res.minDist < minDist) {
minDist = res.minDist;
minPoint = res.minPoint;
minPoint._feature = feature;
}
}
}
return minPoint;
},
/**
* Snap to Polygon
*
* @param <Latlng> latlng - original position
* @param <L.Polygon> feature -
* @param <L.Map> map -
* @param <Number> sensitivity -
* @param <Boolean> vertexonly -
* @param <Number> minDist -
*
* @return <Object> minDist and minPoint
*/
_snapToPolygon: function (latlng, polygon, map, sensitivity, vertexonly, minDist) {
var res, keys, latlngs, i, minPoint;
minPoint = null;
latlngs = polygon.getLatLngs();
latlngs.push(latlngs[0]);
res = this._snapToLatlngs(latlng, polygon.getLatLngs(), map, sensitivity, vertexonly, minDist);
if (res.minDist < minDist) {
minDist = res.minDist;
minPoint = res.minPoint;
}
keys = Object.keys(polygon._holes);
for (i = 0; i < keys.length; i++) {
latlngs = polygon._holes[keys[i]];
latlngs.push(latlngs[0]);
res = this._snapToLatlngs(latlng, polygon._holes[keys[i]], map, sensitivity, vertexonly, minDist);
if (res.minDist < minDist) {
minDist = res.minDist;
minPoint = res.minPoint;
}
}
return {'minDist': minDist, 'minPoint': minPoint};
},
/**
* Snap to MultiPolygon
*
* @param <Latlng> latlng - original position
* @param <L.Polygon> feature -
* @param <L.Map> map -
* @param <Number> sensitivity -
* @param <Boolean> vertexonly -
* @param <Number> minDist -
*
* @return <Object> minDist and minPoint
*/
_snapToMultiPolygon: function (latlng, multipolygon, map, sensitivity, vertexonly, minDist) {
var i, keys, res, minPoint;
minPoint = null;
keys = Object.keys(multipolygon._layers);
for (i = 0; i < keys.length; i++) {
res = this._snapToPolygon(latlng, multipolygon._layers[keys[i]], map, sensitivity, vertexonly, minDist);
if (res.minDist < minDist) {
minDist = res.minDist;
minPoint = res.minPoint;
}
}
return {'minDist': minDist, 'minPoint': minPoint};
},
/**
* Snap to <Array> of <Latlang>
*
* @param <LatLng> latlng - cursor click
* @param <Array> latlngs - array of <L.LatLngs> to snap to
* @param <Object> opts - snapping options
* @param <Boolean> isPolygon - if feature is a polygon
*
* @return <Object> minDist and minPoint
*/
_snapToLatlngs: function (latlng, latlngs, map, sensitivity, vertexonly, minDist) {
var i, tmpDist, minPoint, p, p1, p2, d2;
p = map.latLngToLayerPoint(latlng);
p1 = minPoint = null;
for (i = 0; i < latlngs.length; i++) {
p2 = map.latLngToLayerPoint(latlngs[i]);
if (!vertexonly && p1 !== null) {
tmpDist = L.LineUtil.pointToSegmentDistance(p, p1, p2);
if (tmpDist < minDist && tmpDist <= sensitivity) {
minDist = tmpDist;
minPoint = map.layerPointToLatLng(L.LineUtil.closestPointOnSegment(p, p1, p2));
}
} else if ((d2 = p.distanceTo(p2)) && d2 <= sensitivity && d2 < minDist) {
minDist = d2;
minPoint = latlngs[i];
}
p1 = p2;
}
return {'minDist': minDist, 'minPoint': minPoint};
}
});

View file

@ -0,0 +1,12 @@
L.Marker.include({
/**
* Snap to function
*
* @param <LatLng> latlng - original position
*
* @return <LatLng> - new position
*/
snapTo: function (latlng) {
return L.LineUtil.snapToLayers(latlng, this._leaflet_id, this.options.snapping);
}
});

View file

@ -0,0 +1,12 @@
L.Polyline.include({
/**
* Snap to function
*
* @param <LatLng> latlng - original position
*
* @return <LatLng> - new position
*/
snapTo: function (latlng) {
return L.LineUtil.snapToLayers(latlng, this._leaflet_id, this.options.snapping);
}
});