esri-leaflet
Version:
Leaflet plugins for consuming ArcGIS Online and ArcGIS Server services.
226 lines (193 loc) • 7.98 kB
JavaScript
import { point, latLng } from 'leaflet';
import { Task } from './Task';
import {
warn,
responseToFeatureCollection,
isArcgisOnline,
extentToBounds,
_setGeometry
} from '../Util';
export var Query = Task.extend({
setters: {
offset: 'resultOffset',
limit: 'resultRecordCount',
fields: 'outFields',
precision: 'geometryPrecision',
featureIds: 'objectIds',
returnGeometry: 'returnGeometry',
returnM: 'returnM',
transform: 'datumTransformation',
token: 'token'
},
path: 'query',
params: {
returnGeometry: true,
where: '1=1',
outSR: 4326,
outFields: '*'
},
// Returns a feature if its shape is wholly contained within the search geometry. Valid for all shape type combinations.
within: function (geometry) {
this._setGeometryParams(geometry);
this.params.spatialRel = 'esriSpatialRelContains'; // to the REST api this reads geometry **contains** layer
return this;
},
// Returns a feature if any spatial relationship is found. Applies to all shape type combinations.
intersects: function (geometry) {
this._setGeometryParams(geometry);
this.params.spatialRel = 'esriSpatialRelIntersects';
return this;
},
// Returns a feature if its shape wholly contains the search geometry. Valid for all shape type combinations.
contains: function (geometry) {
this._setGeometryParams(geometry);
this.params.spatialRel = 'esriSpatialRelWithin'; // to the REST api this reads geometry **within** layer
return this;
},
// Returns a feature if the intersection of the interiors of the two shapes is not empty and has a lower dimension than the maximum dimension of the two shapes. Two lines that share an endpoint in common do not cross. Valid for Line/Line, Line/Area, Multi-point/Area, and Multi-point/Line shape type combinations.
crosses: function (geometry) {
this._setGeometryParams(geometry);
this.params.spatialRel = 'esriSpatialRelCrosses';
return this;
},
// Returns a feature if the two shapes share a common boundary. However, the intersection of the interiors of the two shapes must be empty. In the Point/Line case, the point may touch an endpoint only of the line. Applies to all combinations except Point/Point.
touches: function (geometry) {
this._setGeometryParams(geometry);
this.params.spatialRel = 'esriSpatialRelTouches';
return this;
},
// Returns a feature if the intersection of the two shapes results in an object of the same dimension, but different from both of the shapes. Applies to Area/Area, Line/Line, and Multi-point/Multi-point shape type combinations.
overlaps: function (geometry) {
this._setGeometryParams(geometry);
this.params.spatialRel = 'esriSpatialRelOverlaps';
return this;
},
// Returns a feature if the envelope of the two shapes intersects.
bboxIntersects: function (geometry) {
this._setGeometryParams(geometry);
this.params.spatialRel = 'esriSpatialRelEnvelopeIntersects';
return this;
},
// if someone can help decipher the ArcObjects explanation and translate to plain speak, we should mention this method in the doc
indexIntersects: function (geometry) {
this._setGeometryParams(geometry);
this.params.spatialRel = 'esriSpatialRelIndexIntersects'; // Returns a feature if the envelope of the query geometry intersects the index entry for the target geometry
return this;
},
// only valid for Feature Services running on ArcGIS Server 10.3+ or ArcGIS Online
nearby: function (latlng, radius) {
latlng = latLng(latlng);
this.params.geometry = [latlng.lng, latlng.lat];
this.params.geometryType = 'esriGeometryPoint';
this.params.spatialRel = 'esriSpatialRelIntersects';
this.params.units = 'esriSRUnit_Meter';
this.params.distance = radius;
this.params.inSR = 4326;
return this;
},
where: function (string) {
// instead of converting double-quotes to single quotes, pass as is, and provide a more informative message if a 400 is encountered
this.params.where = string;
return this;
},
between: function (start, end) {
this.params.time = [start.valueOf(), end.valueOf()];
return this;
},
simplify: function (map, factor) {
var mapWidth = Math.abs(map.getBounds().getWest() - map.getBounds().getEast());
this.params.maxAllowableOffset = (mapWidth / map.getSize().y) * factor;
return this;
},
orderBy: function (fieldName, order) {
order = order || 'ASC';
this.params.orderByFields = (this.params.orderByFields) ? this.params.orderByFields + ',' : '';
this.params.orderByFields += ([fieldName, order]).join(' ');
return this;
},
run: function (callback, context) {
this._cleanParams();
// services hosted on ArcGIS Online and ArcGIS Server 10.3.1+ support requesting geojson directly
if (this.options.isModern || (isArcgisOnline(this.options.url) && this.options.isModern === undefined)) {
this.params.f = 'geojson';
return this.request(function (error, response) {
this._trapSQLerrors(error);
callback.call(context, error, response, response);
}, this);
// otherwise convert it in the callback then pass it on
} else {
return this.request(function (error, response) {
this._trapSQLerrors(error);
callback.call(context, error, (response && responseToFeatureCollection(response)), response);
}, this);
}
},
count: function (callback, context) {
this._cleanParams();
this.params.returnCountOnly = true;
return this.request(function (error, response) {
callback.call(this, error, (response && response.count), response);
}, context);
},
ids: function (callback, context) {
this._cleanParams();
this.params.returnIdsOnly = true;
return this.request(function (error, response) {
callback.call(this, error, (response && response.objectIds), response);
}, context);
},
// only valid for Feature Services running on ArcGIS Server 10.3+ or ArcGIS Online
bounds: function (callback, context) {
this._cleanParams();
this.params.returnExtentOnly = true;
return this.request(function (error, response) {
if (response && response.extent && extentToBounds(response.extent)) {
callback.call(context, error, extentToBounds(response.extent), response);
} else {
error = {
message: 'Invalid Bounds'
};
callback.call(context, error, null, response);
}
}, context);
},
distinct: function () {
// geometry must be omitted for queries requesting distinct values
this.params.returnGeometry = false;
this.params.returnDistinctValues = true;
return this;
},
// only valid for image services
pixelSize: function (rawPoint) {
var castPoint = point(rawPoint);
this.params.pixelSize = [castPoint.x, castPoint.y];
return this;
},
// only valid for map services
layer: function (layer) {
this.path = layer + '/query';
return this;
},
_trapSQLerrors: function (error) {
if (error) {
if (error.code === '400') {
warn('one common syntax error in query requests is encasing string values in double quotes instead of single quotes');
}
}
},
_cleanParams: function () {
delete this.params.returnIdsOnly;
delete this.params.returnExtentOnly;
delete this.params.returnCountOnly;
},
_setGeometryParams: function (geometry) {
this.params.inSR = 4326;
var converted = _setGeometry(geometry);
this.params.geometry = converted.geometry;
this.params.geometryType = converted.geometryType;
}
});
export function query (options) {
return new Query(options);
}
export default query;