/*! leaflet-wfst 2.0.1-beta.20 2018-03-15 */
(function(window, document, undefined) {
"use strict";
L.XmlUtil = {
namespaces: {
xlink: 'http://www.w3.org/1999/xlink',
xmlns: 'http://www.w3.org/2000/xmlns/',
xsd: 'http://www.w3.org/2001/XMLSchema',
xsi: 'http://www.w3.org/2001/XMLSchema-instance',
wfs: 'http://www.opengis.net/wfs',
gml: 'http://www.opengis.net/gml',
ogc: 'http://www.opengis.net/ogc',
ows: 'http://www.opengis.net/ows'
},
// TODO: find another way to create a new document with doctype text/xml?
xmldoc: (new DOMParser()).parseFromString('', 'text/xml'),
setAttributes: function (node, attributes) {
for (var name in attributes) {
if (attributes[name] != null && attributes[name].toString) {
var value = attributes[name].toString();
var uri = this.namespaces[name.substring(0, name.indexOf(':'))] || null;
node.setAttributeNS(uri, name, value);
}
}
},
evaluate: function (xpath, xml) {
var xmlDoc = xml;
if (!(xmlDoc instanceof Document)) {
xmlDoc = this.parseXml(xml);
}
var xpe = new XPathEvaluator();
var nsResolver = xpe.createNSResolver(xmlDoc.documentElement);
return xpe.evaluate(xpath, xmlDoc, nsResolver, XPathResult.ANY_TYPE, null);
},
createElementNS: function (name, attributes, options) {
options = options || {};
var uri = options.uri;
if (!uri) {
uri = this.namespaces[name.substring(0, name.indexOf(':'))];
}
if (!uri) {
uri = this.namespaces[options.prefix];
}
var node = uri ? this.xmldoc.createElementNS(uri, name) : this.xmldoc.createElement(name);
if (attributes) {
this.setAttributes(node, attributes);
}
if (options.value != null) {
node.appendChild(this.xmldoc.createTextNode(options.value));
}
return node;
},
createTextNode: function (value) {
if(value === null || value === undefined) {
value = '';
} else if(value instanceof Date) {
value = value.toISOString();
}
return this.xmldoc.createTextNode(value);
},
getNodeText: function (node) {
if (!node) {
return '';
}
return node.innerText || node.textContent || node.text;
},
serializeXmlDocumentString: function (node) {
var doc = document.implementation.createDocument('', '', null);
doc.appendChild(node);
var serializer = new XMLSerializer();
return serializer.serializeToString(doc);
},
serializeXmlToString: function (node) {
var serializer = new XMLSerializer();
return serializer.serializeToString(node);
},
parseXml: function (rawXml) {
if (typeof window.DOMParser !== 'undefined') {
return (new window.DOMParser()).parseFromString(rawXml, 'text/xml');
} else if (typeof window.ActiveXObject !== 'undefined' && new window.ActiveXObject('Microsoft.XMLDOM')) {
var xmlDoc = new window.ActiveXObject('Microsoft.XMLDOM');
xmlDoc.async = 'false';
xmlDoc.loadXML(rawXml);
return xmlDoc;
} else {
throw new Error('No XML parser found');
}
},
parseOwsExceptionReport: function (xml) {
var xmlDoc = xml;
if (!(xmlDoc instanceof Document)) {
xmlDoc = this.parseXml(xml);
}
var exceptionReportElement = xmlDoc.documentElement;
if (!exceptionReportElement || exceptionReportElement.tagName !== 'ows:ExceptionReport') {
return null;
}
var exceptionReport = {
exceptions: [],
message: ''
};
var exceptionsNodes = exceptionReportElement.getElementsByTagNameNS(L.XmlUtil.namespaces.ows, 'Exception');
for (var i = 0, exceptionsNodesCount = exceptionsNodes.length; i < exceptionsNodesCount; i++) {
var exceptionNode = exceptionsNodes[i];
var exceptionCode = exceptionNode.getAttribute('exceptionCode');
var exceptionsTextNodes = exceptionNode.getElementsByTagNameNS(L.XmlUtil.namespaces.ows, 'ExceptionText');
var exception = {
code: exceptionCode,
text: ''
};
for (var j = 0, textNodesCount = exceptionsTextNodes.length; j < textNodesCount; j++) {
var exceptionTextNode = exceptionsTextNodes[j];
var exceptionText = exceptionTextNode.innerText || exceptionTextNode.textContent || exceptionTextNode.text;
exception.text += exceptionText;
if (j < textNodesCount - 1) {
exception.text += '. ';
}
}
exceptionReport.message += exception.code + ' - ' + exception.text;
if (i < exceptionsNodesCount - 1) {
exceptionReport.message += ' ';
}
exceptionReport.exceptions.push(exception);
}
return exceptionReport;
}
};
L.Util.request = function (options) {
options = L.extend({
async: true,
method: 'POST',
data: '',
params: {},
headers: {},
url: window.location.href,
withCredentials: false,
success: function (data) {
console.log(data);
},
error: function (data) {
console.log('Ajax request fail');
console.log(data);
},
complete: function () {
}
}, options);
// good bye IE 6,7
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
options.success(xhr.responseText);
} else {
options.error(xhr.responseText);
}
options.complete();
}
};
xhr.withCredentials = options.withCredentials;
var url = options.url + L.Util.getParamString(options.params, options.url);
xhr.open(options.method, url, options.async);
for (var header in options.headers) {
xhr.setRequestHeader(header, options.headers[header]);
}
xhr.send(options.data);
};
L.Filter = {};
L.filter = function (filters) {
var result = L.XmlUtil.createElementNS('ogc:Filter');
if (Array.isArray(filters)) {
filters.forEach(function (element) {
result.appendChild(element instanceof Element ? element : element.toGml());
});
} else if (filters) {
result.appendChild(filters instanceof Element ? filters : filters.toGml());
}
return result;
};
L.Filter.propertyName = function (value) {
return L.XmlUtil.createElementNS('ogc:PropertyName', {}, { value: value });
};
L.Filter.literal = function (value) {
return L.XmlUtil.createElementNS('ogc:Literal', {}, { value: value });
};
L.Filter.element = function(value) {
if(value instanceof Element) {
return value;
}
return value.toGml();
};
L.Filter.propertyElement = function (value) {
if (value instanceof Element) {
return value;
}
if (value && typeof (value.toGml) === "function") {
return value.toGml();
}
return L.Filter.propertyName(value);
};
L.Filter.literalElement = function (value) {
if (value instanceof Element) {
return value;
}
if (value && typeof (value.toGml) === "function") {
return value.toGml();
}
return L.Filter.literal(value);
};
L.Filter.Abstract = L.Class.extend({
attributes: {},
options: {},
tagName: null,
buildFilterContent: function() {
throw "Build filter content is abstract and should be implemented";
},
toGml: function() {
var filterElement = L.XmlUtil.createElementNS(this.tagName, this.attributes, this.options);
this.buildFilterContent(filterElement);
return filterElement;
}
});
L.Filter.BinarySpatial = L.Filter.Abstract.extend({
initialize: function (propertyName, value, crs) {
this.propertyName = propertyName;
this.value = value;
this.crs = crs;
},
buildFilterContent: function (filterElement) {
filterElement.appendChild(L.Filter.propertyName(this.propertyName));
if (typeof(this.value) === "string") {
filterElement.appendChild(L.Filter.propertyName(this.value));
} else {
filterElement.appendChild(this.value.toGml(this.crs));
}
return filterElement;
}
});
L.Filter.Equals = L.Filter.BinarySpatial.extend({
tagName: 'ogc:Equals'
});
L.Filter.equals = function(options) {
return new L.Filter.Equals(options);
};
L.Filter.Disjoint = L.Filter.BinarySpatial.extend({
tagName: 'ogc:Disjoint'
});
L.Filter.disjoint = function(options) {
return new L.Filter.Disjoint(options);
};
L.Filter.Touches = L.Filter.BinarySpatial.extend({
tagName: 'ogc:Touches'
});
L.Filter.touches = function(options) {
return new L.Filter.Touches(options);
};
L.Filter.Within = L.Filter.BinarySpatial.extend({
tagName: 'ogc:Within'
});
L.Filter.within = function(options) {
return new L.Filter.Within(options);
};
L.Filter.Overlaps = L.Filter.BinarySpatial.extend({
tagName: 'ogc:Overlaps'
});
L.Filter.overlaps = function(options) {
return new L.Filter.Overlaps(options);
};
L.Filter.Crosses = L.Filter.BinarySpatial.extend({
tagName: 'ogc:Crosses'
});
L.Filter.crosses = function(options) {
return new L.Filter.Crosses(options);
};
L.Filter.Intersects = L.Filter.BinarySpatial.extend({
tagName: 'ogc:Intersects'
});
L.Filter.intersects = function(options) {
return new L.Filter.Intersects(options);
};
L.Filter.Contains = L.Filter.BinarySpatial.extend({
tagName: 'ogc:Contains'
});
L.Filter.contains = function(options) {
return new L.Filter.Contains(options);
};
L.Filter.DistanceBuffer = L.Filter.Abstract.extend({
initialize: function (propertyName, geometry, crs, distance, units) {
this.propertyName = propertyName;
this.geomerty = geometry;
this.crs = crs;
this.distance = distance;
this.units = units;
},
buildFilterContent: function (filterElement) {
filterElement.appendChild(L.Filter.propertyName(this.propertyName));
filterElement.appendChild(this.geomerty.toGml(this.crs));
filterElement.appendChild(L.XmlUtil.createElementNS('ogc:Distance', { 'units': this.units }, { value: this.distance }));
}
});
L.Filter.DWithin = L.Filter.DistanceBuffer.extend({
tagName: 'ogc:DWithin'
});
L.Filter.dwithin = function(propertyName, geometry, crs, distance, units) {
return new L.Filter.DWithin(propertyName, geometry, crs, distance, units);
};
L.Filter.Beyond = L.Filter.DistanceBuffer.extend({
tagName: 'ogc:Beyond'
});
L.Filter.beyond = function(propertyName, geometry, crs, distance, units) {
return new L.Filter.Beyond(propertyName, geometry, crs, distance, units);
};
L.Filter.BBox = L.Filter.Abstract.extend({
tagName: 'ogc:BBOX',
geometryField: null,
bbox: null,
crs: null,
initialize: function (geometryField, bbox, crs) {
this.bbox = bbox;
this.geometryField = geometryField;
this.crs = crs;
},
buildFilterContent: function (filterElement) {
if (this.geometryField) {
filterElement.appendChild(L.Filter.propertyName(this.geometryField));
}
filterElement.appendChild(this.bbox.toGml(this.crs));
}
});
L.Filter.bbox = function (geometryField, bbox, crs) {
return new L.Filter.BBox(geometryField, bbox, crs);
};
L.Filter.GmlObjectID = L.Filter.Abstract.extend({
tagName: 'ogc:GmlObjectId',
initialize: function (id) {
this.attributes = { 'gml:id': id };
},
buildFilterContent: function() {
}
});
L.Filter.gmlobjectid = function(id) {
return new L.Filter.GmlObjectID(id);
};
L.Filter.BinaryOperator = L.Filter.Abstract.extend({
initialize: function (firstValue, secondValue) {
this.firstValue = firstValue;
this.secondValue = secondValue;
},
buildFilterContent: function (filterElement) {
filterElement.appendChild(L.Filter.propertyElement(this.firstValue));
filterElement.appendChild(L.Filter.literalElement(this.secondValue));
}
});
L.Filter.Add = L.Filter.BinaryOperator.extend({
tagName: 'Add'
});
L.Filter.add = function(a, b) {
return new L.Filter.Add(a, b);
};
L.Filter.Sub = L.Filter.BinaryOperator.extend({
tagName: 'Sub'
});
L.Filter.sub = function(a, b) {
return new L.Filter.Sub(a, b);
};
L.Filter.Mul = L.Filter.BinaryOperator.extend({
tagName: 'Mul'
});
L.Filter.mul = function(a, b) {
return new L.Filter.Mul(a, b);
};
L.Filter.Div = L.Filter.BinaryOperator.extend({
tagName: 'Div'
});
L.Filter.div = function(a, b) {
return new L.Filter.Div(a, b);
};
L.Filter.BinaryComparison = L.Filter.BinaryOperator.extend({
matchCase: false,
initialize: function(firstValue, secondValue, matchCase) {
L.Filter.BinaryOperator.prototype.initialize.call(this, firstValue, secondValue);
this.attributes = { matchCase: !!matchCase };
}
});
L.Filter.EQ = L.Filter.BinaryComparison.extend({
tagName: 'ogc:PropertyIsEqualTo'
});
L.Filter.eq = function(firstValue, secondValue) {
return new L.Filter.EQ(firstValue, secondValue);
};
L.Filter.NotEQ = L.Filter.BinaryComparison.extend({
tagName: 'ogc:PropertyIsNotEqualTo'
});
L.Filter.neq = function(firstValue, secondValue) {
return new L.Filter.NotEQ(firstValue, secondValue);
};
L.Filter.LT = L.Filter.BinaryComparison.extend({
tagName: 'ogc:PropertyIsLessThan'
});
L.Filter.lt = function(firstValue, secondValue) {
return new L.Filter.LT(firstValue, secondValue);
};
L.Filter.GT = L.Filter.BinaryComparison.extend({
tagName: 'ogc:PropertyIsGreaterThan'
});
L.Filter.gt = function(firstValue, secondValue) {
return new L.Filter.GT(firstValue, secondValue);
};
L.Filter.LEQ = L.Filter.BinaryComparison.extend({
tagName: 'ogc:PropertyIsLessThanOrEqualTo'
});
L.Filter.leq = function(firstValue, secondValue) {
return new L.Filter.LEQ(firstValue, secondValue);
};
L.Filter.GEQ = L.Filter.BinaryComparison.extend({
tagName: 'ogc:PropertyIsGreaterThanOrEqualTo'
});
L.Filter.geq = function(firstValue, secondValue) {
return new L.Filter.GEQ(firstValue, secondValue);
};
L.Filter.Like = L.Filter.Abstract.extend({
tagName: 'ogc:PropertyIsLike',
wildCard: '*',
singleChar: '#',
escapeChar: '!',
matchCase: true,
initialize: function (name, val, attributes) {
this.name = name;
this.val = val;
var defaultAttributes = { wildCard: this.wildCard, singleChar: this.singleChar, escapeChar: this.escapeChar, matchCase: this.matchCase };
this.attributes = L.extend(defaultAttributes, attributes || {});
},
buildFilterContent: function (filterElement) {
var nameElement = L.Filter.propertyName(this.name);
var valueElement = L.Filter.literal(this.val);
filterElement.appendChild(nameElement);
filterElement.appendChild(valueElement);
return filterElement;
}
});
L.Filter.like = function(name, val, attributes) {
return new L.Filter.Like(name, val, attributes);
};
L.Filter.IsNull = L.Filter.Abstract.extend({
tagName: 'ogc:PropertyIsNull',
initialize: function (propertyName) {
this.propertyName = propertyName;
},
buildFilterContent: function (filterElement) {
filterElement.appendChild(L.Filter.propertyName(this.propertyName));
}
});
L.Filter.isnull = function(propertyName) {
return new L.Filter.IsNull(propertyName);
};
L.Filter.IsBetween = L.Filter.Abstract.extend({
tagName: 'ogc:PropertyIsBetween',
initialize: function (property, lowerBoundary, upperBoundary) {
this.property = property;
this.lowerBoundary = lowerBoundary;
this.upperBoundary = upperBoundary;
},
buildFilterContent: function (filterElement) {
filterElement.appendChild(L.Filter.propertyElement(this.property));
var lowerBoundaryElement = L.XmlUtil.createElementNS('ogc:LowerBoundary');
lowerBoundaryElement.appendChild(L.Filter.literalElement(this.lowerBoundary));
filterElement.appendChild(lowerBoundaryElement);
var upperBoundaryElement = L.XmlUtil.createElementNS('ogc:UpperBoundary');
upperBoundaryElement.appendChild(L.Filter.literalElement(this.upperBoundary));
filterElement.appendChild(upperBoundaryElement);
}
});
L.Filter.isbetween = function(property, lowerBoundary, upperBoundary) {
return new L.Filter.IsBetween(property, lowerBoundary, upperBoundary);
};
L.Filter.BinaryLogic = L.Filter.Abstract.extend({
filters: null,
initialize: function () {
var filters = [];
for (var i = 0; i < arguments.length; i++) {
filters.push(arguments[i]);
}
this.filters = filters;
},
buildFilterContent: function (filterElement) {
this.filters.forEach(function(filter) {
filterElement.appendChild(L.Filter.element(filter));
});
}
});
L.Filter.And = L.Filter.BinaryLogic.extend({
tagName: 'And'
});
L.Filter.and = function() {
return new (Function.prototype.bind.apply(L.Filter.And, arguments))();
};
L.Filter.Or = L.Filter.BinaryLogic.extend({
tagName: 'Or'
});
L.Filter.or = function() {
return new (Function.prototype.bind.apply(L.Filter.Or, arguments))();
};
L.Filter.Not = L.Filter.Abstract.extend({
tagName: 'Not',
initialize: function(filter) {
this.filter = filter;
},
buildFilterContent: function(filterElement) {
filterElement.appendChild(L.Filter.element(this.filter));
}
});
L.Filter.not = function(filter) {
return new L.Filter.Not(filter);
};
L.Filter.Function = L.Filter.Abstract.extend({
tagName: 'Function',
initialize: function () {
var functionName = arguments[0];
this.attributes = { name: functionName };
var expressions = [];
for (var i = 1; i < arguments.length; i++) {
expressions.push(arguments[i]);
}
this.expressions = expressions;
},
buildFilterContent: function (filterElement) {
var firstArgument = this.expressions[0];
filterElement.appendChild(L.Filter.propertyElement(firstArgument));
for (var i = 1; i < this.expressions.length; i++) {
var functionArgument = this.expressions[i];
filterElement.appendChild(L.Filter.literalElement(functionArgument));
}
}
});
L.Filter.function = function() {
return new (Function.prototype.bind.apply(L.Filter.Function, arguments))();
};
L.Format = {};
L.Format.Scheme = L.Class.extend({
options: {
geometryField: 'Shape',
},
initialize: function (options) {
L.setOptions(this, options);
},
parse: function (element) {
var featureType = new L.GML.FeatureType({
geometryField: this.options.geometryField
});
var complexTypeDefinition = element.getElementsByTagNameNS(L.XmlUtil.namespaces.xsd, 'complexType')[0];
var properties = complexTypeDefinition.getElementsByTagNameNS(L.XmlUtil.namespaces.xsd, 'sequence')[0];
for (var i = 0; i < properties.childNodes.length; i++) {
var node = properties.childNodes[i];
if (node.nodeType !== document.ELEMENT_NODE) {
continue;
}
var propertyAttr = node.attributes.name;
if (!propertyAttr) {
continue;
}
var propertyName = node.attributes.name.value;
var typeAttr = node.attributes.type;
if (!typeAttr) {
var restriction = node.getElementsByTagNameNS(L.XmlUtil.namespaces.xsd, 'restriction');
typeAttr = restriction.attributes.base;
}
if (!typeAttr) {
continue;
}
var typeName = typeAttr.value.split(':').pop();
if (propertyName === this.options.geometryField) {
featureType.geometryFields[propertyName] = typeName;
continue;
}
featureType.appendField(propertyName, typeName);
}
return featureType;
}
});
L.Format.Base = L.Class.extend({
defaultOptions: {
crs: L.CRS.EPSG3857,
coordsToLatLng: function (coords) {
return new L.LatLng(coords[1], coords[0], coords[2]);
},
latLngToCoords: function (latlng) {
var coords = [latlng.lng, latlng.lat];
if (latlng.alt !== undefined) {
coords.push(latlng.alt);
}
return coords;
},
geometryField: 'Shape'
},
initialize: function (options) {
L.setOptions(this, L.extend({}, this.defaultOptions, options));
if (options.crs) {
var crs = options.crs;
this.options.coordsToLatLng = function (coords) {
var point = L.point(coords[0], coords[1]);
var ll = crs.projection.unproject(point);
if (coords[2]) {
ll.alt = coords[2];
}
return ll;
};
this.options.latLngToCoords = function (ll) {
var latLng = L.latLng(ll);
return crs.projection.project(latLng);
};
}
},
setFeatureDescription: function (featureInfo) {
this.namespaceUri = featureInfo.attributes.targetNamespace.value;
var schemeParser = new L.Format.Scheme({
geometryField: this.options.geometryField
});
this.featureType = schemeParser.parse(featureInfo);
}
});
L.Format.GeoJSON = L.Format.Base.extend({
initialize: function (options) {
L.Format.Base.prototype.initialize.call(this, options);
this.outputFormat = 'application/json';
},
responseToLayers: function (rawData) {
var layers = [];
var geoJson = JSON.parse(rawData);
for (var i = 0; i < geoJson.features.length; i++) {
var layer = this.processFeature(geoJson.features[i]);
if (layer) {
layers.push(layer);
}
}
return layers;
},
processFeature: function (feature) {
var layer = this.generateLayer(feature);
if (!layer) {
return null;
}
layer.feature = feature;
return layer;
},
generateLayer: function (feature) {
var layer = L.GeoJSON.geometryToLayer(feature, this.options || null);
if (!layer) {
console.log(
'Geometry field doesn\' exist inside received feature: \'' + feature + '\', ' +
'so feature will be skipped and won\'t be converted into leaflet layer');
return null;
}
return layer;
}
});
L.GML = L.GML || {};
L.GML.ParserContainerMixin = {
parsers: {},
initializeParserContainer: function () {
this.parsers = {};
},
appendParser: function (parser) {
this.parsers[parser.elementTag] = parser;
},
parseElement: function (element, options) {
var parser = this.parsers[element.tagName];
if (!parser) throw('unknown child element ' + element.tagName);
return parser.parse(element, options);
}
};
L.GML.Element = L.Class.extend({
elementTag: '',
parse: function () {
throw('not implemented parse function in parser for ' + this.elementTag);
}
});
L.GML.Geometry = L.GML.Element.extend({
statics: {
DIM: 2
},
dimensions: function (element) {
if (element.attributes.srsDimension) {
return parseInt(element.attributes.srsDimension.value);
}
return L.GML.Geometry.DIM;
}
});
L.GML.Coordinates = L.GML.Element.extend({
defaultSeparator: {
ds: '.', //decimal separator
cs: ',', // component separator
ts: ' ' // tuple separator
},
initialize: function () {
this.elementTag = 'gml:coordinates';
},
parse: function (element) {
var ds = this.defaultSeparator.ds;
if (element.attributes.decimal) {
ds = element.attributes.decimal.value;
}
var cs = this.defaultSeparator.cs;
if (element.attributes.cs) {
cs = element.attributes.cs.value;
}
var ts = this.defaultSeparator.ts;
if (element.attributes.ts) {
ts = element.attributes.ts.value;
}
var result = [];
var coords = element.textContent.split(ts);
var mapFunction = function (coord) {
if (ds !== '.') {
coord = coord.replace(ds, '.');
}
return parseFloat(coord);
};
for (var i = 0; i < coords.length; i++) {
result.push(coords[i].split(cs).map(mapFunction));
}
if (result.length === 1) {
return result[0];
}
return result;
}
});
L.GML.Pos = L.GML.Element.extend({
initialize: function () {
this.elementTag = 'gml:pos';
},
parse: function (element) {
return element.textContent.split(' ').map(function (coord) {
return parseFloat(coord);
});
}
});
L.GML.PosList = L.GML.Element.extend({
initialize: function () {
this.elementTag = 'gml:posList';
},
parse: function (element, options) {
var result = [];
var dim = options.dimensions;
var coords = element.textContent.split(' ');
for (var i = 0; i < coords.length; i += dim) {
var coord = [];
for (var j = i; j < i + dim; j++) {
coord.push(parseFloat(coords[j]));
}
result.push(coord);
}
return result;
}
});
L.GML.PointNode = L.GML.Geometry.extend({
includes: L.GML.ParserContainerMixin,
initialize: function () {
this.elementTag = 'gml:Point';
this.initializeParserContainer();
this.appendParser(new L.GML.Pos());
this.appendParser(new L.GML.Coordinates());
},
parse: function (element) {
return this.parseElement(element.firstChild, {dimensions: this.dimensions(element)});
}
});
L.GML.PointSequence = L.GML.Geometry.extend({
includes: L.GML.ParserContainerMixin,
initialize: function () {
this.initializeParserContainer();
this.appendParser(new L.GML.Pos());
this.appendParser(new L.GML.PosList());
this.appendParser(new L.GML.Coordinates());
this.appendParser(new L.GML.PointNode());
},
parse: function (element) {
var firstChild = element.firstChild;
var coords = [];
var tagName = firstChild.tagName;
if (tagName === 'gml:pos' || tagName === 'gml:Point') {
var childParser = this.parsers[tagName];
var elements = element.getElementsByTagNameNS(L.XmlUtil.namespaces.gml, tagName.split(':').pop());
for (var i = 0; i < elements.length; i++) {
coords.push(childParser.parse(elements[i]));
}
}
else {
coords = this.parseElement(firstChild, {dimensions: this.dimensions(element)});
}
return coords;
}
});
L.GML.LinearRing = L.GML.PointSequence.extend({
initialize: function () {
L.GML.PointSequence.prototype.initialize.call(this);
this.elementTag = 'gml:LinearRing';
},
parse: function (element) {
var coords = L.GML.PointSequence.prototype.parse.call(this, element);
//for leaflet polygons its not recommended insert additional last point equal to the first one
coords.pop();
return coords;
}
});
L.GML.LineStringNode = L.GML.PointSequence.extend({
initialize: function () {
this.elementTag = 'gml:LineString';
L.GML.PointSequence.prototype.initialize.call(this);
},
parse: function (element) {
return L.GML.PointSequence.prototype.parse.call(this, element);
}
});
L.GML.PolygonNode = L.GML.Geometry.extend({
initialize: function () {
this.elementTag = 'gml:Polygon';
this.linearRingParser = new L.GML.LinearRing();
},
parse: function (element) {
var coords = [];
for (var i = 0; i < element.childNodes.length; i++) {
//there can be exterior and interior, by GML standard and for leaflet its not significant
var child = element.childNodes[i];
if (child.nodeType === document.ELEMENT_NODE) {
coords.push(this.linearRingParser.parse(child.firstChild));
}
}
return coords;
}
});
L.GML.CoordsToLatLngMixin = {
transform: function (coordinates, options) {
if (Array.isArray(coordinates[0])) {
var latLngs = [];
for (var i = 0; i < coordinates.length; i++) {
latLngs.push(this.transform(coordinates[i], options));
}
return latLngs;
}
return options.coordsToLatLng(coordinates);
}
};
L.GML.Point = L.GML.PointNode.extend({
includes: L.GML.CoordsToLatLngMixin,
parse: function (element, options) {
var coords = L.GML.PointNode.prototype.parse.call(this, element);
var layer = new L.Marker();
layer.setLatLng(this.transform(coords, options));
return layer;
}
});
L.GML.LineString = L.GML.LineStringNode.extend({
includes: L.GML.CoordsToLatLngMixin,
parse: function (element, options) {
var layer = new L.Polyline([]);
var coordinates = L.GML.LineStringNode.prototype.parse.call(this, element);
layer.setLatLngs(this.transform(coordinates, options));
return layer;
}
});
L.GML.Polygon = L.GML.PolygonNode.extend({
includes: L.GML.CoordsToLatLngMixin,
parse: function (element, options) {
var layer = new L.Polygon([]);
var coordinates = L.GML.PolygonNode.prototype.parse.call(this, element);
layer.setLatLngs(this.transform(coordinates, options));
return layer;
}
});
L.GML.MultiGeometry = L.GML.Geometry.extend({
includes: [L.GML.ParserContainerMixin, L.GML.CoordsToLatLngMixin],
initialize: function () {
this.initializeParserContainer();
},
parse: function (element, options) {
var childObjects = [];
for (var i = 0; i < element.childNodes.length; i++) {
var geometryMember = element.childNodes[i];
if (geometryMember.nodeType !== document.ELEMENT_NODE) continue;
for (var j = 0; j < geometryMember.childNodes.length; j++) {
var singleGeometry = geometryMember.childNodes[j];
if (singleGeometry.nodeType !== document.ELEMENT_NODE) continue;
childObjects.push(this.parseElement(singleGeometry, options));
}
}
return this.transform(childObjects, options);
}
});
L.GML.AbstractMultiPolyline = L.GML.MultiGeometry.extend({
initialize: function () {
L.GML.MultiGeometry.prototype.initialize.call(this);
this.appendParser(new L.GML.LineStringNode());
},
parse: function (element, options) {
var latLngs = L.GML.MultiGeometry.prototype.parse.call(this, element, options);
var layer = new L.Polyline([]);
layer.setLatLngs(latLngs);
return layer;
}
});
L.GML.AbstractMultiPolygon = L.GML.MultiGeometry.extend({
initialize: function () {
L.GML.MultiGeometry.prototype.initialize.call(this);
this.appendParser(new L.GML.PolygonNode());
},
parse: function (element, options) {
var latLngs = L.GML.MultiGeometry.prototype.parse.call(this, element, options);
var layer = new L.Polygon([]);
layer.setLatLngs(latLngs);
return layer;
}
});
L.GML.MultiLineString = L.GML.AbstractMultiPolyline.extend({
initialize: function () {
L.GML.AbstractMultiPolyline.prototype.initialize.call(this);
this.elementTag = 'gml:MultiLineString';
}
});
L.GML.MultiCurve = L.GML.AbstractMultiPolyline.extend({
initialize: function () {
L.GML.AbstractMultiPolyline.prototype.initialize.call(this);
this.elementTag = 'gml:MultiCurve';
}
});
L.GML.MultiPolygon = L.GML.AbstractMultiPolygon.extend({
initialize: function () {
L.GML.AbstractMultiPolygon.prototype.initialize.call(this);
this.elementTag = 'gml:MultiPolygon';
}
});
L.GML.MultiSurface = L.GML.AbstractMultiPolygon.extend({
initialize: function () {
L.GML.AbstractMultiPolygon.prototype.initialize.call(this);
this.elementTag = 'gml:MultiSurface';
}
});
L.GML.MultiPoint = L.GML.MultiGeometry.extend({
initialize: function () {
L.GML.MultiGeometry.prototype.initialize.call(this);
this.elementTag = 'gml:MultiPoint';
this.appendParser(new L.GML.PointNode());
},
parse: function (element, options) {
var coordinates = L.GML.MultiGeometry.prototype.parse.call(this, element, options);
var multiPoint = new L.FeatureGroup();
for (var i = 0; i < coordinates.length; i++) {
var point = new L.Marker();
point.setLatLng(coordinates[i]);
multiPoint.addLayer(point);
}
return multiPoint;
}
});
L.GML.FeatureType = L.Class.extend({
options: {
geometryField: 'Shape',
},
primitives: [
{
types: ['byte', 'short', 'int', 'integer', 'long', 'float', 'double', 'decimal'],
parse: function (input) {
if (input === 0) {
return 0;
}
input = String.prototype.trim.call(input || '');
return input === '' ? null : Number(input);
},
validate: function (parsedValue) {
// Invalid number can be detected by isNaN check.
return !isNaN(parsedValue);
},
type: 'number'
},
{
types: ['string'],
parse: function (input) {
return input;
},
validate: function (parsedValue) {
// Any value is valid for 'string' type.
return true;
},
type: 'string'
},
{
types: ['boolean'],
parse: function (input) {
input = String.prototype.trim.call(input || '').toLowerCase();
return input !== 'false';
},
validate: function (parsedValue) {
// Any value is valid for 'boolean' type if parser parses it like so: input !== 'false'.
return true;
},
type: 'boolean'
},
{
types: ['date', 'time', 'datetime'],
parse: function (input) {
input = String.prototype.trim.call(input || '');
return input === '' ? null : new Date(input);
},
validate: function (parsedValue) {
// Invalid date also can be detected by isNaN check.
return !isNaN(parsedValue);
},
type: 'date'
}
],
initialize: function (options) {
L.setOptions(this, options);
this.fields = {};
this.fieldValidators = {};
this.fieldTypes = {};
this.geometryFields = {};
},
appendField: function (name, type) {
var that = this;
type = String.prototype.toLowerCase.call(type || '');
this.primitives.forEach(function (primitive) {
if (primitive.types.indexOf(type) !== -1) {
that.fields[name] = primitive.parse;
that.fieldValidators[name] = primitive.validate;
that.fieldTypes[name] = primitive.type;
}
});
},
parse: function (feature) {
var properties = {};
for (var i = 0; i < feature.childNodes.length; i++) {
var node = feature.childNodes[i];
if (node.nodeType !== document.ELEMENT_NODE) {
continue;
}
var propertyName = node.tagName.split(':').pop();
if (propertyName === this.options.geometryField) {
continue;
}
var parseField = this.fields[propertyName];
if (!parseField) {
this.appendField(propertyName, 'string');
parseField = this.fields[propertyName];
}
properties[propertyName] = parseField(node.textContent);
}
return {
type: 'Feature',
properties: properties,
id: feature.attributes['gml:id'].value
};
}
});
L.Format.GML = L.Format.Base.extend({
includes: L.GML.ParserContainerMixin,
initialize: function (options) {
L.Format.Base.prototype.initialize.call(this, options);
this.outputFormat = 'text/xml; subtype=gml/3.1.1';
this.initializeParserContainer();
this.appendParser(new L.GML.Point());
this.appendParser(new L.GML.LineString());
this.appendParser(new L.GML.Polygon());
this.appendParser(new L.GML.MultiLineString());
this.appendParser(new L.GML.MultiPolygon());
this.appendParser(new L.GML.MultiCurve());
this.appendParser(new L.GML.MultiSurface());
this.appendParser(new L.GML.MultiPoint());
},
responseToLayers: function (rawData) {
var layers = [];
var xmlDoc = L.XmlUtil.parseXml(rawData);
var featureCollection = xmlDoc.documentElement;
var featureMemberNodes = featureCollection.getElementsByTagNameNS(L.XmlUtil.namespaces.gml, 'featureMember');
for (var i = 0; i < featureMemberNodes.length; i++) {
var feature = featureMemberNodes[i].firstChild;
var featureAsLayer = this.processFeature(feature);
if (featureAsLayer) {
layers.push(featureAsLayer);
}
}
var featureMembersNode = featureCollection.getElementsByTagNameNS(L.XmlUtil.namespaces.gml, 'featureMembers');
if (featureMembersNode.length > 0) {
var features = featureMembersNode[0].childNodes;
for (var j = 0; j < features.length; j++) {
var node = features[j];
if (node.nodeType !== document.ELEMENT_NODE) {
continue;
}
var nodeAsLayer = this.processFeature(node);
if (nodeAsLayer) {
layers.push(nodeAsLayer);
}
}
}
return layers;
},
processFeature: function (feature) {
var layer = this.generateLayer(feature);
if (!layer) {
return null;
}
layer.feature = this.featureType.parse(feature);
return layer;
},
generateLayer: function (feature) {
var geometryField = feature.getElementsByTagNameNS(this.namespaceUri, this.options.geometryField)[0];
if (!geometryField) {
console.log(
'Geometry field \'' + this.options.geometryField + '\' doesn\' exist inside received feature: \'' + feature.innerHTML + '\', ' +
'so feature will be skipped and won\'t be converted into leaflet layer');
return null;
}
return this.parseElement(geometryField.firstChild, this.options);
}
});
L.Util.project = function (crs, latlngs) {
if (L.Util.isArray(latlngs)) {
var result = [];
latlngs.forEach(function (latlng) {
result.push(L.Util.project(crs, latlng));
});
return result;
} else {
return crs.projection.project(latlngs);
}
};
// 1.0.1 <=> 1.1.0 <=> 1.2.0 compatibility.
L.Util.isFlat = L.LineUtil.isFlat || L.LineUtil._flat || L.Polyline._flat;
L.GmlUtil = {
posNode: function (coord) {
return L.XmlUtil.createElementNS('gml:pos', { srsDimension: 2 }, { value: coord.x + ' ' + coord.y });
},
posListNode: function (coords, close) {
var localcoords = [];
coords.forEach(function (coord) {
localcoords.push(coord.x + ' ' + coord.y);
});
if (close && coords.length > 0) {
var coord = coords[0];
localcoords.push(coord.x + ' ' + coord.y);
}
var posList = localcoords.join(' ');
return L.XmlUtil.createElementNS('gml:posList', {}, { value: posList });
}
};
L.CircleMarker.include({
toGml: function(crs) {
var node = L.XmlUtil.createElementNS('gml:Point', {srsName: crs.code});
node.appendChild(L.GmlUtil.posNode(L.Util.project(crs, this.getLatLng())));
return node;
}
});
L.LatLngBounds.prototype.toGml = function (crs) {
var projectedSW = crs.project(this.getSouthWest());
var projectedNE = crs.project(this.getNorthEast());
var envelopeElement = L.XmlUtil.createElementNS('gml:Envelope', { srsName: crs.code });
envelopeElement.appendChild(L.XmlUtil.createElementNS('gml:lowerCorner', {}, { value: projectedSW.x + ' ' + projectedSW.y }));
envelopeElement.appendChild(L.XmlUtil.createElementNS('gml:upperCorner', {}, { value: projectedNE.x + ' ' + projectedNE.y }));
return envelopeElement;
};
L.Marker.include({
toGml: function (crs) {
var node = L.XmlUtil.createElementNS('gml:Point', {srsName: crs.code});
node.appendChild(L.GmlUtil.posNode(L.Util.project(crs, this.getLatLng())));
return node;
}
});
L.Polygon.include({
toGml: function (crs, forceMulti) {
var polygons = this.getLatLngs();
var gmlPolygons = [];
for (var i = 0; i < polygons.length; i++) {
var polygonCoordinates = polygons[i];
var flat = L.Util.isFlat(polygonCoordinates);
var node = L.XmlUtil.createElementNS('gml:Polygon', {srsName: crs.code, srsDimension: 2});
node.appendChild(L.XmlUtil.createElementNS('gml:exterior'))
.appendChild(L.XmlUtil.createElementNS('gml:LinearRing', {srsDimension: 2}))
.appendChild(L.GmlUtil.posListNode(L.Util.project(crs, flat ? polygonCoordinates : polygonCoordinates[0]), true));
if (!flat) {
for (var hole = 1; hole < polygonCoordinates.length; hole++) {
node.appendChild(L.XmlUtil.createElementNS('gml:interior'))
.appendChild(L.XmlUtil.createElementNS('gml:LinearRing', {srsDimension: 2}))
.appendChild(L.GmlUtil.posListNode(L.Util.project(crs, polygonCoordinates[hole]), true));
}
}
gmlPolygons.push(node);
}
if (gmlPolygons.length === 1 && !forceMulti) return gmlPolygons[0];
// else make multipolygon
var multi = L.XmlUtil.createElementNS('gml:MultiSurface', {srsName: crs.code, srsDimension: 2});
var collection = multi.appendChild(L.XmlUtil.createElementNS('gml:surfaceMembers'));
for (var p = 0; p < gmlPolygons.length; p++) {
collection.appendChild(gmlPolygons[p]);
}
return multi;
}
});
L.Polyline.include({
_lineStringNode: function (crs, latlngs) {
var node = L.XmlUtil.createElementNS('gml:LineString', {srsName: crs.code, srsDimension: 2});
node.appendChild(L.GmlUtil.posListNode(L.Util.project(crs, latlngs), false));
return node;
},
toGml: function (crs, forceMulti) {
var latLngs = this.getLatLngs();
var gmlElements = [];
if (L.Util.isFlat(latLngs)) {
gmlElements.push(this._lineStringNode(crs, latLngs));
} else {
for (var i = 0; i < latLngs.length; i++) {
gmlElements.push(this._lineStringNode(crs, latLngs[i]));
}
}
if(gmlElements.length === 1 && !forceMulti) {
return gmlElements[0];
}
var multi = L.XmlUtil.createElementNS('gml:MultiCurve', {srsName: crs.code, srsDimension: 2});
var collection = multi.appendChild(L.XmlUtil.createElementNS('gml:curveMembers'));
for (var lines = 0; lines < gmlElements.length; lines++) {
collection.appendChild(gmlElements[lines]);
}
return multi;
}
});
var PropertiesMixin = {
setProperties: function (obj) {
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
this.feature.properties[i] = obj[i];
}
}
},
getProperty: function (field) {
return this.feature.properties[field];
},
deleteProperties: function (arr) {
for (var i = 0; i < arr.length; i++) {
if (this.feature.properties.hasOwnProperty(arr[i])) {
delete this.feature.properties[arr[i]];
}
}
}
};
L.Marker.include(PropertiesMixin);
L.Path.include(PropertiesMixin);
L.WFS = L.FeatureGroup.extend({
_capabilities: null,
_boundingBox: null,
options: {
crs: L.CRS.EPSG3857,
showExisting: true,
geometryField: 'Shape',
url: '',
version: '1.1.0',
typeNS: '',
typeName: '',
typeNSName: '',
maxFeatures: null,
filter: null,
opacity: 1,
fillOpacity: 1,
style: {
color: 'black',
weight: 1,
opacity: 1,
fillOpacity: 1
},
namespaceUri: ''
},
state: {},
initialize: function (options, readFormat) {
L.setOptions(this, options);
this.state = {
exist: 'exist'
};
this._layers = {};
this.readFormat = readFormat || new L.Format.GML({
crs: this.options.crs,
geometryField: this.options.geometryField
});
this.options.typeNSName = this.namespaceName(this.options.typeName);
this.options.srsName = this.options.crs.code;
this._updateOpacity();
var that = this;
this.describeFeatureType(function () {
if (that.options.showExisting) {
that.loadFeatures(that.options.filter);
}
}, function (errorMessage) {
that.fire('error', {
error: new Error(errorMessage)
});
});
},
namespaceName: function (name) {
return this.options.typeNS + ':' + name;
},
describeFeatureType: function (successCallback, errorCallback) {
var requestData = L.XmlUtil.createElementNS('wfs:DescribeFeatureType', {
service: 'WFS',
version: this.options.version
});
requestData.appendChild(L.XmlUtil.createElementNS('TypeName', {}, {
value: this.options.typeNSName
}));
var that = this;
L.Util.request({
url: this.options.url,
data: L.XmlUtil.serializeXmlDocumentString(requestData),
headers: this.options.headers || {},
success: function (data) {
// If some exception occur, WFS-service can response successfully, but with ExceptionReport,
// and such situation must be handled.
var exceptionReport = L.XmlUtil.parseOwsExceptionReport(data);
if (exceptionReport) {
if (typeof (errorCallback) === 'function') {
errorCallback(exceptionReport.message);
}
return;
}
var xmldoc = L.XmlUtil.parseXml(data);
var featureInfo = xmldoc.documentElement;
that.readFormat.setFeatureDescription(featureInfo);
that.options.namespaceUri = featureInfo.attributes.targetNamespace.value;
if (typeof (successCallback) === 'function') {
successCallback();
}
},
error: function (errorMessage) {
if (typeof (errorCallback) === 'function') {
errorCallback(errorMessage);
}
}
});
},
getFeature: function (filter) {
var request = L.XmlUtil.createElementNS('wfs:GetFeature', {
service: 'WFS',
version: this.options.version,
maxFeatures: this.options.maxFeatures,
outputFormat: this.readFormat.outputFormat
});
var query = request.appendChild(L.XmlUtil.createElementNS('wfs:Query', {
typeName: this.options.typeNSName,
srsName: this.options.srsName
}));
if (filter) {
query.appendChild(L.filter(filter));
}
return request;
},
loadFeatures: function (filter) {
var that = this;
L.Util.request({
url: this.options.url,
data: L.XmlUtil.serializeXmlDocumentString(that.getFeature(filter)),
headers: this.options.headers || {},
success: function (responseText) {
// If some exception occur, WFS-service can response successfully, but with ExceptionReport,
// and such situation must be handled.
var exceptionReport = L.XmlUtil.parseOwsExceptionReport(responseText);
if (exceptionReport) {
that.fire('error', {
error: new Error(exceptionReport.message)
});
return that;
}
// Request was truly successful (without exception report),
// so convert response to layers.
var layers = that.readFormat.responseToLayers(responseText, {
coordsToLatLng: that.options.coordsToLatLng,
pointToLayer: that.options.pointToLayer
});
if (typeof that.options.style === "function") {
layers.forEach(function (element) {
element.state = that.state.exist;
if (element.setStyle) {
element.setStyle(that.options.style(element));
}
that.addLayer(element);
});
} else {
layers.forEach(function (element) {
element.state = that.state.exist;
that.addLayer(element);
});
that.setStyle(that.options.style);
}
that.fire('load', {
responseText: responseText
});
return that;
},
error: function (errorMessage) {
that.fire('error', {
error: new Error(errorMessage)
});
return that;
}
});
},
getCapabilities: function (successCallback, errorCallback) {
var capabilities = this._capabilities;
// Check if capabilities were already received & cached.
if (capabilities) {
if (typeof (successCallback) === 'function') {
successCallback(capabilities);
return;
}
}
var requestData = L.XmlUtil.createElementNS('wfs:GetCapabilities', {
service: 'WFS',
version: this.options.version
});
var that = this;
L.Util.request({
url: this.options.url,
data: L.XmlUtil.serializeXmlDocumentString(requestData),
headers: this.options.headers || {},
success: function (data) {
// If some exception occur, WFS-service can response successfully, but with ExceptionReport,
// and such situation must be handled.
var exceptionReport = L.XmlUtil.parseOwsExceptionReport(data);
if (exceptionReport) {
if (typeof (errorCallback) === 'function') {
errorCallback(new Error(exceptionReport.message));
}
return;
}
try {
// Request was truly successful (without exception report), parse WFS_Capabilities.
capabilities = L.XmlUtil.parseXml(data).documentElement;
} catch (error) {
// If parsing failed.
if (typeof (errorCallback) === 'function') {
errorCallback(error);
}
return;
}
// Cache received capabilities.
that._capabilities = capabilities;
if (typeof (successCallback) === 'function') {
successCallback(capabilities);
}
},
error: function (errorMessage) {
if (typeof (errorCallback) === 'function') {
errorCallback(new Error(errorMessage));
}
}
});
},
getBoundingBox: function (successCallback, errorCallback) {
var boundingBox = this._boundingBox;
// Check if bounding box was already received & cached.
if (boundingBox) {
if (typeof (successCallback) === 'function') {
successCallback(boundingBox);
return;
}
}
var that = this;
this.getCapabilities(function (capabilities) {
var featureTypeListElement = capabilities.getElementsByTagName('FeatureTypeList')[0];
// Extract all 'FeatureType' nodes to list.
var featureTypeList = featureTypeListElement.getElementsByTagName('FeatureType');
for (var i = 0, len = featureTypeList.length; i < len; i++) {
var featureType = featureTypeList[i];
// Extract current FeatureType's name.
var featureTypeNSName = L.XmlUtil.getNodeText(featureType.getElementsByTagName('Name')[0]);
// Find node with current layer instance's name and namespace.
if (featureTypeNSName === that.options.typeNSName) {
// The element is used to indicate the edges of an
// enclosing rectangle in decimal degrees of latitude and longitude in WGS84.
var wgs84BoundingBox = featureType.getElementsByTagNameNS(L.XmlUtil.namespaces.ows, 'WGS84BoundingBox')[0];
var lowerCornerElement = wgs84BoundingBox.getElementsByTagNameNS(L.XmlUtil.namespaces.ows, 'LowerCorner')[0];
var upperCornerElement = wgs84BoundingBox.getElementsByTagNameNS(L.XmlUtil.namespaces.ows, 'UpperCorner')[0];
// Corner node's inner text format is like '-74.047185 40.679648', Lng and Lat with a space between.
var lowerCorner = L.XmlUtil.getNodeText(lowerCornerElement);
var upperCorner = L.XmlUtil.getNodeText(upperCornerElement);
// Extract LngLats and reverse it to LatLngs.
var sw = lowerCorner.split(' ').reverse();
var ne = upperCorner.split(' ').reverse();
// Wrap it into LatLngBounds.
boundingBox = L.latLngBounds([sw, ne]);
break;
}
}
// Cache received and calculated bounding box.
that._boundingBox = boundingBox;
if (typeof (successCallback) === 'function') {
successCallback(boundingBox);
}
}, function (errorMessage) {
if (typeof (errorCallback) === 'function') {
errorCallback(new Error(errorMessage));
}
});
},
setOpacity: function (opacity, fillOpacity) {
this.options.opacity = opacity;
this.options.fillOpacity = fillOpacity || opacity;
this._updateOpacity();
return this;
},
_updateOpacity: function () {
var style = L.extend(this.options.style || {}, {
opacity: this.options.opacity,
fillOpacity: this.options.fillOpacity
});
this.setStyle(style);
}
});
L.wfs = function (options, readFormat) {
return new L.WFS(options, readFormat);
};
L.WFST = L.WFS.extend({
options: {
forceMulti: false
},
initialize: function (options, readFormat) {
L.WFS.prototype.initialize.call(this, options, readFormat);
this.state = L.extend(this.state, {
insert: 'insertElement',
update: 'updateElement',
remove: 'removeElement'
});
this.changes = {};
},
addLayer: function (layer) {
L.FeatureGroup.prototype.addLayer.call(this, layer);
if (!layer.feature) {
layer.feature = { properties: {} };
}
if (!layer.state) {
layer.state = this.state.insert;
var id = this.getLayerId(layer);
this.changes[id] = layer;
}
return this;
},
removeLayer: function (layer) {
L.FeatureGroup.prototype.removeLayer.call(this, layer);
var id = this.getLayerId(layer);
if (id in this.changes) {
var change = this.changes[id];
if (change.state === this.state.insert) {
delete this.changes[id];
}
else {
change.state = this.state.remove;
}
}
else {
layer.state = this.state.remove;
this.changes[id] = layer;
}
},
editLayer: function (layer) {
if (layer.state !== this.state.insert) {
layer.state = this.state.update;
}
var id = this.getLayerId(layer);
this.changes[id] = layer;
return this;
},
save: function () {
var transaction = L.XmlUtil.createElementNS('wfs:Transaction', { service: 'WFS', version: this.options.version });
var inserted = [];
for (var id in this.changes) {
var layer = this.changes[id];
var action = this[layer.state](layer);
transaction.appendChild(action);
if (layer.state === this.state.insert) {
inserted.push(layer);
}
}
var that = this;
L.Util.request({
url: this.options.url,
data: L.XmlUtil.serializeXmlDocumentString(transaction),
headers: this.options.headers || {},
withCredentials: true,
success: function (data) {
var xmlDoc = L.XmlUtil.parseXml(data);
var exception = L.XmlUtil.parseOwsExceptionReport(xmlDoc);
if(exception !== null) {
that.fire('save:failed', exception);
return;
}
var insertResult = L.XmlUtil.evaluate('//wfs:InsertResults/wfs:Feature/ogc:FeatureId/@fid', xmlDoc);
var insertedIds = [];
var id = insertResult.iterateNext();
while (id) {
insertedIds.push(new L.Filter.GmlObjectID(id.value));
id = insertResult.iterateNext();
}
inserted.forEach(function (layer) {
L.FeatureGroup.prototype.removeLayer.call(that, layer);
});
that.once('load', function () {
that.fire('save:success');
that.changes = {};
});
that.loadFeatures(insertedIds);
},
error: function (data) {
that.fire('save:failed', data);
}
});
return this;
}
});
L.wfst = function (options, readFormat) {
return new L.WFST(options, readFormat);
};
L.WFST.include({
gmlFeature: function (layer) {
var featureNode = L.XmlUtil.createElementNS(this.options.typeNSName, {}, { uri: this.options.namespaceUri });
var feature = layer.feature;
for (var propertyName in feature.properties) {
featureNode.appendChild(this.gmlProperty(propertyName,
feature.properties[propertyName]));
}
featureNode.appendChild(
this.gmlProperty(
this.options.geometryField,
layer.toGml(
this.options.crs,
this.options.forceMulti
)
)
);
return featureNode;
},
/**
Returns element with name as tag and value as innerText or child element
```xml
value
```
or if value is element
```xml
```
@method gmlProperty
@param {string} name Name of property
@param {Object} value Value of property
@return {Element} simple property element value
*/
gmlProperty: function (name, value) {
var propertyNode = L.XmlUtil.createElementNS(this.namespaceName(name));
if (value instanceof Element) {
propertyNode.appendChild(value);
}
else if (value === null || value === undefined || value === '') {
L.XmlUtil.setAttributes(propertyNode, { 'xsi:nil': true });
} else {
propertyNode.appendChild(L.XmlUtil.createTextNode(value));
}
return propertyNode;
},
/**
Returns wfs:Property element with passed property name and value:
```xml
%name%
%value%
```
@method wfsProperty
@param {string} name Property name
@param {Object} value Property value, if passed Element object it will be added as child element of value
@return {Element}
*/
wfsProperty: function (name, value) {
var propertyNode = L.XmlUtil.createElementNS('wfs:Property');
propertyNode.appendChild(L.XmlUtil.createElementNS('wfs:Name', {}, { value: name }));
var valueNode = L.XmlUtil.createElementNS('wfs:Value');
if (value instanceof Element) {
valueNode.appendChild(value);
}
else {
valueNode.appendChild(L.XmlUtil.createTextNode(value));
}
propertyNode.appendChild(valueNode);
return propertyNode;
}
});
L.WFST.include({
/**
Returns wfs:Insert element for passed layer
@method insertElement
@param {Layer} layer
@return {Element} wfs:Insert element with layer
*/
insertElement: function (layer) {
var node = L.XmlUtil.createElementNS('wfs:Insert');
node.appendChild(this.gmlFeature(layer));
return node;
},
/**
Returns wfs:Update element for specified layer
@method updateElement
@param {Layer} layer
@return {Element} wfs:Update element for passed layer properties limited with filter by feature.id
*/
updateElement: function (layer) {
var node = L.XmlUtil.createElementNS('wfs:Update', { typeName: this.options.typeNSName });
var feature = layer.feature;
for (var propertyName in feature.properties) {
if (feature.properties.hasOwnProperty(propertyName)) {
node.appendChild(this.wfsProperty(propertyName, feature.properties[propertyName]));
}
}
node.appendChild(
this.wfsProperty(
this.namespaceName(this.options.geometryField),
layer.toGml(this.options.crs, this.options.forceMulti)
)
);
var idFilter = new L.Filter.GmlObjectID(layer.feature.id);
node.appendChild(L.filter(idFilter));
return node;
},
removeElement: function (layer) {
var node = L.XmlUtil.createElementNS('wfs:Delete', { typeName: this.options.typeNSName });
var idFilter = new L.Filter.GmlObjectID(layer.feature.id);
node.appendChild(L.filter(idFilter));
return node;
}
});
})(window, document);