thanthamky's picture
Upload 116 files
f655b1d verified
L.Edit = L.Edit || {};
/**
* @class L.Edit.Polyline
* @aka L.Edit.Poly
* @aka Edit.Poly
*/
L.Edit.Poly = L.Handler.extend({
options: {},
// @method initialize(): void
initialize: function (poly, options) {
this.latlngs = [poly._latlngs];
if (poly._holes) {
this.latlngs = this.latlngs.concat(poly._holes);
}
this._poly = poly;
L.setOptions(this, options);
this._poly.on('revert-edited', this._updateLatLngs, this);
},
// Compatibility method to normalize Poly* objects
// between 0.7.x and 1.0+
_defaultShape: function () {
if (!L.Polyline._flat) {
return this._poly._latlngs;
}
return L.Polyline._flat(this._poly._latlngs) ? this._poly._latlngs : this._poly._latlngs[0];
},
_eachVertexHandler: function (callback) {
for (var i = 0; i < this._verticesHandlers.length; i++) {
callback(this._verticesHandlers[i]);
}
},
// @method addHooks(): void
// Add listener hooks to this handler
addHooks: function () {
this._initHandlers();
this._eachVertexHandler(function (handler) {
handler.addHooks();
});
},
// @method removeHooks(): void
// Remove listener hooks from this handler
removeHooks: function () {
this._eachVertexHandler(function (handler) {
handler.removeHooks();
});
},
// @method updateMarkers(): void
// Fire an update for each vertex handler
updateMarkers: function () {
this._eachVertexHandler(function (handler) {
handler.updateMarkers();
});
},
_initHandlers: function () {
this._verticesHandlers = [];
for (var i = 0; i < this.latlngs.length; i++) {
this._verticesHandlers.push(new L.Edit.PolyVerticesEdit(this._poly, this.latlngs[i], this.options));
}
},
_updateLatLngs: function (e) {
this.latlngs = [e.layer._latlngs];
if (e.layer._holes) {
this.latlngs = this.latlngs.concat(e.layer._holes);
}
}
});
/**
* @class L.Edit.PolyVerticesEdit
* @aka Edit.PolyVerticesEdit
*/
L.Edit.PolyVerticesEdit = L.Handler.extend({
options: {
icon: new L.DivIcon({
iconSize: new L.Point(8, 8),
className: 'leaflet-div-icon leaflet-editing-icon'
}),
touchIcon: new L.DivIcon({
iconSize: new L.Point(20, 20),
className: 'leaflet-div-icon leaflet-editing-icon leaflet-touch-icon'
}),
drawError: {
color: '#b00b00',
timeout: 1000
}
},
// @method intialize(): void
initialize: function (poly, latlngs, options) {
// if touch, switch to touch icon
if (L.Browser.touch) {
this.options.icon = this.options.touchIcon;
}
this._poly = poly;
if (options && options.drawError) {
options.drawError = L.Util.extend({}, this.options.drawError, options.drawError);
}
this._latlngs = latlngs;
L.setOptions(this, options);
},
// Compatibility method to normalize Poly* objects
// between 0.7.x and 1.0+
_defaultShape: function () {
if (!L.Polyline._flat) {
return this._latlngs;
}
return L.Polyline._flat(this._latlngs) ? this._latlngs : this._latlngs[0];
},
// @method addHooks(): void
// Add listener hooks to this handler.
addHooks: function () {
var poly = this._poly;
if (!(poly instanceof L.Polygon)) {
poly.options.fill = false;
if (poly.options.editing) {
poly.options.editing.fill = false;
}
}
poly.setStyle(poly.options.editing);
if (this._poly._map) {
this._map = this._poly._map; // Set map
if (!this._markerGroup) {
this._initMarkers();
}
this._poly._map.addLayer(this._markerGroup);
}
},
// @method removeHooks(): void
// Remove listener hooks from this handler.
removeHooks: function () {
var poly = this._poly;
poly.setStyle(poly.options.original);
if (poly._map) {
poly._map.removeLayer(this._markerGroup);
delete this._markerGroup;
delete this._markers;
}
},
// @method updateMarkers(): void
// Clear markers and update their location
updateMarkers: function () {
this._markerGroup.clearLayers();
this._initMarkers();
},
_initMarkers: function () {
if (!this._markerGroup) {
this._markerGroup = new L.LayerGroup();
}
this._markers = [];
var latlngs = this._defaultShape(),
i, j, len, marker;
for (i = 0, len = latlngs.length; i < len; i++) {
marker = this._createMarker(latlngs[i], i);
marker.on('click', this._onMarkerClick, this);
this._markers.push(marker);
}
var markerLeft, markerRight;
for (i = 0, j = len - 1; i < len; j = i++) {
if (i === 0 && !(L.Polygon && (this._poly instanceof L.Polygon))) {
continue;
}
markerLeft = this._markers[j];
markerRight = this._markers[i];
this._createMiddleMarker(markerLeft, markerRight);
this._updatePrevNext(markerLeft, markerRight);
}
},
_createMarker: function (latlng, index) {
// Extending L.Marker in TouchEvents.js to include touch.
var marker = new L.Marker.Touch(latlng, {
draggable: true,
icon: this.options.icon,
});
marker._origLatLng = latlng;
marker._index = index;
marker
.on('dragstart', this._onMarkerDragStart, this)
.on('drag', this._onMarkerDrag, this)
.on('dragend', this._fireEdit, this)
.on('touchmove', this._onTouchMove, this)
.on('touchend', this._fireEdit, this)
.on('MSPointerMove', this._onTouchMove, this)
.on('MSPointerUp', this._fireEdit, this);
this._markerGroup.addLayer(marker);
return marker;
},
_onMarkerDragStart: function () {
this._poly.fire('editstart');
},
_spliceLatLngs: function () {
var latlngs = this._defaultShape();
var removed = [].splice.apply(latlngs, arguments);
this._poly._convertLatLngs(latlngs, true);
this._poly.redraw();
return removed;
},
_removeMarker: function (marker) {
var i = marker._index;
this._markerGroup.removeLayer(marker);
this._markers.splice(i, 1);
this._spliceLatLngs(i, 1);
this._updateIndexes(i, -1);
marker
.off('dragstart', this._onMarkerDragStart, this)
.off('drag', this._onMarkerDrag, this)
.off('dragend', this._fireEdit, this)
.off('touchmove', this._onMarkerDrag, this)
.off('touchend', this._fireEdit, this)
.off('click', this._onMarkerClick, this)
.off('MSPointerMove', this._onTouchMove, this)
.off('MSPointerUp', this._fireEdit, this);
},
_fireEdit: function () {
this._poly.edited = true;
this._poly.fire('edit');
this._poly._map.fire(L.Draw.Event.EDITVERTEX, { layers: this._markerGroup, poly: this._poly });
},
_onMarkerDrag: function (e) {
var marker = e.target;
var poly = this._poly;
L.extend(marker._origLatLng, marker._latlng);
if (marker._middleLeft) {
marker._middleLeft.setLatLng(this._getMiddleLatLng(marker._prev, marker));
}
if (marker._middleRight) {
marker._middleRight.setLatLng(this._getMiddleLatLng(marker, marker._next));
}
if (poly.options.poly) {
var tooltip = poly._map._editTooltip; // Access the tooltip
// If we don't allow intersections and the polygon intersects
if (!poly.options.poly.allowIntersection && poly.intersects()) {
var originalColor = poly.options.color;
poly.setStyle({ color: this.options.drawError.color });
// Manually trigger 'dragend' behavior on marker we are about to remove
// WORKAROUND: introduced in 1.0.0-rc2, may be related to #4484
if (L.version.indexOf('0.7') !== 0) {
marker.dragging._draggable._onUp(e);
}
this._onMarkerClick(e); // Remove violating marker
// FIXME: Reset the marker to it's original position (instead of remove)
if (tooltip) {
tooltip.updateContent({
text: L.drawLocal.draw.handlers.polyline.error
});
}
// Reset everything back to normal after a second
setTimeout(function () {
poly.setStyle({ color: originalColor });
if (tooltip) {
tooltip.updateContent({
text: L.drawLocal.edit.handlers.edit.tooltip.text,
subtext: L.drawLocal.edit.handlers.edit.tooltip.subtext
});
}
}, 1000);
}
}
this._poly.redraw();
this._poly.fire('editdrag');
},
_onMarkerClick: function (e) {
var minPoints = L.Polygon && (this._poly instanceof L.Polygon) ? 4 : 3,
marker = e.target;
// If removing this point would create an invalid polyline/polygon don't remove
if (this._defaultShape().length < minPoints) {
return;
}
// remove the marker
this._removeMarker(marker);
// update prev/next links of adjacent markers
this._updatePrevNext(marker._prev, marker._next);
// remove ghost markers near the removed marker
if (marker._middleLeft) {
this._markerGroup.removeLayer(marker._middleLeft);
}
if (marker._middleRight) {
this._markerGroup.removeLayer(marker._middleRight);
}
// create a ghost marker in place of the removed one
if (marker._prev && marker._next) {
this._createMiddleMarker(marker._prev, marker._next);
} else if (!marker._prev) {
marker._next._middleLeft = null;
} else if (!marker._next) {
marker._prev._middleRight = null;
}
this._fireEdit();
},
_onTouchMove: function (e) {
var layerPoint = this._map.mouseEventToLayerPoint(e.originalEvent.touches[0]),
latlng = this._map.layerPointToLatLng(layerPoint),
marker = e.target;
L.extend(marker._origLatLng, latlng);
if (marker._middleLeft) {
marker._middleLeft.setLatLng(this._getMiddleLatLng(marker._prev, marker));
}
if (marker._middleRight) {
marker._middleRight.setLatLng(this._getMiddleLatLng(marker, marker._next));
}
this._poly.redraw();
this.updateMarkers();
},
_updateIndexes: function (index, delta) {
this._markerGroup.eachLayer(function (marker) {
if (marker._index > index) {
marker._index += delta;
}
});
},
_createMiddleMarker: function (marker1, marker2) {
var latlng = this._getMiddleLatLng(marker1, marker2),
marker = this._createMarker(latlng),
onClick,
onDragStart,
onDragEnd;
marker.setOpacity(0.6);
marker1._middleRight = marker2._middleLeft = marker;
onDragStart = function () {
marker.off('touchmove', onDragStart, this);
var i = marker2._index;
marker._index = i;
marker
.off('click', onClick, this)
.on('click', this._onMarkerClick, this);
latlng.lat = marker.getLatLng().lat;
latlng.lng = marker.getLatLng().lng;
this._spliceLatLngs(i, 0, latlng);
this._markers.splice(i, 0, marker);
marker.setOpacity(1);
this._updateIndexes(i, 1);
marker2._index++;
this._updatePrevNext(marker1, marker);
this._updatePrevNext(marker, marker2);
this._poly.fire('editstart');
};
onDragEnd = function () {
marker.off('dragstart', onDragStart, this);
marker.off('dragend', onDragEnd, this);
marker.off('touchmove', onDragStart, this);
this._createMiddleMarker(marker1, marker);
this._createMiddleMarker(marker, marker2);
};
onClick = function () {
onDragStart.call(this);
onDragEnd.call(this);
this._fireEdit();
};
marker
.on('click', onClick, this)
.on('dragstart', onDragStart, this)
.on('dragend', onDragEnd, this)
.on('touchmove', onDragStart, this);
this._markerGroup.addLayer(marker);
},
_updatePrevNext: function (marker1, marker2) {
if (marker1) {
marker1._next = marker2;
}
if (marker2) {
marker2._prev = marker1;
}
},
_getMiddleLatLng: function (marker1, marker2) {
var map = this._poly._map,
p1 = map.project(marker1.getLatLng()),
p2 = map.project(marker2.getLatLng());
return map.unproject(p1._add(p2)._divideBy(2));
}
});
L.Polyline.addInitHook(function () {
// Check to see if handler has already been initialized. This is to support versions of Leaflet that still have L.Handler.PolyEdit
if (this.editing) {
return;
}
if (L.Edit.Poly) {
this.editing = new L.Edit.Poly(this, this.options.poly);
if (this.options.editable) {
this.editing.enable();
}
}
this.on('add', function () {
if (this.editing && this.editing.enabled()) {
this.editing.addHooks();
}
});
this.on('remove', function () {
if (this.editing && this.editing.enabled()) {
this.editing.removeHooks();
}
});
});