merged with upstream and improved key handling

This commit is contained in:
Dmitry Fedorov
2018-11-02 17:19:10 -07:00
252 changed files with 5980 additions and 3750 deletions

View File

@@ -2,6 +2,16 @@
### Next version
#### The `getUid` function returns string
The `getUid` function from the `ol/util` module now returns a string instead of a number.
#### Attributions are not collapsible for `ol/source/OSM`
When a map contains a layer from a `ol/source/OSM` source, the `ol/control/Attribution` control will be shown with the `collapsible: false` behavior.
To get the previous behavior, configure the `ol/control/Attribution` control with `collapsible: true`.
### v5.2.0
#### Removal of the `snapToPixel` option for `ol/style/Image` subclasses
@@ -16,7 +26,7 @@ When rendering with the Immediate API, symbols will no longer be snapped to inte
#### Geometry constructor and `setCoordinates` no longer accept `null` coordinates
Geometries (`ol/geom/*`) now need to be constructed with valid coordinates (center for `ol/geom/Circle`) as first constructor argument. The same applies to the `setCoordinates()` (`setCenter() for `ol/geom/Circle`) method.
Geometries (`ol/geom/*`) now need to be constructed with valid coordinates (center for `ol/geom/Circle`) as first constructor argument. The same applies to the `setCoordinates()` (`setCenter()` for `ol/geom/Circle`) method.
### v5.0.0

View File

@@ -7,22 +7,23 @@
"allowUnknownTags": true
},
"source": {
"includePattern": ".+\\.js(doc)?$",
"includePattern": ".+\\.js$",
"excludePattern": "(^|\\/|\\\\)_",
"include": [
"src/ol"
]
},
"plugins": [
"plugins/markdown",
"config/jsdoc/api/plugins/normalize-exports",
"config/jsdoc/api/plugins/markdown",
"jsdoc-plugin-typescript",
"config/jsdoc/api/plugins/inline-options",
"config/jsdoc/api/plugins/inheritdoc",
"config/jsdoc/api/plugins/events",
"config/jsdoc/api/plugins/observable",
"config/jsdoc/api/plugins/api"
],
"markdown": {
"parser": "gfm"
"typescript": {
"moduleRoot": "src"
},
"templates": {
"cleverLinks": true,

View File

@@ -8,10 +8,10 @@
<td><p>The view manages the visual parameters of the map view, like resolution or rotation.</p>
[View](module-ol_View-View.html) with center, projection, resolution and rotation</td>
<td><p>Layers are lightweight containers that get their data from [sources](module-ol_source_Source-Source.html).</p>
[layer/Tile](module-ol_layer_Tile-TileLayer.html)<br>
[layer/Image](module-ol_layer_Image-ImageLayer.html)<br>
[layer/Vector](module-ol_layer_Vector-VectorLayer.html)<br>
[layer/VectorTile](module-ol_layer_VectorTile-VectorTileLayer.html)</td>
[ol/layer/Tile](module-ol_layer_Tile-TileLayer.html)<br>
[ol/layer/Image](module-ol_layer_Image-ImageLayer.html)<br>
[ol/layer/Vector](module-ol_layer_Vector-VectorLayer.html)<br>
[ol/layer/VectorTile](module-ol_layer_VectorTile-VectorTileLayer.html)</td>
</tr><tr>
<th>Controls</th><th>Interactions</th><th>Sources and formats</th>
</tr><tr>
@@ -21,20 +21,20 @@
<td>
[Map default interactions](module-ol_interaction.html#~defaults)<br>
Interactions for [vector features](module-ol_Feature-Feature.html)
<ul><li>[interaction/Select](module-ol_interaction_Select-Select.html)</li>
<li>[interaction/Draw](module-ol_interaction_Draw-Draw.html)</li>
<li>[interaction/Modify](module-ol_interaction_Modify-Modify.html)</li></ul>
<ul><li>[ol/interaction/Select](module-ol_interaction_Select-Select.html)</li>
<li>[ol/interaction/Draw](module-ol_interaction_Draw-Draw.html)</li>
<li>[ol/interaction/Modify](module-ol_interaction_Modify-Modify.html)</li></ul>
[All interactions](module-ol_interaction_Interaction-Interaction.html)</td>
<td>[Tile sources](module-ol_source_Tile-TileSource.html) for [layer/Tile](module-ol_layer_Tile-TileLayer.html)
<br>[Image sources](module-ol_source_Image-ImageSource.html) for [layer/Image](module-ol_layer_Image-ImageLayer.html)
<br>[Vector sources](module-ol_source_Vector-VectorSource.html) for [layer/Vector](module-ol_layer_Vector-VectorLayer.html)
<br>[Vector tile sources](module-ol_source_VectorTile-VectorTile.html) for [layer/VectorTile](module-ol_layer_VectorTile-VectorTileLayer.html)
<td>[Tile sources](module-ol_source_Tile-TileSource.html) for [ol/layer/Tile](module-ol_layer_Tile-TileLayer.html)
<br>[Image sources](module-ol_source_Image-ImageSource.html) for [ol/layer/Image](module-ol_layer_Image-ImageLayer.html)
<br>[Vector sources](module-ol_source_Vector-VectorSource.html) for [ol/layer/Vector](module-ol_layer_Vector-VectorLayer.html)
<br>[Vector tile sources](module-ol_source_VectorTile-VectorTile.html) for [ol/layer/VectorTile](module-ol_layer_VectorTile-VectorTileLayer.html)
<br>[Formats](module-ol_format_Feature-FeatureFormat.html) for reading/writing vector data
<br>[format/WMSCapabilities](module-ol_format_WMSCapabilities-WMSCapabilities.html)</td></tr>
<br>[ol/format/WMSCapabilities](module-ol_format_WMSCapabilities-WMSCapabilities.html)</td></tr>
<tr><th>Projections</th><th>Observable objects</th><th>Other components</th></tr>
<tr><td><p>All coordinates and extents need to be provided in view projection (default: EPSG:3857). To transform, use [proj.transform()](module-ol_proj.html#.transform) and [proj.transformExtent()](module-ol_proj.html#.transformExtent).</p>
<tr><td><p>All coordinates and extents need to be provided in view projection (default: EPSG:3857). To transform, use [ol/proj#transform()](module-ol_proj.html#.transform) and [ol/proj#transformExtent()](module-ol_proj.html#.transformExtent).</p>
[ol/proj](module-ol_proj.html)</td>
<td><p>Changes to all [ol/Object](module-ol_Object-BaseObject.html)s can be observed by calling the [object.on('propertychange')](module-ol_Object-BaseObject.html#on) method. Listeners receive an [ol/Object~ObjectEvent](module-ol_Object-ObjectEvent.html) with information on the changed property and old value.</p>
<td><p>Changes to all [ol/Object](module-ol_Object-BaseObject.html)s can be observed by calling the [object.on('propertychange')](module-ol_Object-BaseObject.html#on) method. Listeners receive an [ol/Object.ObjectEvent](module-ol_Object-ObjectEvent.html) with information on the changed property and old value.</p>
<td>
[ol/Geolocation](module-ol_Geolocation.html)<br>
[ol/Overlay](module-ol_Overlay-Overlay.html)<br></td>

View File

@@ -95,17 +95,20 @@ exports.handlers = {
newDoclet: function(e) {
const doclet = e.doclet;
if (doclet.stability) {
modules[doclet.longname.split('~').shift()] = true;
modules[doclet.longname.split(/[~\.]/).shift()] = true;
api.push(doclet);
}
// Mark explicity defined namespaces - needed in parseComplete to keep
// namespaces that we need as containers for api items.
if (/.*\.jsdoc$/.test(doclet.meta.filename) && doclet.kind == 'namespace') {
doclet.namespace_ = true;
}
if (doclet.kind == 'class') {
modules[doclet.longname.split('~').shift()] = true;
modules[doclet.longname.split(/[~\.]/).shift()] = true;
if (!(doclet.longname in classes)) {
classes[doclet.longname] = doclet;
} else if ('augments' in doclet) {
classes[doclet.longname].augments = doclet.augments;
}
}
if (doclet.name === doclet.longname && !doclet.memberof) {
// Make sure anonymous default exports are documented
doclet.setMemberof(doclet.longname);
}
},
@@ -113,7 +116,7 @@ exports.handlers = {
const doclets = e.doclets;
for (let i = doclets.length - 1; i >= 0; --i) {
const doclet = doclets[i];
if (doclet.stability || doclet.namespace_) {
if (doclet.stability) {
if (doclet.kind == 'class') {
includeAugments(doclet);
}

View File

@@ -12,7 +12,7 @@ exports.handlers = {
events[cls] = [];
}
events[cls].push(doclet.longname);
} else if (doclet.kind == 'class') {
} else if (doclet.kind == 'class' && !(doclet.longname in classes)) {
classes[doclet.longname] = doclet;
}
},
@@ -29,7 +29,7 @@ exports.handlers = {
event = doclet.fires[j].replace('event:', '');
if (events[event]) {
fires.push.apply(fires, events[event]);
} else {
} else if (doclet.fires[j] !== 'event:ObjectEvent') {
fires.push(doclet.fires[j]);
}
}
@@ -40,4 +40,3 @@ exports.handlers = {
}
};

View File

@@ -0,0 +1,109 @@
/*
* This is a hack to prevent inheritDoc tags from entirely removing
* documentation of the method that inherits the documentation.
*
* TODO: Remove this hack when https://github.com/jsdoc3/jsdoc/issues/53
* is addressed.
*/
exports.defineTags = function(dictionary) {
dictionary.defineTag('inheritDoc', {
mustHaveValue: false,
canHaveType: false,
canHaveName: false,
onTagged: function(doclet, tag) {
doclet.inheritdoc = true;
}
});
};
const lookup = {};
const incompleteByClass = {};
const keepKeys = ['comment', 'meta', 'name', 'memberof', 'longname', 'augment',
'stability'];
exports.handlers = {
newDoclet: function(e) {
const doclet = e.doclet;
let incompletes;
if (!(doclet.longname in lookup)) {
lookup[doclet.longname] = [];
}
lookup[doclet.longname].push(doclet);
if (doclet.inheritdoc) {
if (!(doclet.memberof in incompleteByClass)) {
incompleteByClass[doclet.memberof] = [];
}
incompletes = incompleteByClass[doclet.memberof];
if (incompletes.indexOf(doclet.name) == -1) {
incompletes.push(doclet.name);
}
}
},
parseComplete: function(e) {
let ancestors, candidate, candidates, doclet, i, j, k, l, key;
let incompleteDoclet, stability, incomplete, incompletes;
const doclets = e.doclets;
for (i = doclets.length - 1; i >= 0; --i) {
doclet = doclets[i];
if (doclet.augments) {
ancestors = [].concat(doclet.augments);
}
incompletes = incompleteByClass[doclet.longname];
if (ancestors && incompletes) {
// collect ancestors from the whole hierarchy
for (j = 0; j < ancestors.length; ++j) {
candidates = lookup[ancestors[j]];
if (candidates) {
for (k = candidates.length - 1; k >= 0; --k) {
candidate = candidates[k];
if (candidate.augments) {
ancestors = ancestors.concat(candidate.augments);
}
}
}
}
// walk through all inheritDoc members
for (j = incompletes.length - 1; j >= 0; --j) {
incomplete = incompletes[j];
candidates = lookup[doclet.longname + '#' + incomplete];
if (candidates) {
// get the incomplete doclet that needs to be augmented
for (k = candidates.length - 1; k >= 0; --k) {
incompleteDoclet = candidates[k];
if (incompleteDoclet.inheritdoc) {
break;
}
}
}
// find the documented ancestor
for (k = ancestors.length - 1; k >= 0; --k) {
candidates = lookup[ancestors[k] + '#' + incomplete];
if (candidates) {
for (l = candidates.length - 1; l >= 0; --l) {
candidate = candidates[l];
if (candidate && !candidate.inheritdoc) {
stability = candidate.stability || incompleteDoclet.stability;
if (stability) {
incompleteDoclet.stability = stability;
for (key in candidate) {
if (candidate.hasOwnProperty(key) &&
keepKeys.indexOf(key) == -1) {
incompleteDoclet[key] = candidate[key];
}
}
}
}
}
}
}
}
}
}
}
};

View File

@@ -0,0 +1,111 @@
/**
* Modified from JSDoc's plugins/markdown and lib/jsdoc/util/markdown modules
* (see https://github.com/jsdoc3/jsdoc/), which are licensed under the Apache 2
* license (see http://www.apache.org/licenses/LICENSE-2.0).
*
* This version does not protect http(s) urls from being turned into links, and
* works around an issue with `~` characters in module paths by escaping them.
*/
const marked = require('marked');
const format = require('util').format;
const tags = [
'author',
'classdesc',
'description',
'exceptions',
'params',
'properties',
'returns',
'see',
'summary'
];
const hasOwnProp = Object.prototype.hasOwnProperty;
const markedRenderer = new marked.Renderer();
// Allow prettyprint to work on inline code samples
markedRenderer.code = function(code, language) {
const langClass = language ? ' lang-' + language : '';
return format('<pre class="prettyprint source%s"><code>%s</code></pre>',
langClass, escapeCode(code));
};
function escapeCode(source) {
return source.replace(/</g, '&lt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
}
function escapeUnderscoresAndTildes(source) {
return source.replace(/\{@[^}\r\n]+\}/g, function(wholeMatch) {
return wholeMatch
.replace(/(^|[^\\])_/g, '$1\\_')
.replace('~', '&tilde;');
});
}
function unencodeQuotesAndTildes(source) {
return source.replace(/\{@[^}\r\n]+\}/g, function(wholeMatch) {
return wholeMatch
.replace(/&quot;/g, '"')
.replace(/&tilde;/g, '~');
});
}
function parse(source) {
let result;
source = escapeUnderscoresAndTildes(source);
result = marked(source, {renderer: markedRenderer})
.replace(/\s+$/, '')
.replace(/&#39;/g, '\'');
result = unencodeQuotesAndTildes(result);
return result;
}
function shouldProcessString(tagName, text) {
let shouldProcess = true;
// we only want to process `@author` and `@see` tags that contain Markdown links
if ((tagName === 'author' || tagName === 'see') && text.indexOf('[') === -1) {
shouldProcess = false;
}
return shouldProcess;
}
function process(doclet) {
tags.forEach(function(tag) {
if (!hasOwnProp.call(doclet, tag)) {
return;
}
if (typeof doclet[tag] === 'string' && shouldProcessString(tag, doclet[tag])) {
doclet[tag] = parse(doclet[tag]);
} else if (Array.isArray(doclet[tag])) {
doclet[tag].forEach(function(value, index, original) {
const inner = {};
inner[tag] = value;
process(inner);
original[index] = inner[tag];
});
} else if (doclet[tag]) {
process(doclet[tag]);
}
});
}
exports.handlers = {
newDoclet: function(e) {
process(e.doclet);
}
};

View File

@@ -1,106 +0,0 @@
/**
* @filedesc
* Expands module path type to point to default export when no name is given
*/
const fs = require('fs');
const path = require('path');
let moduleRoot;
function addDefaultExportPath(obj) {
if (!Array.isArray(obj)) {
obj = obj.names;
}
obj.forEach((name, index) => {
const matches = name.match(/module\:([^>|),\.<]|)+/g);
if (matches) {
matches.forEach(module => {
if (!/[~\.]/.test(module)) {
const checkFile = path.resolve(moduleRoot, module.replace(/^module\:/, ''));
const file = fs.readFileSync(require.resolve(checkFile), 'utf-8');
const lines = file.split('\n');
let hasDefaultExport = false;
for (let i = 0, ii = lines.length; i < ii; ++i) {
hasDefaultExport = hasDefaultExport || /^export default [^\{]/.test(lines[i]);
const match = lines[i].match(/^export default ([A-Za-z_$][A-Za-z0-9_$]+);$/);
if (match) {
// Use variable name if default export is assigned to a variable.
obj[index] = name = name.replace(module, `${module}~${match[1]}`);
return;
}
}
if (hasDefaultExport) {
// Duplicate last part if default export is not assigned to a variable.
obj[index] = name = name.replace(module, `${module}~${module.split('/').pop()}`);
}
}
});
}
});
}
function replaceLinks(comment) {
const matches = comment.match(/\{@link [^\} #]+}/g);
if (matches) {
const modules = matches.map(m => {
const mm = m.match(/(module:[^\}]+)}$/);
if (mm) {
return mm[1];
}
}).filter(m => !!m);
const newModules = modules.concat();
addDefaultExportPath(newModules);
modules.forEach((module, i) => {
comment = comment.replace(module, newModules[i]);
});
}
return comment;
}
exports.handlers = {
/**
* Adds default export to module path types without name
* @param {Object} e Event object.
*/
newDoclet: function(e) {
const doclet = e.doclet;
if (doclet.kind == 'module') {
const levelsUp = doclet.longname.replace(/^module\:/, '').split('/');
if (doclet.meta.filename != 'index.js') {
levelsUp.pop();
}
const pathArgs = [doclet.meta.path].concat(levelsUp.map(() => '../'));
moduleRoot = path.resolve.apply(null, pathArgs);
} else {
if (doclet.description) {
doclet.description = replaceLinks(doclet.description);
}
if (doclet.classdesc) {
doclet.classdesc = replaceLinks(doclet.classdesc);
}
const module = doclet.longname.split('#').shift();
if (module.indexOf('module:') == 0 && module.indexOf('.') !== -1) {
doclet.longname = doclet.longname.replace(module, module.replace('.', '~'));
}
if (doclet.augments) {
addDefaultExportPath(doclet.augments);
}
if (doclet.params) {
doclet.params.forEach(p => addDefaultExportPath(p.type));
}
if (doclet.returns) {
doclet.returns.forEach(r => addDefaultExportPath(r.type));
}
if (doclet.properties) {
doclet.properties.forEach(p => addDefaultExportPath(p.type));
}
if (doclet.type) {
addDefaultExportPath(doclet.type);
}
}
}
};

View File

@@ -5,7 +5,7 @@ exports.handlers = {
newDoclet: function(e) {
const doclet = e.doclet;
if (doclet.kind == 'class') {
if (doclet.kind == 'class' && !(doclet.longname in classes)) {
classes[doclet.longname] = doclet;
}
},
@@ -47,7 +47,7 @@ exports.handlers = {
if (!cls.fires) {
cls.fires = [];
}
event = 'module:ol/Object~ObjectEvent#event:change:' + name;
event = 'module:ol/Object.ObjectEvent#event:change:' + name;
if (cls.fires.indexOf(event) == -1) {
cls.fires.push(event);
}

View File

@@ -1,85 +0,0 @@
/*
* Changes @enum annotations into @typedef.
*/
// types that are undefined or typedefs containing undefined
let undefinedLikes = null;
/**
* Changes the description of the param if it is required.
* @param {Object} doclet The doclet.
* @returns {Object} The modified doclet.
*/
function markRequiredIfNeeded(doclet) {
const memberof = doclet.memberof;
if (!memberof) {
return doclet;
}
const types = doclet.type.names;
let isRequiredParam = true;
// iterate over all types that are like-undefined (see above for explanation)
for (let idx = undefinedLikes.length - 1; idx >= 0; idx--) {
const undefinedLike = undefinedLikes[idx];
// … if the current types contains a type that is undefined-like,
// it is not required.
if (types.indexOf(undefinedLike) != -1) {
isRequiredParam = false;
}
}
if (isRequiredParam) {
const reqSnippet = '<span class="required-option">Required.</span></p>';
const endsWithP = /<\/p>$/i;
let description = doclet.description;
if (description && endsWithP.test(description)) {
description = description.replace(endsWithP, ' ' + reqSnippet);
} else if (doclet.description === undefined) {
description = '<p>' + reqSnippet;
}
doclet.description = description;
}
return doclet;
}
/**
* Iterates over all doclets and finds the names of types that contain
* undefined. Stores the names in the global variable undefinedLikes, so
* that e.g. markRequiredIfNeeded can use these.
* @param {Array} doclets The doclets.
*/
function findTypesLikeUndefined(doclets) {
undefinedLikes = ['undefined']; // include type 'undefined' explicitly
for (let i = doclets.length - 1; i >= 0; --i) {
const doclet = doclets[i];
if (doclet.kind === 'typedef') {
const types = doclet.type.names;
if (types.indexOf('undefined') !== -1) {
// the typedef contains 'undefined', so it self is undefinedLike.
undefinedLikes.push(doclet.longname);
}
}
}
}
exports.handlers = {
newDoclet: function(e) {
const doclet = e.doclet;
if (doclet.isEnum) {
// We never export enums, so we document them like typedefs
doclet.kind = 'typedef';
delete doclet.isEnum;
}
},
parseComplete: function(e) {
const doclets = e.doclets;
findTypesLikeUndefined(doclets);
for (let i = doclets.length - 1; i >= 0; --i) {
markRequiredIfNeeded(doclets[i]);
}
}
};

View File

@@ -30,7 +30,11 @@ $(function () {
});
// Show an item related a current documentation automatically
var filename = $('.page-title').data('filename').replace(/\.[a-z]+$/, '');
var filename = $('.page-title').data('filename')
.replace(/\.[a-z]+$/, '')
.replace('module-', 'module:')
.replace(/_/g, '/')
.replace(/-/g, '~');
var $currentItem = $('.navigation .item[data-name*="' + filename + '"]:eq(0)');
if ($currentItem.length) {
@@ -97,7 +101,8 @@ $(function () {
var anchors = $('.anchor');
var _onHashChange = function () {
var activeHash = window.document.location.hash
.replace(/\./g, '\\.'); // Escape dot in element id
.replace(/\./g, '\\.') // Escape dot in element id
.replace(/\~/g, '\\~'); // Escape tilde in element id
anchors.removeClass('highlighted');

View File

@@ -14,7 +14,7 @@ if (data.type && data.type.names) {
<div class="anchor" id="<?js= id ?>">
</div>
<h4 class="name">
<?js= data.attribs + (data.scope === 'static' ? longname : name) + typeSignature ?>
<?js= data.attribs + (data.scope === 'static' ? longname : name.indexOf('module:') === 0 ? name.split('/').pop() : name) + typeSignature ?>
<?js= this.partial('stability.tmpl', data) ?>
</h4>
</div>

View File

@@ -77,7 +77,7 @@ var self = this;
(<?js= self.linkto(eventClass.longname) ?>)
<?js } ?>
<?js } ?>
<?js= self.partial('stability.tmpl', eventDoclet || (data.stability ? data : {stability: 'experimental'})) ?>
<?js= self.partial('stability.tmpl', eventDoclet || (data.stability ? data : {})) ?>
<?js if (description) { ?> -
<?js= description ?>
<?js } ?>

View File

@@ -1,5 +1,8 @@
<?js
var self = this;
function toShortName(name) {
return name.indexOf('module:') === 0 ? name.split('/').pop() : name;
}
?>
<div class="navigation">
<div class="search">
@@ -25,7 +28,7 @@ var self = this;
<?js
item.members.forEach(function (v) {
?>
<li data-name="<?js= v.longname ?>"><?js= self.linkto(v.longname, v.name) ?></li>
<li data-name="<?js= v.longname ?>"><?js= self.linkto(v.longname, toShortName(v.name)) ?></li>
<?js
});
}
@@ -40,7 +43,7 @@ var self = this;
item.typedefs.forEach(function (v) {
?>
<li data-name="<?js= v.longname ?>" class="<?js= (v.stability && v.stability !== 'stable') ? 'unstable' : ''?>">
<?js= self.linkto(v.longname, v.name) ?>
<?js= self.linkto(v.longname, toShortName(v.name)) ?>
</li>
<?js
});
@@ -57,7 +60,7 @@ var self = this;
item.methods.forEach(function (v) {
?>
<li data-name="<?js= v.longname ?>" class="<?js= (v.stability && v.stability !== 'stable') ? 'unstable' : ''?>">
<?js= self.linkto(v.longname, v.name) ?>
<?js= self.linkto(v.longname, toShortName(v.name)) ?>
</li>
<?js
});
@@ -74,7 +77,7 @@ var self = this;
v = self.find({longname: v})[0] || {longname: v, name: v.split(/#?event:/)[1]};
?>
<li data-name="<?js= v.longname ?>" class="<?js= (v.stability && v.stability != 'stable') ? 'unstable' : '' ?>">
<?js= self.linkto(v.longname, v.name) ?>
<?js= self.linkto(v.longname, toShortName(v.name)) ?>
</li>
<?js
});

View File

@@ -8,7 +8,7 @@
<th>Name</th>
<th>Type</th>
<th>Settable</th>
<th><a href="module-ol_Object-ObjectEvent.html">ol/Object~ObjectEvent</a> type</th>
<th><a href="module-ol_Object-ObjectEvent.html">ol/Object.ObjectEvent</a> type</th>
<th class="last">Description</th>
</tr>
</thead>

View File

@@ -10,8 +10,12 @@
"includePattern": "\\.js$"
},
"plugins": [
"jsdoc-plugin-typescript",
"config/jsdoc/info/api-plugin",
"config/jsdoc/info/define-plugin",
"config/jsdoc/info/virtual-plugin"
]
],
"typescript": {
"moduleRoot": "src"
}
}

View File

@@ -1,21 +0,0 @@
// Rollup configuration for the full build
import noderesolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import {uglify} from 'rollup-plugin-uglify';
import buble from 'rollup-plugin-buble';
import sourcemaps from 'rollup-plugin-sourcemaps';
export default {
input: 'build/index.js',
output: [
{file: 'build/ol.js', format: 'iife', sourcemap: true}
],
plugins: [
noderesolve(),
commonjs(),
buble(),
uglify(),
sourcemaps()
]
};

View File

@@ -0,0 +1,13 @@
const path = require('path');
module.exports = {
entry: './build/index.js',
devtool: 'source-map',
mode: 'production',
output: {
path: path.resolve('./build/legacy'),
filename: 'ol.js',
library: 'ol',
libraryTarget: 'umd',
libraryExport: 'default'
}
};

View File

@@ -54,9 +54,12 @@ The projection of your map can be set through the `view`-property. Here are some
examples:
```javascript
import Map from 'ol/Map';
import View from 'ol/View';
// OpenLayers comes with support for the World Geodetic System 1984, EPSG:4326:
var map = new ol.Map({
view: new ol.View({
const map = new Map({
view: new View({
projection: 'EPSG:4326'
// other view properties like map center etc.
})
@@ -65,23 +68,29 @@ var map = new ol.Map({
```
```javascript
import Map from 'ol/Map';
import View from 'ol/View';
import proj4 from 'proj4';
import {register} from 'ol/proj/proj4';
import {get as getProjection} from 'ol/proj';
// To use other projections, you have to register the projection in OpenLayers.
// This can easily be done with [https://proj4js.org](proj4)
//
// By default OpenLayers does not know about the EPSG:21781 (Swiss) projection.
// So we create a projection instance for EPSG:21781 and pass it to
// ol.proj.addProjection to make it available to the library for lookup by its
// register to make it available to the library for lookup by its
// code.
proj4.defs('EPSG:21781',
'+proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 +k_0=1 ' +
'+x_0=600000 +y_0=200000 +ellps=bessel ' +
'+towgs84=660.077,13.551,369.344,2.484,1.783,2.939,5.66 +units=m +no_defs');
ol.proj.proj4.register(proj4);
var swissProjection = ol.proj.get('EPSG:21781');
register(proj4);
const swissProjection = getProjection('EPSG:21781');
// we can now use the projection:
var map = new ol.Map({
view: new ol.View({
const map = new Map({
view: new View({
projection: swissProjection
// other view properties like map center etc.
})
@@ -104,15 +113,20 @@ coordinates for the center have to be provided in that projection. Chances are
that your map looks like this:
```javascript
var washingtonLonLat = [-77.036667, 38.895];
var map = new ol.Map({
import Map from 'ol/Map';
import View from 'ol/View';
import TileLayer from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';
const washingtonLonLat = [-77.036667, 38.895];
const map = new Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
new TileLayer({
source: new OSM()
})
],
target: 'map',
view: new ol.View({
view: new View({
center: washingtonLonLat,
zoom: 12
})
@@ -128,31 +142,38 @@ The solution is easy: Provide the coordinates projected into Web Mercator.
OpenLayers has some helpful utility methods to assist you:
```javascript
var washingtonLonLat = [-77.036667, 38.895];
var washingtonWebMercator = ol.proj.fromLonLat(washingtonLonLat);
import Map from 'ol/Map';
import View from 'ol/View';
import TileLayer from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';
import {fromLonLat} from 'ol/proj';
var map = new ol.Map({
const washingtonLonLat = [-77.036667, 38.895];
const washingtonWebMercator = fromLonLat(washingtonLonLat);
const map = new Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
new TileLayer({
source: new OSM()
})
],
target: 'map',
view: new ol.View({
view: new View({
center: washingtonWebMercator,
zoom: 8
})
});
```
The method `ol.proj.fromLonLat()` is available from version 3.5 onwards.
The method `fromLonLat()` is available from version 3.5 onwards.
If you told OpenLayers about a custom projection (see above), you can use the
following method to transform a coordinate from WGS84 to your projection:
```javascript
import {transform} from 'ol/proj';
// assuming that OpenLayers knows about EPSG:21781, see above
var swissCoord = ol.proj.transform([8.23, 46.86], 'EPSG:4326', 'EPSG:21781');
const swissCoord = transform([8.23, 46.86], 'EPSG:4326', 'EPSG:21781');
```
@@ -189,18 +210,24 @@ So the next step would be to put the decimal coordinates into an array and use
it as center:
```javascript
var schladming = [47.394167, 13.689167]; // caution partner, read on...
// since we are using OSM, we have to transform the coordinates...
var schladmingWebMercator = ol.proj.fromLonLat(schladming);
import Map from 'ol/Map';
import View from 'ol/View';
import TileLayer from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';
import {fromLonLat} from 'ol/proj';
var map = new ol.Map({
const schladming = [47.394167, 13.689167]; // caution partner, read on...
// since we are using OSM, we have to transform the coordinates...
const schladmingWebMercator = fromLonLat(schladming);
const map = new Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
new TileLayer({
source: new OSM()
})
],
target: 'map',
view: new ol.View({
view: new View({
center: schladmingWebMercator,
zoom: 9
})
@@ -219,18 +246,24 @@ e.g. try to change the map center.
Ok, then let's flip the coordinates:
```javascript
var schladming = [13.689167, 47.394167]; // longitude first, then latitude
// since we are using OSM, we have to transform the coordinates...
var schladmingWebMercator = ol.proj.fromLonLat(schladming);
import Map from 'ol/Map';
import View from 'ol/View';
import TileLayer from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';
import {fromLonLat} from 'ol/proj';
var map = new ol.Map({
const schladming = [13.689167, 47.394167]; // longitude first, then latitude
// since we are using OSM, we have to transform the coordinates...
const schladmingWebMercator = fromLonLat(schladming);
const map = new Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
new TileLayer({
source: new OSM()
})
],
target: 'map',
view: new ol.View({
view: new View({
center: schladmingWebMercator,
zoom: 9
})
@@ -244,7 +277,7 @@ first, and then the latitude. This behaviour is the same as we had in OpenLayers
2, and it actually makes sense because of the natural axis order in WGS84.
If you cannot remember the correct order, just have a look at the method name
we used: `ol.proj.fromLonLat`; even there we hint that we expect longitude
we used: `fromLonLat`; even there we hint that we expect longitude
first, and then latitude.
@@ -254,8 +287,11 @@ Suppose you want to load a KML file and display the contained features on the
map. Code like the following could be used:
```javascript
var vector = new ol.layer.Vector({
source: new ol.source.KML({
import VectorLayer from 'ol/layer/Vector';
import KMLSource from 'ol/source/KML';
const vector = new VectorLayer({
source: new KMLSource({
projection: 'EPSG:3857',
url: 'data/kml/2012-02-10.kml'
})
@@ -266,13 +302,16 @@ You may ask yourself how many features are in that KML, and try something like
the following:
```javascript
var vector = new ol.layer.Vector({
source: new ol.source.KML({
import VectorLayer from 'ol/layer/Vector';
import KMLSource from 'ol/source/KML';
const vector = new VectorLayer({
source: new KMLSource({
projection: 'EPSG:3857',
url: 'data/kml/2012-02-10.kml'
})
});
var numFeatures = vector.getSource().getFeatures().length;
const numFeatures = vector.getSource().getFeatures().length;
console.log("Count right after construction: " + numFeatures);
```
@@ -284,9 +323,9 @@ been populated with features), you should use an event listener function on the
```javascript
vector.getSource().on('change', function(evt){
var source = evt.target;
const source = evt.target;
if (source.getState() === 'ready') {
var numFeatures = source.getFeatures().length;
const numFeatures = source.getFeatures().length;
console.log("Count after change: " + numFeatures);
}
});
@@ -315,16 +354,17 @@ map.renderSync();
## Why are my features not found?
You are using `ol.Map#forEachFeatureAtPixel` or `ol.Map#hasFeatureAtPixel`, but
You are using `Map#forEachFeatureAtPixel` or `Map#hasFeatureAtPixel`, but
it sometimes does not work for large icons or labels? The *hit detection* only
checks features that are within a certain distance of the given position. For large
icons, the actual geometry of a feature might be too far away and is not considered.
In this case, set the `renderBuffer` property of `ol.layer.Vector` (the default
value is 100px):
In this case, set the `renderBuffer` property of `VectorLayer` (the default value is 100px):
```javascript
var vectorLayer = new ol.layer.Vector({
import VectorLayer from 'ol/layer/Vector';
const vectorLayer = new VectorLayer({
...
renderBuffer: 200
});

View File

@@ -17,7 +17,7 @@ OpenLayers is available as [`ol` npm package](https://npmjs.com/package/ol), whi
## Renderers and Browser Support
By default, OpenLayers uses a performance optimized Canvas renderer. An experimental WebGL renderer (without text rendering support) is also avaialble.
By default, OpenLayers uses a performance optimized Canvas renderer. An experimental WebGL renderer (without text rendering support) is also available.
OpenLayers runs on all modern browsers that support [HTML5](https://html.spec.whatwg.org/multipage/) and [ECMAScript 5](http://www.ecma-international.org/ecma-262/5.1/). This includes Chrome, Firefox, Safari and Edge. For older browsers and platforms like Internet Explorer (down to version 9) and Android 4.x, [polyfills](http://polyfill.io), the application bundle needs to be transpiled (e.g. using [Babel](https://babeljs.io)) and bundled with polyfills for `requestAnimationFrame`, `Element.prototype.classList` and `URL`.

View File

@@ -1,6 +1,5 @@
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import {defaults as defaultControls} from '../src/ol/control.js';
import TileLayer from '../src/ol/layer/Tile.js';
import OSM from '../src/ol/source/OSM.js';
@@ -12,11 +11,6 @@ const map = new Map({
})
],
target: 'map',
controls: defaultControls({
attributionOptions: {
collapsible: false
}
}),
view: new View({
center: [0, 0],
zoom: 2

View File

@@ -1,6 +1,5 @@
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import {defaults as defaultControls} from '../src/ol/control.js';
import TileLayer from '../src/ol/layer/Tile.js';
import {fromLonLat} from '../src/ol/proj.js';
import {OSM, TileDebug} from '../src/ol/source.js';
@@ -20,11 +19,6 @@ const map = new Map({
})
],
target: 'map',
controls: defaultControls({
attributionOptions: {
collapsible: false
}
}),
view: new View({
center: fromLonLat([-0.1275, 51.507222]),
zoom: 10

View File

@@ -1,6 +1,5 @@
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import {defaults as defaultControls} from '../src/ol/control.js';
import GeoJSON from '../src/ol/format/GeoJSON.js';
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
import {OSM, Vector as VectorSource} from '../src/ol/source.js';
@@ -45,11 +44,6 @@ const map = new Map({
vectorLayer
],
target: 'map',
controls: defaultControls({
attributionOptions: {
collapsible: false
}
}),
view: view
});

View File

@@ -1,4 +1,3 @@
import {inherits} from '../src/ol/util.js';
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import {defaults as defaultControls, Control} from '../src/ol/control.js';
@@ -6,13 +5,6 @@ import TileLayer from '../src/ol/layer/Tile.js';
import OSM from '../src/ol/source/OSM.js';
/**
* Define a namespace for the application.
*/
window.app = {};
const app = window.app;
//
// Define rotate to north control.
//
@@ -23,32 +15,31 @@ const app = window.app;
* @extends {module:ol/control/Control~Control}
* @param {Object=} opt_options Control options.
*/
app.RotateNorthControl = function(opt_options) {
class RotateNorthControl extends Control {
constructor(opt_options) {
const options = opt_options || {};
const button = document.createElement('button');
button.innerHTML = 'N';
const this_ = this;
const handleRotateNorth = function() {
this_.getMap().getView().setRotation(0);
};
button.addEventListener('click', handleRotateNorth, false);
button.addEventListener('touchstart', handleRotateNorth, false);
const element = document.createElement('div');
element.className = 'rotate-north ol-unselectable ol-control';
element.appendChild(button);
Control.call(this, {
super({
element: element,
target: options.target
});
};
inherits(app.RotateNorthControl, Control);
button.addEventListener('click', this.handleRotateNorth.bind(this), false);
}
handleRotateNorth() {
this.getMap().getView().setRotation(0);
}
}
//
@@ -57,12 +48,8 @@ inherits(app.RotateNorthControl, Control);
const map = new Map({
controls: defaultControls({
attributionOptions: {
collapsible: false
}
}).extend([
new app.RotateNorthControl()
controls: defaultControls().extend([
new RotateNorthControl()
]),
layers: [
new TileLayer({

View File

@@ -1,4 +1,3 @@
import {inherits} from '../src/ol/util.js';
import Feature from '../src/ol/Feature.js';
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
@@ -9,23 +8,17 @@ import {TileJSON, Vector as VectorSource} from '../src/ol/source.js';
import {Fill, Icon, Stroke, Style} from '../src/ol/style.js';
/**
* Define a namespace for the application.
*/
const app = {};
/**
* @constructor
* @extends {module:ol/interaction/Pointer}
*/
app.Drag = function() {
PointerInteraction.call(this, {
handleDownEvent: app.Drag.prototype.handleDownEvent,
handleDragEvent: app.Drag.prototype.handleDragEvent,
handleMoveEvent: app.Drag.prototype.handleMoveEvent,
handleUpEvent: app.Drag.prototype.handleUpEvent
class Drag extends PointerInteraction {
constructor() {
super({
handleDownEvent: handleDownEvent,
handleDragEvent: handleDragEvent,
handleMoveEvent: handleMoveEvent,
handleUpEvent: handleUpEvent
});
/**
@@ -51,16 +44,15 @@ app.Drag = function() {
* @private
*/
this.previousCursor_ = undefined;
};
inherits(app.Drag, PointerInteraction);
}
}
/**
* @param {module:ol/MapBrowserEvent~MapBrowserEvent} evt Map browser event.
* @return {boolean} `true` to start the drag sequence.
*/
app.Drag.prototype.handleDownEvent = function(evt) {
function handleDownEvent(evt) {
const map = evt.map;
const feature = map.forEachFeatureAtPixel(evt.pixel,
@@ -74,13 +66,13 @@ app.Drag.prototype.handleDownEvent = function(evt) {
}
return !!feature;
};
}
/**
* @param {module:ol/MapBrowserEvent~MapBrowserEvent} evt Map browser event.
*/
app.Drag.prototype.handleDragEvent = function(evt) {
function handleDragEvent(evt) {
const deltaX = evt.coordinate[0] - this.coordinate_[0];
const deltaY = evt.coordinate[1] - this.coordinate_[1];
@@ -89,13 +81,13 @@ app.Drag.prototype.handleDragEvent = function(evt) {
this.coordinate_[0] = evt.coordinate[0];
this.coordinate_[1] = evt.coordinate[1];
};
}
/**
* @param {module:ol/MapBrowserEvent~MapBrowserEvent} evt Event.
*/
app.Drag.prototype.handleMoveEvent = function(evt) {
function handleMoveEvent(evt) {
if (this.cursor_) {
const map = evt.map;
const feature = map.forEachFeatureAtPixel(evt.pixel,
@@ -113,17 +105,17 @@ app.Drag.prototype.handleMoveEvent = function(evt) {
this.previousCursor_ = undefined;
}
}
};
}
/**
* @return {boolean} `false` to stop the drag sequence.
*/
app.Drag.prototype.handleUpEvent = function() {
function handleUpEvent() {
this.coordinate_ = null;
this.feature_ = null;
return false;
};
}
const pointFeature = new Feature(new Point([0, 0]));
@@ -137,7 +129,7 @@ const polygonFeature = new Feature(
const map = new Map({
interactions: defaultInteractions().extend([new app.Drag()]),
interactions: defaultInteractions().extend([new Drag()]),
layers: [
new TileLayer({
source: new TileJSON({

View File

@@ -8,7 +8,7 @@ docs: >
normalize the events from the browser.
tags: "device, orientation, gyronorm"
resources:
- https://cdn.rawgit.com/dorukeker/gyronorm.js/v2.0.6/dist/gyronorm.complete.min.js
- https://unpkg.com/gyronorm@2.0.6/dist/gyronorm.complete.min.js
---
<div id="map" class="map"></div>
<p>

View File

@@ -1,6 +1,5 @@
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import {defaults as defaultControls} from '../src/ol/control.js';
import TileLayer from '../src/ol/layer/Tile.js';
import {toRadians} from '../src/ol/math.js';
import OSM from '../src/ol/source/OSM.js';
@@ -16,11 +15,6 @@ const map = new Map({
})
],
target: 'map',
controls: defaultControls({
attributionOptions: {
collapsible: false
}
}),
view: view
});

View File

@@ -1,6 +1,5 @@
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import {defaults as defaultControls} from '../src/ol/control.js';
import GeoJSON from '../src/ol/format/GeoJSON.js';
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
import {OSM, Vector as VectorSource} from '../src/ol/source.js';
@@ -18,11 +17,6 @@ const map = new Map({
})
],
target: 'map',
controls: defaultControls({
attributionOptions: {
collapsible: false
}
}),
view: new View({
center: [0, 0],
zoom: 2

View File

@@ -1,6 +1,5 @@
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import {defaults as defaultControls} from '../src/ol/control.js';
import WKT from '../src/ol/format/WKT.js';
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
import {OSM, Vector as VectorSource} from '../src/ol/source.js';
@@ -26,11 +25,6 @@ const vector = new VectorLayer({
const map = new Map({
layers: [raster, vector],
target: 'map',
controls: defaultControls({
attributionOptions: {
collapsible: false
}
}),
view: new View({
center: [0, 0],
zoom: 2

View File

@@ -2,7 +2,6 @@ import Feature from '../src/ol/Feature.js';
import Map from '../src/ol/Map.js';
import {unByKey} from '../src/ol/Observable.js';
import View from '../src/ol/View.js';
import {defaults as defaultControls} from '../src/ol/control.js';
import {easeOut} from '../src/ol/easing.js';
import Point from '../src/ol/geom/Point.js';
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
@@ -19,11 +18,6 @@ const map = new Map({
})
})
],
controls: defaultControls({
attributionOptions: {
collapsible: false
}
}),
target: 'map',
view: new View({
center: [0, 0],

View File

@@ -1,7 +1,6 @@
import Feature from '../src/ol/Feature.js';
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import {defaults as defaultControls} from '../src/ol/control.js';
import GeoJSON from '../src/ol/format/GeoJSON.js';
import Circle from '../src/ol/geom/Circle.js';
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
@@ -174,11 +173,6 @@ const map = new Map({
vectorLayer
],
target: 'map',
controls: defaultControls({
attributionOptions: {
collapsible: false
}
}),
view: new View({
center: [0, 0],
zoom: 2

View File

@@ -2,7 +2,6 @@ import Geolocation from '../src/ol/Geolocation.js';
import Map from '../src/ol/Map.js';
import Overlay from '../src/ol/Overlay.js';
import View from '../src/ol/View.js';
import {defaults as defaultControls} from '../src/ol/control.js';
import LineString from '../src/ol/geom/LineString.js';
import TileLayer from '../src/ol/layer/Tile.js';
import {fromLonLat} from '../src/ol/proj.js';
@@ -22,11 +21,6 @@ const map = new Map({
})
],
target: 'map',
controls: defaultControls({
attributionOptions: {
collapsible: false
}
}),
view: view
});

View File

@@ -2,7 +2,6 @@ import Feature from '../src/ol/Feature.js';
import Geolocation from '../src/ol/Geolocation.js';
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import {defaults as defaultControls} from '../src/ol/control.js';
import Point from '../src/ol/geom/Point.js';
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
import {OSM, Vector as VectorSource} from '../src/ol/source.js';
@@ -20,11 +19,6 @@ const map = new Map({
})
],
target: 'map',
controls: defaultControls({
attributionOptions: {
collapsible: false
}
}),
view: view
});

View File

@@ -1,7 +1,6 @@
import Feature from '../src/ol/Feature.js';
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import {defaults as defaultControls} from '../src/ol/control.js';
import IGC from '../src/ol/format/IGC.js';
import {LineString, Point} from '../src/ol/geom.js';
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
@@ -93,11 +92,6 @@ const map = new Map({
})
],
target: 'map',
controls: defaultControls({
attributionOptions: {
collapsible: false
}
}),
view: new View({
center: [703365.7089403362, 5714629.865071137],
zoom: 9

View File

@@ -7,6 +7,6 @@ docs: >
with OpenLayers.
tags: "vector, jsts, buffer"
resources:
- https://cdn.rawgit.com/bjornharrtell/jsts/gh-pages/1.6.0/jsts.min.js
- https://unpkg.com/jsts@2.0.2/dist/jsts.min.js
---
<div id="map" class="map"></div>

View File

@@ -1,6 +1,5 @@
import Map from '../src/ol/WebGLMap.js';
import View from '../src/ol/View.js';
import {defaults as defaultControls} from '../src/ol/control.js';
import {WEBGL} from '../src/ol/has.js';
import TileLayer from '../src/ol/layer/Tile.js';
import OSM from '../src/ol/source/OSM.js';
@@ -20,11 +19,6 @@ if (!WEBGL) {
const map = new Map({
layers: [osm],
target: 'map',
controls: defaultControls({
attributionOptions: {
collapsible: false
}
}),
view: new View({
center: [0, 0],
zoom: 2

View File

@@ -1,6 +1,5 @@
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import {defaults as defaultControls} from '../src/ol/control.js';
import TileLayer from '../src/ol/layer/Tile.js';
import OSM from '../src/ol/source/OSM.js';
@@ -11,11 +10,6 @@ const osm = new TileLayer({
const map = new Map({
layers: [osm],
target: 'map',
controls: defaultControls({
attributionOptions: {
collapsible: false
}
}),
view: new View({
center: [0, 0],
zoom: 2

View File

@@ -1,6 +1,5 @@
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import {defaults as defaultControls} from '../src/ol/control.js';
import TileLayer from '../src/ol/layer/Tile.js';
import BingMaps from '../src/ol/source/BingMaps.js';
import OSM from '../src/ol/source/OSM.js';
@@ -18,11 +17,6 @@ const bing = new TileLayer({
const map = new Map({
layers: [osm, bing],
target: 'map',
controls: defaultControls({
attributionOptions: {
collapsible: false
}
}),
view: new View({
center: [0, 0],
zoom: 2

View File

@@ -1,6 +1,5 @@
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import {defaults as defaultControls} from '../src/ol/control.js';
import TileLayer from '../src/ol/layer/Tile.js';
import OSM, {ATTRIBUTION} from '../src/ol/source/OSM.js';
@@ -34,11 +33,6 @@ const map = new Map({
openSeaMapLayer
],
target: 'map',
controls: defaultControls({
attributionOptions: {
collapsible: false
}
}),
view: new View({
maxZoom: 18,
center: [-244780.24508882355, 5986452.183179816],

View File

@@ -1,6 +1,5 @@
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import {defaults as defaultControls} from '../src/ol/control.js';
import TileLayer from '../src/ol/layer/Tile.js';
import OSM from '../src/ol/source/OSM.js';
import TileJSON from '../src/ol/source/TileJSON.js';
@@ -26,11 +25,6 @@ const map = new Map({
})
],
target: 'map',
controls: defaultControls({
attributionOptions: {
collapsible: false
}
}),
view: new View({
center: [653600, 5723680],
zoom: 5

View File

@@ -17,11 +17,7 @@ const mousePositionControl = new MousePosition({
});
const map = new Map({
controls: defaultControls({
attributionOptions: {
collapsible: false
}
}).extend([mousePositionControl]),
controls: defaultControls().extend([mousePositionControl]),
layers: [
new TileLayer({
source: new OSM()

View File

@@ -1,6 +1,5 @@
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import {defaults as defaultControls} from '../src/ol/control.js';
import {getBottomLeft, getTopRight} from '../src/ol/extent.js';
import TileLayer from '../src/ol/layer/Tile.js';
import {toLonLat} from '../src/ol/proj.js';
@@ -14,11 +13,6 @@ const map = new Map({
})
],
target: 'map',
controls: defaultControls({
attributionOptions: {
collapsible: false
}
}),
view: new View({
center: [0, 0],
zoom: 2

View File

@@ -6,11 +6,7 @@ import OSM from '../src/ol/source/OSM.js';
const map = new Map({
controls: defaultControls({
attributionOptions: {
collapsible: false
}
}).extend([
controls: defaultControls().extend([
new ZoomToExtent({
extent: [
813079.7791264898, 5929220.284081122,

View File

@@ -1,6 +1,5 @@
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import {defaults as defaultControls} from '../src/ol/control.js';
import TileLayer from '../src/ol/layer/Tile.js';
import OSM from '../src/ol/source/OSM.js';
@@ -29,11 +28,6 @@ const map = new Map({
source: new OSM()
})
],
controls: defaultControls({
attributionOptions: {
collapsible: false
}
}),
target: 'map',
view: new View({
center: center,

View File

@@ -15,8 +15,9 @@ function createMapboxStreetsV6Style(Style, Fill, Stroke, Icon, Text) {
var icon = iconCache[iconName];
if (!icon) {
icon = new Style({image: new Icon({
src: 'https://cdn.rawgit.com/mapbox/maki/master/icons/' + iconName + '-15.svg',
imgSize: [15, 15]
src: 'https://unpkg.com/@mapbox/maki@4.0.0/icons/' + iconName + '-15.svg',
imgSize: [15, 15],
crossOrigin: 'anonymous'
})});
iconCache[iconName] = icon;
}

View File

@@ -1,6 +1,5 @@
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import {defaults as defaultControls} from '../src/ol/control.js';
import TileLayer from '../src/ol/layer/Tile.js';
import OSM from '../src/ol/source/OSM.js';
@@ -12,11 +11,6 @@ const map = new Map({
})
],
target: 'map',
controls: defaultControls({
attributionOptions: {
collapsible: false
}
}),
view: new View({
center: [14200000, 4130000],
rotation: Math.PI / 6,

View File

@@ -8,11 +8,7 @@ import OSM from '../src/ol/source/OSM.js';
const scaleLineControl = new ScaleLine();
const map = new Map({
controls: defaultControls({
attributionOptions: {
collapsible: false
}
}).extend([
controls: defaultControls().extend([
scaleLineControl
]),
layers: [

View File

@@ -53,7 +53,9 @@ const ExampleModify = {
const selectedFeatures = this.select.getFeatures();
this.select.on('change:active', function() {
selectedFeatures.forEach(selectedFeatures.remove, selectedFeatures);
selectedFeatures.forEach(function(each) {
selectedFeatures.remove(each);
});
});
},
setActive: function(active) {

View File

@@ -1,6 +1,5 @@
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import {defaults as defaultControls} from '../src/ol/control.js';
import TileLayer from '../src/ol/layer/Tile.js';
import OSM from '../src/ol/source/OSM.js';
@@ -11,11 +10,6 @@ const map = new Map({
source: new OSM()
})
],
controls: defaultControls({
attributionOptions: {
collapsible: false
}
}),
view: new View({
center: [0, 0],
zoom: 2

View File

@@ -7,7 +7,7 @@ docs: >
with OpenLayers, enabling creating and editing topological geometry. Standard interaction draws edges, snapping to existing edges. Delete an edge by drawing a new edge crossing the one to delete.
tags: "draw, edit, vector, topology, topolis"
resources:
- https://cdn.rawgit.com/bjornharrtell/topolis/releases/0.1.1/topolis.min.js
- https://unpkg.com/topolis@0.2.5/dist/topolis.js
- https://code.jquery.com/jquery-3.1.1.min.js
- https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.3/toastr.min.js
- https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.3/toastr.min.css

View File

@@ -1,6 +1,5 @@
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import {defaults as defaultControls} from '../src/ol/control.js';
import OSMXML from '../src/ol/format/OSMXML.js';
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
import {bbox as bboxStrategy} from '../src/ol/loadingstrategy.js';
@@ -121,11 +120,6 @@ const raster = new TileLayer({
map = new Map({
layers: [raster, vector],
target: document.getElementById('map'),
controls: defaultControls({
attributionOptions: {
collapsible: false
}
}),
view: new View({
center: [739218, 5906096],
maxZoom: 19,

View File

@@ -77,7 +77,7 @@ function getJsSource(chunk, jsName) {
return jsSource;
}
}
if (module.identifier.endsWith(jsName)) {
if (module.identifier.endsWith(jsName) && module.source) {
return module.source;
}
}

View File

@@ -1,6 +1,5 @@
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import {defaults as defaultControls} from '../src/ol/control.js';
import {getWidth} from '../src/ol/extent.js';
import TileLayer from '../src/ol/layer/Tile.js';
import {fromLonLat, get as getProjection} from '../src/ol/proj.js';
@@ -10,11 +9,6 @@ import WMTSTileGrid from '../src/ol/tilegrid/WMTS.js';
const map = new Map({
target: 'map',
controls: defaultControls({
attributionOptions: {
collapsible: false
}
}),
view: new View({
zoom: 5,
center: fromLonLat([5, 45])

View File

@@ -1,6 +1,5 @@
import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import {defaults as defaultControls} from '../src/ol/control.js';
import {getWidth, getTopLeft} from '../src/ol/extent.js';
import TileLayer from '../src/ol/layer/Tile.js';
import {get as getProjection} from '../src/ol/proj.js';
@@ -48,11 +47,6 @@ const map = new Map({
})
],
target: 'map',
controls: defaultControls({
attributionOptions: {
collapsible: false
}
}),
view: new View({
center: [-11158582, 4813697],
zoom: 4

View File

@@ -18,7 +18,7 @@
"build-examples": "webpack --config examples/webpack/config.js --mode production",
"build-package": "npm run transpile && npm run copy-css && node tasks/prepare-package && cp README.md build/ol",
"build-index": "npm run build-package && node tasks/generate-index",
"build-legacy": "rm -rf build && npm run build-index && rollup --config config/rollup.js && cleancss --source-map src/ol/ol.css -o build/ol.css",
"build-legacy": "rm -rf build && npm run build-index && webpack --config config/webpack-config-legacy-build.js && cleancss --source-map src/ol/ol.css -o build/legacy/ol.css",
"copy-css": "cp src/ol/ol.css build/ol/ol.css",
"transpile": "rm -rf build/ol && mkdir -p build && buble --input src/ol --output build/ol --no modules --sourcemap",
"typecheck": "tsc --pretty",
@@ -40,7 +40,9 @@
},
"devDependencies": {
"@openlayers/eslint-plugin": "^4.0.0-beta.1",
"@types/arcgis-rest-api": "^10.4.3",
"@types/geojson": "^7946.0.4",
"@types/rbush": "^2.0.2",
"@types/topojson-specification": "^1.0.0",
"buble": "^0.19.3",
"buble-loader": "^0.5.1",
@@ -51,13 +53,14 @@
"eslint": "5.0.1",
"eslint-config-openlayers": "^11.0.0",
"expect.js": "0.3.1",
"front-matter": "^2.1.2",
"front-matter": "^3.0.0",
"fs-extra": "^7.0.0",
"glob": "^7.1.2",
"handlebars": "4.0.11",
"istanbul": "0.4.5",
"jquery": "3.3.1",
"jsdoc": "3.5.5",
"jsdoc-plugin-typescript": "^1.0.2",
"karma": "^3.0.0",
"karma-chrome-launcher": "2.2.0",
"karma-coverage": "^1.1.1",
@@ -66,23 +69,18 @@
"karma-sauce-launcher": "1.2.0",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "4.0.0-beta.0",
"marked": "0.5.0",
"marked": "0.5.1",
"mocha": "5.2.0",
"mustache": "^2.3.0",
"mustache": "^3.0.0",
"pixelmatch": "^4.0.2",
"proj4": "2.5.0",
"rollup": "0.65.2",
"rollup-plugin-buble": "0.19.2",
"rollup-plugin-commonjs": "9.1.6",
"rollup-plugin-node-resolve": "3.4.0",
"rollup-plugin-sourcemaps": "0.4.2",
"rollup-plugin-uglify": "5.0.2",
"rollup": "0.66.6",
"sinon": "^6.0.0",
"typescript": "^3.1.0-dev.20180905",
"uglifyjs-webpack-plugin": "^1.2.5",
"uglifyjs-webpack-plugin": "^2.0.1",
"url-polyfill": "^1.0.13",
"walk": "^2.3.9",
"webpack": "4.19.0",
"webpack": "4.23.1",
"webpack-cli": "^3.0.8",
"webpack-dev-server": "^3.1.4"
},

View File

@@ -14,7 +14,7 @@ class AssertionError extends Error {
* @param {number} code Error code.
*/
constructor(code) {
const path = VERSION.split('-')[0];
const path = VERSION === 'latest' ? VERSION : 'v' + VERSION.split('-')[0];
const message = 'Assertion failed. See https://openlayers.org/en/' + path +
'/doc/errors/#' + code + ' for details.';

View File

@@ -24,7 +24,7 @@ const Property = {
export class CollectionEvent extends Event {
/**
* @param {import("./CollectionEventType.js").default} type Type.
* @param {CollectionEventType} type Type.
* @param {*=} opt_element Element.
*/
constructor(type, opt_element) {
@@ -56,6 +56,8 @@ export class CollectionEvent extends Event {
* Collection; they trigger events on the appropriate object, not on the
* Collection as a whole.
*
* @fires CollectionEvent
*
* @template T
* @api
*/
@@ -160,7 +162,7 @@ class Collection extends BaseObject {
* @api
*/
getLength() {
return /** @type {number} */ (this.get(Property.LENGTH));
return this.get(Property.LENGTH);
}
/**

View File

@@ -8,13 +8,13 @@
export default {
/**
* Triggered when an item is added to the collection.
* @event module:ol/Collection~CollectionEvent#add
* @event module:ol/Collection.CollectionEvent#add
* @api
*/
ADD: 'add',
/**
* Triggered when an item is removed from the collection.
* @event module:ol/Collection~CollectionEvent#remove
* @event module:ol/Collection.CollectionEvent#remove
* @api
*/
REMOVE: 'remove'

View File

@@ -5,8 +5,14 @@ import {assert} from './asserts.js';
import {listen, unlisten, unlistenByKey} from './events.js';
import EventType from './events/EventType.js';
import BaseObject, {getChangeEventType} from './Object.js';
import Geometry from './geom/Geometry.js';
import Style from './style/Style.js';
/**
* @typedef {typeof Feature|typeof import("./render/Feature.js").default} FeatureClass
*/
/**
* @typedef {Feature|import("./render/Feature.js").default} FeatureLike
*/
/**
* @classdesc
@@ -78,7 +84,7 @@ class Feature extends BaseObject {
/**
* User provided style.
* @private
* @type {import("./style/Style.js").default|Array<import("./style/Style.js").default>|import("./style/Style.js").StyleFunction}
* @type {import("./style/Style.js").StyleLike}
*/
this.style_ = null;
@@ -98,11 +104,9 @@ class Feature extends BaseObject {
this, getChangeEventType(this.geometryName_),
this.handleGeometryChanged_, this);
if (opt_geometryOrProperties !== undefined) {
if (opt_geometryOrProperties instanceof Geometry ||
!opt_geometryOrProperties) {
/** @type {?Geometry} */
const geometry = opt_geometryOrProperties;
if (opt_geometryOrProperties) {
if (typeof /** @type {?} */ (opt_geometryOrProperties).getSimplifiedGeometry === 'function') {
const geometry = /** @type {import("./geom/Geometry.js").default} */ (opt_geometryOrProperties);
this.setGeometry(geometry);
} else {
/** @type {Object<string, *>} */
@@ -171,7 +175,7 @@ class Feature extends BaseObject {
/**
* Get the feature's style. Will return what was provided to the
* {@link module:ol/Feature~Feature#setStyle} method.
* @return {import("./style/Style.js").default|Array<import("./style/Style.js").default>|import("./style/Style.js").StyleFunction} The feature style.
* @return {import("./style/Style.js").StyleLike} The feature style.
* @api
*/
getStyle() {
@@ -226,7 +230,7 @@ class Feature extends BaseObject {
* Set the style for the feature. This can be a single style object, an array
* of styles, or a function that takes a resolution and returns an array of
* styles. If it is `null` the feature has no style (a `null` style).
* @param {import("./style/Style.js").default|Array<import("./style/Style.js").default>|import("./style/Style.js").StyleFunction} style Style for this feature.
* @param {import("./style/Style.js").StyleLike} style Style for this feature.
* @api
* @fires module:ol/events/Event~Event#event:change
*/
@@ -272,9 +276,9 @@ class Feature extends BaseObject {
/**
* Convert the provided object into a feature style function. Functions passed
* through unchanged. Arrays of import("./style/Style.js").default or single style objects wrapped
* through unchanged. Arrays of Style or single style objects wrapped
* in a new feature style function.
* @param {import("./style/Style.js").StyleFunction|!Array<import("./style/Style.js").default>|!import("./style/Style.js").default} obj
* @param {!import("./style/Style.js").StyleFunction|!Array<import("./style/Style.js").default>|!import("./style/Style.js").default} obj
* A feature style function, a single style, or an array of styles.
* @return {import("./style/Style.js").StyleFunction} A style function.
*/
@@ -289,9 +293,10 @@ export function createStyleFunction(obj) {
if (Array.isArray(obj)) {
styles = obj;
} else {
assert(obj instanceof Style,
assert(typeof /** @type {?} */ (obj).getZIndex === 'function',
41); // Expected an `import("./style/Style.js").Style` or an array of `import("./style/Style.js").Style`
styles = [obj];
const style = /** @type {import("./style/Style.js").default} */ (obj);
styles = [style];
}
return function() {
return styles;

View File

@@ -4,6 +4,7 @@
import GeolocationProperty from './GeolocationProperty.js';
import BaseObject, {getChangeEventType} from './Object.js';
import {listen} from './events.js';
import Event from './events/Event.js';
import EventType from './events/EventType.js';
import {circular as circularPolygon} from './geom/Polygon.js';
import {GEOLOCATION} from './has.js';
@@ -11,6 +12,30 @@ import {toRadians} from './math.js';
import {get as getProjection, getTransformFromProjections, identityTransform} from './proj.js';
/**
* @classdesc
* Events emitted on Geolocation error.
*/
class GeolocationError extends Event {
/**
* @param {PositionError} error error object.
*/
constructor(error) {
super(EventType.ERROR);
/**
* @type {number}
*/
this.code = error.code;
/**
* @type {string}
*/
this.message = error.message;
}
}
/**
* @typedef {Object} Options
* @property {boolean} [tracking=false] Start Tracking right after
@@ -174,9 +199,8 @@ class Geolocation extends BaseObject {
* @param {PositionError} error error object.
*/
positionError_(error) {
error.type = EventType.ERROR;
this.setTracking(false);
this.dispatchEvent(/** @type {{type: string, target: undefined}} */ (error));
this.dispatchEvent(new GeolocationError(error));
}
/**

View File

@@ -17,7 +17,7 @@ import Text from './style/Text.js';
/**
* @type {import("./style/Stroke.js").default}
* @type {Stroke}
* @private
* @const
*/
@@ -26,7 +26,6 @@ const DEFAULT_STROKE_STYLE = new Stroke({
});
/**
* TODO can be configurable
* @type {Array<number>}
* @private
*/
@@ -36,7 +35,7 @@ const INTERVALS = [
/**
* @typedef {Object} GraticuleLabelDataType
* @property {import("./geom/Point.js").default} geom
* @property {Point} geom
* @property {string} text
*/
@@ -50,7 +49,7 @@ const INTERVALS = [
* appropriate for conformal projections like Spherical Mercator. If you
* increase the value, more lines will be drawn and the drawing performance will
* decrease.
* @property {import("./style/Stroke.js").default} [strokeStyle='rgba(0,0,0,0.2)'] The
* @property {Stroke} [strokeStyle='rgba(0,0,0,0.2)'] The
* stroke style to use for drawing the graticule. If not provided, a not fully
* opaque black will be used.
* @property {number} [targetSize=100] The target size of the graticule cells,
@@ -71,7 +70,7 @@ const INTERVALS = [
* @property {number} [latLabelPosition=1] Latitude label position in fractions
* (0..1) of view extent. 0 means at the left of the viewport, 1 means at the
* right.
* @property {import("./style/Text.js").default} [lonLabelStyle] Longitude label text
* @property {Text} [lonLabelStyle] Longitude label text
* style. If not provided, the following style will be used:
* ```js
* new Text({
@@ -89,7 +88,7 @@ const INTERVALS = [
* Note that the default's `textBaseline` configuration will not work well for
* `lonLabelPosition` configurations that position labels close to the top of
* the viewport.
* @property {import("./style/Text.js").default} [latLabelStyle] Latitude label text style.
* @property {Text} [latLabelStyle] Latitude label text style.
* If not provided, the following style will be used:
* ```js
* new Text({
@@ -107,6 +106,11 @@ const INTERVALS = [
* Note that the default's `textAlign` configuration will not work well for
* `latLabelPosition` configurations that position labels close to the left of
* the viewport.
* @property {Array<number>} [intervals=[90, 45, 30, 20, 10, 5, 2, 1, 0.5, 0.2, 0.1, 0.05, 0.01, 0.005, 0.002, 0.001]]
* Intervals (in degrees) for the graticule. Example to limit graticules to 30 and 10 degrees intervals:
* ```js
* [30, 10]
* ```
*/
@@ -200,19 +204,19 @@ class Graticule {
this.maxLines_ = options.maxLines !== undefined ? options.maxLines : 100;
/**
* @type {Array<import("./geom/LineString.js").default>}
* @type {Array<LineString>}
* @private
*/
this.meridians_ = [];
/**
* @type {Array<import("./geom/LineString.js").default>}
* @type {Array<LineString>}
* @private
*/
this.parallels_ = [];
/**
* @type {import("./style/Stroke.js").default}
* @type {Stroke}
* @private
*/
this.strokeStyle_ = options.strokeStyle !== undefined ? options.strokeStyle : DEFAULT_STROKE_STYLE;
@@ -282,7 +286,7 @@ class Graticule {
options.latLabelPosition;
/**
* @type {import("./style/Text.js").default}
* @type {Text}
* @private
*/
this.lonLabelStyle_ = options.lonLabelStyle !== undefined ? options.lonLabelStyle :
@@ -299,7 +303,7 @@ class Graticule {
});
/**
* @type {import("./style/Text.js").default}
* @type {Text}
* @private
*/
this.latLabelStyle_ = options.latLabelStyle !== undefined ? options.latLabelStyle :
@@ -319,6 +323,12 @@ class Graticule {
this.parallelsLabels_ = [];
}
/**
* @type {Array<number>}
* @private
*/
this.intervals_ = options.intervals !== undefined ? options.intervals : INTERVALS;
this.setMap(options.map !== undefined ? options.map : null);
}
@@ -348,10 +358,10 @@ class Graticule {
}
/**
* @param {import("./geom/LineString.js").default} lineString Meridian
* @param {LineString} lineString Meridian
* @param {import("./extent.js").Extent} extent Extent.
* @param {number} index Index.
* @return {import("./geom/Point.js").default} Meridian point.
* @return {Point} Meridian point.
* @private
*/
getMeridianPoint_(lineString, extent, index) {
@@ -398,10 +408,10 @@ class Graticule {
}
/**
* @param {import("./geom/LineString.js").default} lineString Parallels.
* @param {LineString} lineString Parallels.
* @param {import("./extent.js").Extent} extent Extent.
* @param {number} index Index.
* @return {import("./geom/Point.js").default} Parallel point.
* @return {Point} Parallel point.
* @private
*/
getParallelPoint_(lineString, extent, index) {
@@ -530,8 +540,8 @@ class Graticule {
const p1 = [];
/** @type {Array<number>} **/
const p2 = [];
for (let i = 0, ii = INTERVALS.length; i < ii; ++i) {
const delta = INTERVALS[i] / 2;
for (let i = 0, ii = this.intervals_.length; i < ii; ++i) {
const delta = this.intervals_[i] / 2;
p1[0] = centerLon - delta;
p1[1] = centerLat - delta;
p2[0] = centerLon + delta;
@@ -542,7 +552,7 @@ class Graticule {
if (dist <= target) {
break;
}
interval = INTERVALS[i];
interval = this.intervals_[i];
}
return interval;
}
@@ -561,7 +571,7 @@ class Graticule {
* @param {number} minLat Minimal latitude.
* @param {number} maxLat Maximal latitude.
* @param {number} squaredTolerance Squared tolerance.
* @return {import("./geom/LineString.js").default} The meridian line string.
* @return {LineString} The meridian line string.
* @param {number} index Index.
* @private
*/
@@ -579,7 +589,7 @@ class Graticule {
/**
* Get the list of meridians. Meridians are lines of equal longitude.
* @return {Array<import("./geom/LineString.js").default>} The meridians.
* @return {Array<LineString>} The meridians.
* @api
*/
getMeridians() {
@@ -591,7 +601,7 @@ class Graticule {
* @param {number} minLon Minimal longitude.
* @param {number} maxLon Maximal longitude.
* @param {number} squaredTolerance Squared tolerance.
* @return {import("./geom/LineString.js").default} The parallel line string.
* @return {LineString} The parallel line string.
* @param {number} index Index.
* @private
*/
@@ -609,7 +619,7 @@ class Graticule {
/**
* Get the list of parallels. Parallels are lines of equal latitude.
* @return {Array<import("./geom/LineString.js").default>} The parallels.
* @return {Array<LineString>} The parallels.
* @api
*/
getParallels() {

View File

@@ -64,7 +64,7 @@ class ImageWrapper extends ImageBase {
/**
* @protected
* @type {import("./ImageState.js").default}
* @type {ImageState}
*/
this.state = ImageState.IDLE;

View File

@@ -1,6 +1,7 @@
/**
* @module ol/ImageBase
*/
import {abstract} from './util.js';
import EventTarget from './events/Target.js';
import EventType from './events/EventType.js';
@@ -63,7 +64,9 @@ class ImageBase extends EventTarget {
* @abstract
* @return {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} Image.
*/
getImage() {}
getImage() {
return abstract();
}
/**
* @return {number} PixelRatio.
@@ -90,7 +93,9 @@ class ImageBase extends EventTarget {
* Load not yet loaded URI.
* @abstract
*/
load() {}
load() {
abstract();
}
}

View File

@@ -11,7 +11,7 @@ import ImageState from './ImageState.js';
* If any error occurs during drawing, the "done" callback should be called with
* that error.
*
* @typedef {function(function(Error))} Loader
* @typedef {function(function(Error=))} Loader
*/
@@ -62,7 +62,7 @@ class ImageCanvas extends ImageBase {
/**
* Handle async drawing complete.
* @param {Error} err Any error during drawing.
* @param {Error=} err Any error during drawing.
* @private
*/
handleLoad_(err) {

View File

@@ -7,17 +7,12 @@ import {createCanvasContext2D} from './dom.js';
import {listenOnce, unlistenByKey} from './events.js';
import EventType from './events/EventType.js';
/**
* @typedef {function(new: ImageTile, import("./tilecoord.js").TileCoord,
* import("./TileState.js").default, string, ?string, import("./Tile.js").LoadFunction)} TileClass
* @api
*/
class ImageTile extends Tile {
/**
* @param {import("./tilecoord.js").TileCoord} tileCoord Tile coordinate.
* @param {import("./TileState.js").default} state State.
* @param {TileState} state State.
* @param {string} src Image source URI.
* @param {?string} crossOrigin Cross origin.
* @param {import("./Tile.js").LoadFunction} tileLoadFunction Tile load function.
@@ -114,7 +109,8 @@ class ImageTile extends Tile {
* @private
*/
handleImageLoad_() {
if (this.image_.naturalWidth && this.image_.naturalHeight) {
const image = /** @type {HTMLImageElement} */ (this.image_);
if (image.naturalWidth && image.naturalHeight) {
this.state = TileState.LOADED;
} else {
this.state = TileState.EMPTY;

View File

@@ -27,10 +27,10 @@ class MapBrowserEventHandler extends EventTarget {
this.map_ = map;
/**
* @type {number}
* @type {any}
* @private
*/
this.clickTimeoutId_ = 0;
this.clickTimeoutId_;
/**
* @type {boolean}
@@ -118,17 +118,17 @@ class MapBrowserEventHandler extends EventTarget {
let newEvent = new MapBrowserPointerEvent(
MapBrowserEventType.CLICK, this.map_, pointerEvent);
this.dispatchEvent(newEvent);
if (this.clickTimeoutId_ !== 0) {
if (this.clickTimeoutId_ !== undefined) {
// double-click
clearTimeout(this.clickTimeoutId_);
this.clickTimeoutId_ = 0;
this.clickTimeoutId_ = undefined;
newEvent = new MapBrowserPointerEvent(
MapBrowserEventType.DBLCLICK, this.map_, pointerEvent);
this.dispatchEvent(newEvent);
} else {
// click
this.clickTimeoutId_ = setTimeout(function() {
this.clickTimeoutId_ = 0;
this.clickTimeoutId_ = undefined;
const newEvent = new MapBrowserPointerEvent(
MapBrowserEventType.SINGLECLICK, this.map_, pointerEvent);
this.dispatchEvent(newEvent);

View File

@@ -8,7 +8,7 @@
export default {
/**
* Triggered when a property is changed.
* @event module:ol/Object~ObjectEvent#propertychange
* @event module:ol/Object.ObjectEvent#propertychange
* @api
*/
PROPERTYCHANGE: 'propertychange'

View File

@@ -22,7 +22,7 @@ import {containsExtent} from './extent.js';
* shifts the overlay down.
* @property {import("./coordinate.js").Coordinate} [position] The overlay position
* in map projection.
* @property {import("./OverlayPositioning.js").default} [positioning='top-left'] Defines how
* @property {OverlayPositioning} [positioning='top-left'] Defines how
* the overlay is actually positioned with respect to its `position` property.
* Possible values are `'bottom-left'`, `'bottom-center'`, `'bottom-right'`,
* `'center-left'`, `'center-center'`, `'center-right'`, `'top-left'`,
@@ -205,7 +205,7 @@ class Overlay extends BaseObject {
this.setOffset(options.offset !== undefined ? options.offset : [0, 0]);
this.setPositioning(options.positioning !== undefined ?
/** @type {import("./OverlayPositioning.js").default} */ (options.positioning) :
/** @type {OverlayPositioning} */ (options.positioning) :
OverlayPositioning.TOP_LEFT);
if (options.position !== undefined) {
@@ -271,14 +271,14 @@ class Overlay extends BaseObject {
/**
* Get the current positioning of this overlay.
* @return {import("./OverlayPositioning.js").default} How the overlay is positioned
* @return {OverlayPositioning} How the overlay is positioned
* relative to its point on the map.
* @observable
* @api
*/
getPositioning() {
return (
/** @type {import("./OverlayPositioning.js").default} */ (this.get(Property.POSITIONING))
/** @type {OverlayPositioning} */ (this.get(Property.POSITIONING))
);
}
@@ -469,7 +469,7 @@ class Overlay extends BaseObject {
/**
* Set the positioning for this overlay.
* @param {import("./OverlayPositioning.js").default} positioning how the overlay is
* @param {OverlayPositioning} positioning how the overlay is
* positioned relative to its point on the map.
* @observable
* @api

View File

@@ -42,7 +42,7 @@ import {create as createTransform, apply as applyTransform} from './transform.js
* @property {null|import("./extent.js").Extent} extent
* @property {import("./coordinate.js").Coordinate} focus
* @property {number} index
* @property {Object<number, import("./layer/Layer.js").State>} layerStates
* @property {Object<string, import("./layer/Layer.js").State>} layerStates
* @property {Array<import("./layer/Layer.js").State>} layerStatesArray
* @property {import("./transform.js").Transform} pixelToCoordinateTransform
* @property {Array<PostRenderFunction>} postRenderFunctions
@@ -88,7 +88,7 @@ import {create as createTransform, apply as applyTransform} from './transform.js
* @typedef {Object} MapOptions
* @property {Collection<import("./control/Control.js").default>|Array<import("./control/Control.js").default>} [controls]
* Controls initially added to the map. If not specified,
* {@link module:ol/control/util~defaults} is used.
* {@link module:ol/control~defaults} is used.
* @property {number} [pixelRatio=window.devicePixelRatio] The ratio between
* physical pixels and device-independent pixels (dips) on the device.
* @property {Collection<import("./interaction/Interaction.js").default>|Array<import("./interaction/Interaction.js").default>} [interactions]
@@ -102,7 +102,7 @@ import {create as createTransform, apply as applyTransform} from './transform.js
* map target (i.e. the user-provided div for the map). If this is not
* `document`, the target element needs to be focused for key events to be
* emitted, requiring that the target element has a `tabindex` attribute.
* @property {Array<import("./layer/Base.js").default>|Collection<import("./layer/Base.js").default>} [layers]
* @property {Array<import("./layer/Base.js").default>|Collection<import("./layer/Base.js").default>|LayerGroup} [layers]
* Layers. If this is not defined, a map with no layers will be rendered. Note
* that layers are rendered in the order supplied, so if you want, for example,
* a vector layer to appear on top of a tile layer, it must come after the tile
@@ -464,6 +464,10 @@ class PluggableMap extends BaseObject {
}
/**
* @abstract
* @return {import("./renderer/Map.js").default} The map renderer
*/
createRenderer() {
throw new Error('Use a map type that has a createRenderer method');
}
@@ -546,7 +550,7 @@ class PluggableMap extends BaseObject {
* callback with each intersecting feature. Layers included in the detection can
* be configured through the `layerFilter` option in `opt_options`.
* @param {import("./pixel.js").Pixel} pixel Pixel.
* @param {function(this: S, (import("./Feature.js").default|import("./render/Feature.js").default),
* @param {function(this: S, import("./Feature.js").FeatureLike,
* import("./layer/Layer.js").default): T} callback Feature callback. The callback will be
* called with two arguments. The first argument is one
* {@link module:ol/Feature feature} or
@@ -565,7 +569,8 @@ class PluggableMap extends BaseObject {
return;
}
const coordinate = this.getCoordinateFromPixel(pixel);
opt_options = opt_options !== undefined ? opt_options : {};
opt_options = opt_options !== undefined ? opt_options :
/** @type {AtPixelOptions} */ ({});
const hitTolerance = opt_options.hitTolerance !== undefined ?
opt_options.hitTolerance * this.frameState_.pixelRatio : 0;
const layerFilter = opt_options.layerFilter !== undefined ?
@@ -579,7 +584,7 @@ class PluggableMap extends BaseObject {
* Get all features that intersect a pixel on the viewport.
* @param {import("./pixel.js").Pixel} pixel Pixel.
* @param {AtPixelOptions=} opt_options Optional options.
* @return {Array<import("./Feature.js").default|import("./render/Feature.js").default>} The detected features or
* @return {Array<import("./Feature.js").FeatureLike>} The detected features or
* `null` if none were found.
* @api
*/
@@ -637,7 +642,8 @@ class PluggableMap extends BaseObject {
return false;
}
const coordinate = this.getCoordinateFromPixel(pixel);
opt_options = opt_options !== undefined ? opt_options : {};
opt_options = opt_options !== undefined ? opt_options :
/** @type {AtPixelOptions} */ ({});
const layerFilter = opt_options.layerFilter !== undefined ? opt_options.layerFilter : TRUE;
const hitTolerance = opt_options.hitTolerance !== undefined ?
opt_options.hitTolerance * this.frameState_.pixelRatio : 0;
@@ -657,13 +663,16 @@ class PluggableMap extends BaseObject {
/**
* Returns the map pixel position for a browser event relative to the viewport.
* @param {Event} event Event.
* @param {Event|TouchEvent} event Event.
* @return {import("./pixel.js").Pixel} Pixel.
* @api
*/
getEventPixel(event) {
const viewportPosition = this.viewport_.getBoundingClientRect();
const eventPosition = event.changedTouches ? event.changedTouches[0] : event;
const eventPosition = 'changedTouches' in event ?
/** @type {TouchEvent} */ (event).changedTouches[0] :
/** @type {MouseEvent} */ (event);
return [
eventPosition.clientX - viewportPosition.left,
eventPosition.clientY - viewportPosition.top
@@ -963,7 +972,7 @@ class PluggableMap extends BaseObject {
tileQueue.loadMoreTiles(maxTotalLoading, maxNewLoads);
}
}
if (frameState && this.hasListener(MapEventType.RENDERCOMPLETE) && !frameState.animate &&
if (frameState && this.hasListener(RenderEventType.RENDERCOMPLETE) && !frameState.animate &&
!this.tileQueue_.getTilesLoading() && !getLoading(this.getLayers().getArray())) {
this.renderer_.dispatchRenderEvent(RenderEventType.RENDERCOMPLETE, frameState);
}
@@ -1295,8 +1304,7 @@ class PluggableMap extends BaseObject {
* @param {import("./Feature.js").default} feature Feature.
*/
skipFeature(feature) {
const featureUid = getUid(feature).toString();
this.skippedFeatureUids_[featureUid] = true;
this.skippedFeatureUids_[getUid(feature)] = true;
this.render();
}
@@ -1331,8 +1339,7 @@ class PluggableMap extends BaseObject {
* @param {import("./Feature.js").default} feature Feature.
*/
unskipFeature(feature) {
const featureUid = getUid(feature).toString();
delete this.skippedFeatureUids_[featureUid];
delete this.skippedFeatureUids_[getUid(feature)];
this.render();
}
}
@@ -1359,8 +1366,8 @@ function createOptionsInternal(options) {
*/
const values = {};
const layerGroup = (options.layers instanceof LayerGroup) ?
options.layers : new LayerGroup({layers: options.layers});
const layerGroup = options.layers && typeof /** @type {?} */ (options.layers).getLayers === 'function' ?
/** @type {LayerGroup} */ (options.layers) : new LayerGroup({layers: /** @type {Collection} */ (options.layers)});
values[MapProperty.LAYERGROUP] = layerGroup;
values[MapProperty.TARGET] = options.target;
@@ -1373,9 +1380,9 @@ function createOptionsInternal(options) {
if (Array.isArray(options.controls)) {
controls = new Collection(options.controls.slice());
} else {
assert(options.controls instanceof Collection,
assert(typeof /** @type {?} */ (options.controls).getArray === 'function',
47); // Expected `controls` to be an array or an `import("./Collection.js").Collection`
controls = options.controls;
controls = /** @type {Collection} */ (options.controls);
}
}
@@ -1384,9 +1391,9 @@ function createOptionsInternal(options) {
if (Array.isArray(options.interactions)) {
interactions = new Collection(options.interactions.slice());
} else {
assert(options.interactions instanceof Collection,
assert(typeof /** @type {?} */ (options.interactions).getArray === 'function',
48); // Expected `interactions` to be an array or an `import("./Collection.js").Collection`
interactions = options.interactions;
interactions = /** @type {Collection} */ (options.interactions);
}
}
@@ -1395,7 +1402,7 @@ function createOptionsInternal(options) {
if (Array.isArray(options.overlays)) {
overlays = new Collection(options.overlays.slice());
} else {
assert(options.overlays instanceof Collection,
assert(typeof /** @type {?} */ (options.overlays).getArray === 'function',
49); // Expected `overlays` to be an array or an `import("./Collection.js").Collection`
overlays = options.overlays;
}
@@ -1421,13 +1428,15 @@ export default PluggableMap;
function getLoading(layers) {
for (let i = 0, ii = layers.length; i < ii; ++i) {
const layer = layers[i];
if (layer instanceof LayerGroup) {
return getLoading(layer.getLayers().getArray());
}
const source = layers[i].getSource();
if (typeof /** @type {?} */ (layer).getLayers === 'function') {
return getLoading(/** @type {LayerGroup} */ (layer).getLayers().getArray());
} else {
const source = /** @type {import("./layer/Layer.js").default} */ (
layer).getSource();
if (source && source.loading) {
return true;
}
}
}
return false;
}

View File

@@ -122,7 +122,7 @@ class Tile extends EventTarget {
/**
* Lookup of start times for rendering transitions. If the start time is
* equal to -1, the transition is complete.
* @type {Object<number, number>}
* @type {Object<string, number>}
*/
this.transitionStarts_ = {};
@@ -180,7 +180,7 @@ class Tile extends EventTarget {
}
let tile = this.interimTile;
let prev = this;
let prev = /** @type {Tile} */ (this);
do {
if (tile.getState() == TileState.LOADED) {
@@ -244,7 +244,7 @@ class Tile extends EventTarget {
/**
* Get the alpha value for rendering.
* @param {number} id An id for the renderer.
* @param {string} id An id for the renderer.
* @param {number} time The render frame time.
* @return {number} A number between 0 and 1.
*/
@@ -272,7 +272,7 @@ class Tile extends EventTarget {
* Determine if a tile is in an alpha transition. A tile is considered in
* transition if tile.getAlpha() has not yet been called or has been called
* and returned 1.
* @param {number} id An id for the renderer.
* @param {string} id An id for the renderer.
* @return {boolean} The tile is in transition.
*/
inTransition(id) {
@@ -284,7 +284,7 @@ class Tile extends EventTarget {
/**
* Mark a transition as complete.
* @param {number} id An id for the renderer.
* @param {string} id An id for the renderer.
*/
endTransition(id) {
if (this.transition_) {

View File

@@ -12,7 +12,6 @@ export default {
/**
* Indicates that tile loading failed
* @type {number}
* @api
*/
ERROR: 3,
EMPTY: 4,

View File

@@ -25,7 +25,7 @@ class VectorImageTile extends Tile {
/**
* @param {import("./tilecoord.js").TileCoord} tileCoord Tile coordinate.
* @param {import("./TileState.js").default} state State.
* @param {TileState} state State.
* @param {number} sourceRevision Source revision.
* @param {import("./format/Feature.js").default} format Feature format.
* @param {import("./Tile.js").LoadFunction} tileLoadFunction Tile load function.
@@ -36,8 +36,7 @@ class VectorImageTile extends Tile {
* @param {Object<string, import("./VectorTile.js").default>} sourceTiles Source tiles.
* @param {number} pixelRatio Pixel ratio.
* @param {import("./proj/Projection.js").default} projection Projection.
* @param {function(new: import("./VectorTile.js").default, import("./tilecoord.js").TileCoord, import("./TileState.js").default, string,
* import("./format/Feature.js").default, import("./Tile.js").LoadFunction)} tileClass Class to
* @param {typeof import("./VectorTile.js").default} tileClass Class to
* instantiate for source tiles.
* @param {function(this: import("./source/VectorTile.js").default, import("./events/Event.js").default)} handleTileChange
* Function to call when a source tile's state changes.
@@ -192,7 +191,7 @@ class VectorImageTile extends Tile {
* @return {CanvasRenderingContext2D} The rendering context.
*/
getContext(layer) {
const key = getUid(layer).toString();
const key = getUid(layer);
if (!(key in this.context_)) {
this.context_[key] = createCanvasContext2D();
}
@@ -214,7 +213,7 @@ class VectorImageTile extends Tile {
* @return {ReplayState} The replay state.
*/
getReplayState(layer) {
const key = getUid(layer).toString();
const key = getUid(layer);
if (!(key in this.replayState_)) {
this.replayState_[key] = {
dirty: false,

View File

@@ -12,12 +12,6 @@ import TileState from './TileState.js';
const DEFAULT_EXTENT = [0, 0, 4096, 4096];
/**
* @typedef {function(new: VectorTile, import("./tilecoord.js").TileCoord,
* TileState, string, ?string, import("./Tile.js").LoadFunction)} TileClass
* @api
*/
class VectorTile extends Tile {
/**
@@ -120,7 +114,7 @@ class VectorTile extends Tile {
/**
* Get the features for this tile. Geometries will be in the projection returned
* by {@link module:ol/VectorTile~VectorTile#getProjection}.
* @return {Array<import("./Feature.js").default|import("./render/Feature.js").default>} Features.
* @return {Array<import("./Feature.js").FeatureLike>} Features.
* @api
*/
getFeatures() {

View File

@@ -17,7 +17,6 @@ import {inAndOut} from './easing.js';
import {getForViewAndSize, getCenter, getHeight, getWidth, isEmpty} from './extent.js';
import GeometryType from './geom/GeometryType.js';
import {fromExtent as polygonFromExtent} from './geom/Polygon.js';
import SimpleGeometry from './geom/SimpleGeometry.js';
import {clamp, modulo} from './math.js';
import {assign} from './obj.js';
import {createProjection, METERS_PER_UNIT} from './proj.js';
@@ -987,9 +986,9 @@ class View extends BaseObject {
}
/** @type {import("./geom/SimpleGeometry.js").default} */
let geometry;
if (!(geometryOrExtent instanceof SimpleGeometry)) {
assert(Array.isArray(geometryOrExtent),
assert(Array.isArray(geometryOrExtent) || typeof /** @type {?} */ (geometryOrExtent).getSimplifiedGeometry === 'function',
24); // Invalid extent or geometry provided as `geometry`
if (Array.isArray(geometryOrExtent)) {
assert(!isEmpty(geometryOrExtent),
25); // Cannot fit empty extent provided as `geometry`
geometry = polygonFromExtent(geometryOrExtent);
@@ -1135,7 +1134,7 @@ class View extends BaseObject {
}
/**
* @param {import("./ViewHint.js").default} hint Hint.
* @param {ViewHint} hint Hint.
* @param {number} delta Delta.
* @return {number} New value.
*/

View File

@@ -133,7 +133,7 @@ export function asArray(color) {
if (Array.isArray(color)) {
return color;
} else {
return fromString(/** @type {string} */ (color));
return fromString(color);
}
}
@@ -185,9 +185,7 @@ function fromStringInternal_(s) {
} else {
assert(false, 14); // Invalid color
}
return (
/** @type {Color} */ (color)
);
return color;
}

View File

@@ -23,22 +23,9 @@ import {toString} from './color.js';
* @api
*/
export function asColorLike(color) {
if (isColorLike(color)) {
return /** @type {string|CanvasPattern|CanvasGradient} */ (color);
if (Array.isArray(color)) {
return toString(color);
} else {
return toString(/** @type {import("./color.js").Color} */ (color));
return color;
}
}
/**
* @param {?} color The value that is potentially an {@link ol/colorlike~ColorLike}.
* @return {boolean} The color is an {@link ol/colorlike~ColorLike}.
*/
export function isColorLike(color) {
return (
typeof color === 'string' ||
color instanceof CanvasPattern ||
color instanceof CanvasGradient
);
}

View File

@@ -5,6 +5,7 @@
export {default as Attribution} from './control/Attribution.js';
export {default as Control} from './control/Control.js';
export {default as FullScreen} from './control/FullScreen.js';
export {default as MousePosition} from './control/MousePosition.js';
export {default as OverviewMap} from './control/OverviewMap.js';
export {default as Rotate} from './control/Rotate.js';
export {default as ScaleLine} from './control/ScaleLine.js';

View File

@@ -16,9 +16,9 @@ import {visibleAtResolution} from '../layer/Layer.js';
* @property {HTMLElement|string} [target] Specify a target if you
* want the control to be rendered outside of the map's
* viewport.
* @property {boolean} [collapsible=true] Specify if attributions can
* be collapsed. If you use an OSM source, should be set to `false` — see
* {@link https://www.openstreetmap.org/copyright OSM Copyright} —
* @property {boolean} [collapsible] Specify if attributions can
* be collapsed. If not specified, sources control this behavior with their
* `attributionsCollapsible` setting.
* @property {boolean} [collapsed=true] Specify if attributions should
* be collapsed at startup.
* @property {string} [tipLabel='Attributions'] Text label to use for the button tip.
@@ -70,6 +70,12 @@ class Attribution extends Control {
*/
this.collapsed_ = options.collapsed !== undefined ? options.collapsed : true;
/**
* @private
* @type {boolean}
*/
this.overrideCollapsible_ = options.collapsible !== undefined;
/**
* @private
* @type {boolean}
@@ -145,12 +151,12 @@ class Attribution extends Control {
}
/**
* Get a list of visible attributions.
* Collect a list of visible attributions and set the collapsible state.
* @param {import("../PluggableMap.js").FrameState} frameState Frame state.
* @return {Array<string>} Attributions.
* @private
*/
getSourceAttributions_(frameState) {
collectSourceAttributions_(frameState) {
/**
* Used to determine if an attribution already exists.
* @type {!Object<string, boolean>}
@@ -171,7 +177,7 @@ class Attribution extends Control {
continue;
}
const source = layerState.layer.getSource();
const source = /** @type {import("../layer/Layer.js").default} */ (layerState.layer).getSource();
if (!source) {
continue;
}
@@ -186,6 +192,10 @@ class Attribution extends Control {
continue;
}
if (!this.overrideCollapsible_ && source.getAttributionsCollapsible() === false) {
this.setCollapsible(false);
}
if (Array.isArray(attributions)) {
for (let j = 0, jj = attributions.length; j < jj; ++j) {
if (!(attributions[j] in lookup)) {
@@ -216,7 +226,7 @@ class Attribution extends Control {
return;
}
const attributions = this.getSourceAttributions_(frameState);
const attributions = this.collectSourceAttributions_(frameState);
const visible = attributions.length > 0;
if (this.renderedVisible_ != visible) {

View File

@@ -34,9 +34,9 @@ const getChangeType = (function() {
/**
* @typedef {Object} Options
* @property {string} [className='ol-full-screen'] CSS class name.
* @property {string|HTMLElement} [label='\u2922'] Text label to use for the button.
* @property {string|Text} [label='\u2922'] Text label to use for the button.
* Instead of text, also an element (e.g. a `span` element) can be used.
* @property {string|HTMLElement} [labelActive='\u00d7'] Text label to use for the
* @property {string|Text} [labelActive='\u00d7'] Text label to use for the
* button when full-screen is active.
* Instead of text, also an element (e.g. a `span` element) can be used.
* @property {string} [tipLabel='Toggle full-screen'] Text label to use for the button tip.
@@ -87,7 +87,7 @@ class FullScreen extends Control {
/**
* @private
* @type {HTMLElement}
* @type {Text}
*/
this.labelNode_ = typeof label === 'string' ?
document.createTextNode(label) : label;
@@ -96,19 +96,24 @@ class FullScreen extends Control {
/**
* @private
* @type {HTMLElement}
* @type {Text}
*/
this.labelActiveNode_ = typeof labelActive === 'string' ?
document.createTextNode(labelActive) : labelActive;
const tipLabel = options.tipLabel ? options.tipLabel : 'Toggle full-screen';
const button = document.createElement('button');
button.className = this.cssClassName_ + '-' + isFullScreen();
button.setAttribute('type', 'button');
button.title = tipLabel;
button.appendChild(this.labelNode_);
/**
* @private
* @type {HTMLElement}
*/
this.button_ = document.createElement('button');
listen(button, EventType.CLICK,
const tipLabel = options.tipLabel ? options.tipLabel : 'Toggle full-screen';
this.setClassName_(this.button_, isFullScreen());
this.button_.setAttribute('type', 'button');
this.button_.title = tipLabel;
this.button_.appendChild(this.labelNode_);
listen(this.button_, EventType.CLICK,
this.handleClick_, this);
const cssClasses = this.cssClassName_ + ' ' + CLASS_UNSELECTABLE +
@@ -116,7 +121,7 @@ class FullScreen extends Control {
(!isFullScreenSupported() ? CLASS_UNSUPPORTED : '');
const element = this.element;
element.className = cssClasses;
element.appendChild(button);
element.appendChild(this.button_);
/**
* @private
@@ -176,13 +181,12 @@ class FullScreen extends Control {
* @private
*/
handleFullScreenChange_() {
const button = this.element.firstElementChild;
const map = this.getMap();
if (isFullScreen()) {
button.className = this.cssClassName_ + '-true';
this.setClassName_(this.button_, true);
replaceNode(this.labelActiveNode_, this.labelNode_);
} else {
button.className = this.cssClassName_ + '-false';
this.setClassName_(this.button_, false);
replaceNode(this.labelNode_, this.labelActiveNode_);
}
if (map) {
@@ -190,6 +194,20 @@ class FullScreen extends Control {
}
}
/**
* @param {HTMLElement} element Target element
* @param {boolean} fullscreen True if fullscreen class name should be active
* @private
*/
setClassName_(element, fullscreen) {
const activeClassName = this.cssClassName_ + '-true';
const inactiveClassName = this.cssClassName_ + '-false';
const nextClassName = fullscreen ? activeClassName : inactiveClassName;
element.classList.remove(activeClassName);
element.classList.remove(inactiveClassName);
element.classList.add(nextClassName);
}
/**
* @inheritDoc
* @api
@@ -253,7 +271,7 @@ function requestFullScreenWithKeys(element) {
if (element.mozRequestFullScreenWithKeys) {
element.mozRequestFullScreenWithKeys();
} else if (element.webkitRequestFullscreen) {
element.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
element.webkitRequestFullscreen();
} else {
requestFullScreen(element);
}

View File

@@ -23,11 +23,11 @@ const COORDINATE_FORMAT = 'coordinateFormat';
* @typedef {Object} Options
* @property {string} [className='ol-mouse-position'] CSS class name.
* @property {import("../coordinate.js").CoordinateFormat} [coordinateFormat] Coordinate format.
* @property {import("../proj.js").ProjectionLike} projection Projection.
* @property {import("../proj.js").ProjectionLike} [projection] Projection. Default is the view projection.
* @property {function(import("../MapEvent.js").default)} [render] Function called when the
* control should be re-rendered. This is called in a `requestAnimationFrame`
* callback.
* @property {Element|string} [target] Specify a target if you want the
* @property {HTMLElement|string} [target] Specify a target if you want the
* control to be rendered outside of the map's viewport.
* @property {string} [undefinedHTML='&#160;'] Markup to show when coordinates are not
* available (e.g. when the pointer leaves the map viewport). By default, the last position

View File

@@ -155,7 +155,7 @@ class OverviewMap extends Control {
const ovmap = this.ovmap_;
if (options.layers) {
options.layers.forEach(
/** @type {Array<import("../layer/Layer.js").default>} */ (options.layers).forEach(
/**
* @param {import("../layer/Layer.js").default} layer Layer.
*/
@@ -204,7 +204,8 @@ class OverviewMap extends Control {
};
const move = function(event) {
const coordinates = ovmap.getEventCoordinate(computeDesiredMousePosition(event));
const position = /** @type {?} */ (computeDesiredMousePosition(event));
const coordinates = ovmap.getEventCoordinate(/** @type {Event} */ (position));
overlay.setPosition(coordinates);
};

View File

@@ -121,22 +121,19 @@ class ScaleLine extends Control {
this, getChangeEventType(UNITS_PROP),
this.handleUnitsChanged_, this);
this.setUnits(/** @type {Units} */ (options.units) ||
Units.METRIC);
this.setUnits(/** @type {Units} */ (options.units) || Units.METRIC);
}
/**
* Return the units to use in the scale line.
* @return {Units|undefined} The units
* @return {Units} The units
* to use in the scale line.
* @observable
* @api
*/
getUnits() {
return (
/** @type {Units|undefined} */ (this.get(UNITS_PROP))
);
return this.get(UNITS_PROP);
}
/**

View File

@@ -5,7 +5,7 @@ import ViewHint from '../ViewHint.js';
import Control from '../control/Control.js';
import {CLASS_CONTROL, CLASS_UNSELECTABLE} from '../css.js';
import {easeOut} from '../easing.js';
import {listen} from '../events.js';
import {listen, unlistenByKey} from '../events.js';
import {stopPropagation} from '../events/Event.js';
import EventType from '../events/EventType.js';
import {clamp} from '../math.js';
@@ -57,6 +57,12 @@ class ZoomSlider extends Control {
render: options.render || render
});
/**
* @type {!Array.<import("../events.js").EventsKey>}
* @private
*/
this.dragListenerKeys_ = [];
/**
* Will hold the current resolution of the view.
*
@@ -133,7 +139,7 @@ class ZoomSlider extends Control {
containerElement.className = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL;
containerElement.appendChild(thumbElement);
/**
* @type {import("../pointer/PointerEventHandler.js").default}
* @type {PointerEventHandler}
* @private
*/
this.dragger_ = new PointerEventHandler(containerElement);
@@ -231,20 +237,31 @@ class ZoomSlider extends Control {
this.previousX_ = event.clientX;
this.previousY_ = event.clientY;
this.dragging_ = true;
if (this.dragListenerKeys_.length === 0) {
const drag = this.handleDraggerDrag_;
const end = this.handleDraggerEnd_;
this.dragListenerKeys_.push(
listen(document, EventType.MOUSEMOVE, drag, this),
listen(document, PointerEventType.POINTERMOVE, drag, this),
listen(document, EventType.MOUSEUP, end, this),
listen(document, PointerEventType.POINTERUP, end, this)
);
}
}
}
/**
* Handle dragger drag events.
*
* @param {import("../pointer/PointerEvent.js").default|Event} event The drag event.
* @param {import("../pointer/PointerEvent.js").default} event The drag event.
* @private
*/
handleDraggerDrag_(event) {
if (this.dragging_) {
const element = /** @type {HTMLElement} */ (this.element.firstElementChild);
const deltaX = event.clientX - this.previousX_ + parseInt(element.style.left, 10);
const deltaY = event.clientY - this.previousY_ + parseInt(element.style.top, 10);
const deltaX = event.clientX - this.previousX_ + parseFloat(element.style.left);
const deltaY = event.clientY - this.previousY_ + parseFloat(element.style.top);
const relativePosition = this.getRelativePosition_(deltaX, deltaY);
this.currentResolution_ = this.getResolutionForPosition_(relativePosition);
this.getMap().getView().setResolution(this.currentResolution_);
@@ -256,7 +273,7 @@ class ZoomSlider extends Control {
/**
* Handle dragger end events.
* @param {import("../pointer/PointerEvent.js").default|Event} event The drag event.
* @param {import("../pointer/PointerEvent.js").default} event The drag event.
* @private
*/
handleDraggerEnd_(event) {
@@ -273,6 +290,8 @@ class ZoomSlider extends Control {
this.dragging_ = false;
this.previousX_ = undefined;
this.previousY_ = undefined;
this.dragListenerKeys_.forEach(unlistenByKey);
this.dragListenerKeys_.length = 0;
}
}

View File

@@ -34,7 +34,7 @@ import Zoom from './Zoom.js';
*
* @param {DefaultsOptions=} opt_options
* Defaults options.
* @return {import("../Collection.js").default<import("./Control.js").default>}
* @return {Collection<import("./Control.js").default>}
* Controls.
* @function module:ol/control.defaults
* @api

View File

@@ -22,7 +22,7 @@ import {clear} from './obj.js';
* Listener function. This function is called with an event object as argument.
* When the function returns `false`, event propagation will stop.
*
* @typedef {function(import("./events/Event.js").default): (void|boolean)} ListenerFunction
* @typedef {function((Event|import("./events/Event.js").default)): (void|boolean)} ListenerFunction
* @api
*/
@@ -78,27 +78,36 @@ export function findListener(listeners, listener, opt_this, opt_setDeleteIndex)
* @return {Array<EventsKey>|undefined} Listeners.
*/
export function getListeners(target, type) {
const listenerMap = target.ol_lm;
const listenerMap = getListenerMap(target);
return listenerMap ? listenerMap[type] : undefined;
}
/**
* Get the lookup of listeners. If one does not exist on the target, it is
* created.
* @param {import("./events/Target.js").EventTargetLike} target Target.
* Get the lookup of listeners.
* @param {Object} target Target.
* @param {boolean=} opt_create If a map should be created if it doesn't exist.
* @return {!Object<string, Array<EventsKey>>} Map of
* listeners by event type.
*/
function getListenerMap(target) {
function getListenerMap(target, opt_create) {
let listenerMap = target.ol_lm;
if (!listenerMap) {
if (!listenerMap && opt_create) {
listenerMap = target.ol_lm = {};
}
return listenerMap;
}
/**
* Remove the listener map from a target.
* @param {Object} target Target.
*/
function removeListenerMap(target) {
delete target.ol_lm;
}
/**
* Clean up all listener objects of the given type. All properties on the
* listener objects will be removed, and if no listeners remain in the listener
@@ -110,15 +119,16 @@ function removeListeners(target, type) {
const listeners = getListeners(target, type);
if (listeners) {
for (let i = 0, ii = listeners.length; i < ii; ++i) {
target.removeEventListener(type, listeners[i].boundListener);
/** @type {import("./events/Target.js").default} */ (target).
removeEventListener(type, listeners[i].boundListener);
clear(listeners[i]);
}
listeners.length = 0;
const listenerMap = target.ol_lm;
const listenerMap = getListenerMap(target);
if (listenerMap) {
delete listenerMap[type];
if (Object.keys(listenerMap).length === 0) {
delete target.ol_lm;
removeListenerMap(target);
}
}
}
@@ -141,7 +151,7 @@ function removeListeners(target, type) {
* @return {EventsKey} Unique key for the listener.
*/
export function listen(target, type, listener, opt_this, opt_once) {
const listenerMap = getListenerMap(target);
const listenerMap = getListenerMap(target, true);
let listeners = listenerMap[type];
if (!listeners) {
listeners = listenerMap[type] = [];
@@ -160,7 +170,8 @@ export function listen(target, type, listener, opt_this, opt_once) {
target: target,
type: type
});
target.addEventListener(type, bindListener(listenerObj));
/** @type {import("./events/Target.js").default} */ (target).
addEventListener(type, bindListener(listenerObj));
listeners.push(listenerObj);
}
@@ -228,7 +239,8 @@ export function unlisten(target, type, listener, opt_this) {
*/
export function unlistenByKey(key) {
if (key && key.target) {
key.target.removeEventListener(key.type, key.boundListener);
/** @type {import("./events/Target.js").default} */ (key.target).
removeEventListener(key.type, key.boundListener);
const listeners = getListeners(key.target, key.type);
if (listeners) {
const i = 'deleteIndex' in key ? key.deleteIndex : listeners.indexOf(key);
@@ -252,7 +264,9 @@ export function unlistenByKey(key) {
*/
export function unlistenAll(target) {
const listenerMap = getListenerMap(target);
if (listenerMap) {
for (const type in listenerMap) {
removeListeners(target, type);
}
}
}

View File

@@ -72,7 +72,8 @@ class Target extends Disposable {
* Object with a `type` property.
*
* @param {{type: string,
* target: (EventTargetLike|undefined)}|
* target: (EventTargetLike|undefined),
* propagationStopped: (boolean|undefined)}|
* import("./Event.js").default|string} event Event object.
* @return {boolean|undefined} `false` if anyone called preventDefault on the
* event object or if any of the listeners returned false.

View File

@@ -24,7 +24,7 @@ import {WEBKIT, MAC} from '../has.js';
* @api
*/
export const altKeyOnly = function(mapBrowserEvent) {
const originalEvent = mapBrowserEvent.originalEvent;
const originalEvent = /** @type {KeyboardEvent|MouseEvent|TouchEvent} */ (mapBrowserEvent.originalEvent);
return (
originalEvent.altKey &&
!(originalEvent.metaKey || originalEvent.ctrlKey) &&
@@ -41,7 +41,7 @@ export const altKeyOnly = function(mapBrowserEvent) {
* @api
*/
export const altShiftKeysOnly = function(mapBrowserEvent) {
const originalEvent = mapBrowserEvent.originalEvent;
const originalEvent = /** @type {KeyboardEvent|MouseEvent|TouchEvent} */ (mapBrowserEvent.originalEvent);
return (
originalEvent.altKey &&
!(originalEvent.metaKey || originalEvent.ctrlKey) &&
@@ -94,7 +94,7 @@ export const click = function(mapBrowserEvent) {
* @return {boolean} The result.
*/
export const mouseActionButton = function(mapBrowserEvent) {
const originalEvent = mapBrowserEvent.originalEvent;
const originalEvent = /** @type {MouseEvent} */ (mapBrowserEvent.originalEvent);
return originalEvent.button == 0 &&
!(WEBKIT && MAC && originalEvent.ctrlKey);
};
@@ -156,7 +156,7 @@ export const doubleClick = function(mapBrowserEvent) {
* @api
*/
export const noModifierKeys = function(mapBrowserEvent) {
const originalEvent = mapBrowserEvent.originalEvent;
const originalEvent = /** @type {KeyboardEvent|MouseEvent|TouchEvent} */ (mapBrowserEvent.originalEvent);
return (
!originalEvent.altKey &&
!(originalEvent.metaKey || originalEvent.ctrlKey) &&
@@ -174,7 +174,7 @@ export const noModifierKeys = function(mapBrowserEvent) {
* @api
*/
export const platformModifierKeyOnly = function(mapBrowserEvent) {
const originalEvent = mapBrowserEvent.originalEvent;
const originalEvent = /** @type {KeyboardEvent|MouseEvent|TouchEvent} */ (mapBrowserEvent.originalEvent);
return !originalEvent.altKey &&
(MAC ? originalEvent.metaKey : originalEvent.ctrlKey) &&
!originalEvent.shiftKey;
@@ -190,7 +190,7 @@ export const platformModifierKeyOnly = function(mapBrowserEvent) {
* @api
*/
export const shiftKeyOnly = function(mapBrowserEvent) {
const originalEvent = mapBrowserEvent.originalEvent;
const originalEvent = /** @type {KeyboardEvent|MouseEvent|TouchEvent} */ (mapBrowserEvent.originalEvent);
return (
!originalEvent.altKey &&
!(originalEvent.metaKey || originalEvent.ctrlKey) &&
@@ -208,7 +208,7 @@ export const shiftKeyOnly = function(mapBrowserEvent) {
*/
export const targetNotEditable = function(mapBrowserEvent) {
const target = mapBrowserEvent.originalEvent.target;
const tagName = target.tagName;
const tagName = /** @type {Element} */ (target).tagName;
return (
tagName !== 'INPUT' &&
tagName !== 'SELECT' &&
@@ -224,11 +224,10 @@ export const targetNotEditable = function(mapBrowserEvent) {
* @api
*/
export const mouseOnly = function(mapBrowserEvent) {
assert(mapBrowserEvent.pointerEvent, 56); // mapBrowserEvent must originate from a pointer event
const pointerEvent = /** @type {import("../MapBrowserPointerEvent").default} */ (mapBrowserEvent).pointerEvent;
assert(pointerEvent !== undefined, 56); // mapBrowserEvent must originate from a pointer event
// see http://www.w3.org/TR/pointerevents/#widl-PointerEvent-pointerType
return (
/** @type {import("../MapBrowserEvent.js").default} */ (mapBrowserEvent).pointerEvent.pointerType == 'mouse'
);
return pointerEvent.pointerType == 'mouse';
};
@@ -242,6 +241,7 @@ export const mouseOnly = function(mapBrowserEvent) {
* @api
*/
export const primaryAction = function(mapBrowserEvent) {
const pointerEvent = mapBrowserEvent.pointerEvent;
const pointerEvent = /** @type {import("../MapBrowserPointerEvent").default} */ (mapBrowserEvent).pointerEvent;
assert(pointerEvent !== undefined, 56); // mapBrowserEvent must originate from a pointer event
return pointerEvent.isPrimary && pointerEvent.button === 0;
};

View File

@@ -165,7 +165,7 @@ export function containsXY(extent, x, y) {
* Get the relationship between a coordinate and extent.
* @param {Extent} extent The extent.
* @param {import("./coordinate.js").Coordinate} coordinate The coordinate.
* @return {import("./extent/Relationship.js").default} The relationship (bitwise compare with
* @return {Relationship} The relationship (bitwise compare with
* import("./extent/Relationship.js").Relationship).
*/
export function coordinateRelationship(extent, coordinate) {
@@ -478,7 +478,7 @@ export function getCenter(extent) {
/**
* Get a corner coordinate of an extent.
* @param {Extent} extent Extent.
* @param {import("./extent/Corner.js").default} corner Corner.
* @param {Corner} corner Corner.
* @return {import("./coordinate.js").Coordinate} Corner coordinate.
*/
export function getCorner(extent, corner) {
@@ -494,9 +494,7 @@ export function getCorner(extent, corner) {
} else {
assert(false, 13); // Invalid corner
}
return (
/** @type {!import("./coordinate.js").Coordinate} */ (coordinate)
);
return coordinate;
}

View File

@@ -4,7 +4,6 @@
import {VOID} from './functions.js';
import FormatType from './format/FormatType.js';
/**
* {@link module:ol/source/Vector} sources use a function of this type to
* load features.
@@ -17,7 +16,7 @@ import FormatType from './format/FormatType.js';
*
* The function is responsible for loading the features and adding them to the
* source.
* @typedef {function(this:import("./source/Vector.js").default, import("./extent.js").Extent, number,
* @typedef {function(this:(import("./source/Vector").default|import("./VectorTile.js").default), import("./extent.js").Extent, number,
* import("./proj/Projection.js").default)} FeatureLoader
* @api
*/
@@ -39,10 +38,10 @@ import FormatType from './format/FormatType.js';
/**
* @param {string|FeatureUrlFunction} url Feature URL service.
* @param {import("./format/Feature.js").default} format Feature format.
* @param {function(this:import("./VectorTile.js").default, Array<import("./Feature.js").default>, import("./proj/Projection.js").default, import("./extent.js").Extent)|function(this:import("./source/Vector.js").default, Array<import("./Feature.js").default>)} success
* @param {function(this:import("./VectorTile.js").default, Array<import("./Feature.js").default>, import("./proj/Projection.js").default, import("./extent.js").Extent)|function(this:import("./source/Vector").default, Array<import("./Feature.js").default>)} success
* Function called with the loaded features and optionally with the data
* projection. Called with the vector tile or source as `this`.
* @param {function(this:import("./VectorTile.js").default)|function(this:import("./source/Vector.js").default)} failure
* @param {function(this:import("./VectorTile.js").default)|function(this:import("./source/Vector").default)} failure
* Function called when loading failed. Called with the vector tile or
* source as `this`.
* @return {FeatureLoader} The feature loader.
@@ -53,7 +52,7 @@ export function loadFeaturesXhr(url, format, success, failure) {
* @param {import("./extent.js").Extent} extent Extent.
* @param {number} resolution Resolution.
* @param {import("./proj/Projection.js").default} projection Projection.
* @this {import("./source/Vector.js").default|import("./VectorTile.js").default}
* @this {import("./source/Vector").default|import("./VectorTile.js").default}
*/
function(extent, resolution, projection) {
const xhr = new XMLHttpRequest();
@@ -121,9 +120,12 @@ export function xhr(url, format) {
* @param {Array<import("./Feature.js").default>} features The loaded features.
* @param {import("./proj/Projection.js").default} dataProjection Data
* projection.
* @this {import("./source/Vector.js").default}
* @this {import("./source/Vector").default|import("./VectorTile.js").default}
*/
function(features, dataProjection) {
this.addFeatures(features);
const sourceOrTile = /** @type {?} */ (this);
if (typeof sourceOrTile.addFeatures === 'function') {
/** @type {import("./source/Vector").default} */ (sourceOrTile).addFeatures(features);
}
}, /* FIXME handle error */ VOID);
}

View File

@@ -17,9 +17,31 @@ import Point from '../geom/Point.js';
import Polygon from '../geom/Polygon.js';
import {deflateCoordinates} from '../geom/flat/deflate.js';
import {linearRingIsClockwise} from '../geom/flat/orient.js';
import {assign, isEmpty} from '../obj.js';
import {isEmpty} from '../obj.js';
import {get as getProjection} from '../proj.js';
/**
* @typedef {import("arcgis-rest-api").Feature} EsriJSONFeature
* @typedef {import("arcgis-rest-api").FeatureSet} EsriJSONFeatureSet
* @typedef {import("arcgis-rest-api").Geometry} EsriJSONGeometry
* @typedef {import("arcgis-rest-api").Point} EsriJSONPoint
* @typedef {import("arcgis-rest-api").Polyline} EsriJSONPolyline
* @typedef {import("arcgis-rest-api").Polygon} EsriJSONPolygon
* @typedef {import("arcgis-rest-api").Multipoint} EsriJSONMultipoint
* @typedef {import("arcgis-rest-api").HasZM} EsriJSONHasZM
* @typedef {import("arcgis-rest-api").Position} EsriJSONPosition
* @typedef {import("arcgis-rest-api").SpatialReferenceWkid} EsriJSONSpatialReferenceWkid
*/
/**
* @typedef {Object} EsriJSONMultiPolygon
* @property {Array<Array<Array<Array<number>>>>} rings Rings for the MultiPolygon.
* @property {boolean} [hasM] If the polygon coordinates have an M value.
* @property {boolean} [hasZ] If the polygon coordinates have a Z value.
* @property {EsriJSONSpatialReferenceWkid} [spatialReference] The coordinate reference system.
*/
/**
* @const
@@ -104,13 +126,12 @@ class EsriJSON extends JSONFeature {
* @inheritDoc
*/
readFeaturesFromObject(object, opt_options) {
const esriJSONObject = /** @type {EsriJSONObject} */ (object);
const options = opt_options ? opt_options : {};
if (esriJSONObject.features) {
const esriJSONFeatureCollection = /** @type {EsriJSONFeatureCollection} */ (object);
if (object['features']) {
const esriJSONFeatureSet = /** @type {EsriJSONFeatureSet} */ (object);
/** @type {Array<import("../Feature.js").default>} */
const features = [];
const esriJSONFeatures = esriJSONFeatureCollection.features;
const esriJSONFeatures = esriJSONFeatureSet.features;
options.idField = object.objectIdFieldName;
for (let i = 0, ii = esriJSONFeatures.length; i < ii; ++i) {
features.push(this.readFeatureFromObject(esriJSONFeatures[i], options));
@@ -132,9 +153,9 @@ class EsriJSON extends JSONFeature {
* @inheritDoc
*/
readProjectionFromObject(object) {
const esriJSONObject = /** @type {EsriJSONObject} */ (object);
if (esriJSONObject.spatialReference && esriJSONObject.spatialReference.wkid) {
const crs = esriJSONObject.spatialReference.wkid;
if (object['spatialReference'] && object['spatialReference']['wkid'] !== undefined) {
const spatialReference = /** @type {EsriJSONSpatialReferenceWkid} */ (object['spatialReference']);
const crs = spatialReference.wkid;
return getProjection('EPSG:' + crs);
} else {
return null;
@@ -170,8 +191,8 @@ class EsriJSON extends JSONFeature {
if (geometry) {
object['geometry'] = writeGeometry(geometry, opt_options);
if (opt_options && opt_options.featureProjection) {
object['geometry']['spatialReference'] = /** @type {EsriJSONCRS} */({
wkid: getProjection(opt_options.featureProjection).getCode().split(':').pop()
object['geometry']['spatialReference'] = /** @type {EsriJSONSpatialReferenceWkid} */({
wkid: Number(getProjection(opt_options.featureProjection).getCode().split(':').pop())
});
}
}
@@ -200,7 +221,7 @@ class EsriJSON extends JSONFeature {
for (let i = 0, ii = features.length; i < ii; ++i) {
objects.push(this.writeFeatureObject(features[i], opt_options));
}
return /** @type {EsriJSONFeatureCollection} */ ({
return /** @type {EsriJSONFeatureSet} */ ({
'features': objects
});
}
@@ -218,26 +239,27 @@ function readGeometry(object, opt_options) {
}
/** @type {import("../geom/GeometryType.js").default} */
let type;
if (typeof object.x === 'number' && typeof object.y === 'number') {
if (typeof object['x'] === 'number' && typeof object['y'] === 'number') {
type = GeometryType.POINT;
} else if (object.points) {
} else if (object['points']) {
type = GeometryType.MULTI_POINT;
} else if (object.paths) {
if (object.paths.length === 1) {
} else if (object['paths']) {
const esriJSONPolyline = /** @type {EsriJSONPolyline} */ (object);
if (esriJSONPolyline.paths.length === 1) {
type = GeometryType.LINE_STRING;
} else {
type = GeometryType.MULTI_LINE_STRING;
}
} else if (object.rings) {
const layout = getGeometryLayout(object);
const rings = convertRings(object.rings, layout);
object = /** @type {EsriJSONGeometry} */(assign({}, object));
} else if (object['rings']) {
const esriJSONPolygon = /** @type {EsriJSONPolygon} */ (object);
const layout = getGeometryLayout(esriJSONPolygon);
const rings = convertRings(esriJSONPolygon.rings, layout);
if (rings.length === 1) {
type = GeometryType.POLYGON;
object.rings = rings[0];
object['rings'] = rings[0];
} else {
type = GeometryType.MULTI_POLYGON;
object.rings = rings;
object['rings'] = rings;
}
}
const geometryReader = GEOMETRY_READERS[type];
@@ -254,7 +276,7 @@ function readGeometry(object, opt_options) {
* Logic inspired by: https://github.com/Esri/terraformer-arcgis-parser
* @param {Array<!Array<!Array<number>>>} rings Rings.
* @param {import("../geom/GeometryLayout.js").default} layout Geometry layout.
* @return {Array<!Array<!Array<number>>>} Transformed rings.
* @return {Array<!Array<!Array<!Array<number>>>>} Transformed rings.
*/
function convertRings(rings, layout) {
const flatRing = [];
@@ -301,7 +323,7 @@ function convertRings(rings, layout) {
/**
* @param {EsriJSONGeometry} object Object.
* @param {EsriJSONPoint} object Object.
* @return {import("../geom/Geometry.js").default} Point.
*/
function readPointGeometry(object) {
@@ -323,7 +345,7 @@ function readPointGeometry(object) {
/**
* @param {EsriJSONGeometry} object Object.
* @param {EsriJSONPolyline} object Object.
* @return {import("../geom/Geometry.js").default} LineString.
*/
function readLineStringGeometry(object) {
@@ -333,7 +355,7 @@ function readLineStringGeometry(object) {
/**
* @param {EsriJSONGeometry} object Object.
* @param {EsriJSONPolyline} object Object.
* @return {import("../geom/Geometry.js").default} MultiLineString.
*/
function readMultiLineStringGeometry(object) {
@@ -343,7 +365,7 @@ function readMultiLineStringGeometry(object) {
/**
* @param {EsriJSONGeometry} object Object.
* @param {EsriJSONHasZM} object Object.
* @return {import("../geom/GeometryLayout.js").default} The geometry layout to use.
*/
function getGeometryLayout(object) {
@@ -360,7 +382,7 @@ function getGeometryLayout(object) {
/**
* @param {EsriJSONGeometry} object Object.
* @param {EsriJSONMultipoint} object Object.
* @return {import("../geom/Geometry.js").default} MultiPoint.
*/
function readMultiPointGeometry(object) {
@@ -370,19 +392,17 @@ function readMultiPointGeometry(object) {
/**
* @param {EsriJSONGeometry} object Object.
* @param {EsriJSONMultiPolygon} object Object.
* @return {import("../geom/Geometry.js").default} MultiPolygon.
*/
function readMultiPolygonGeometry(object) {
const layout = getGeometryLayout(object);
return new MultiPolygon(
/** @type {Array<Array<Array<Array<number>>>>} */(object.rings),
layout);
return new MultiPolygon(object.rings, layout);
}
/**
* @param {EsriJSONGeometry} object Object.
* @param {EsriJSONPolygon} object Object.
* @return {import("../geom/Geometry.js").default} Polygon.
*/
function readPolygonGeometry(object) {
@@ -452,13 +472,14 @@ function getHasZM(geometry) {
* @return {EsriJSONPolyline} EsriJSON geometry.
*/
function writeLineStringGeometry(geometry, opt_options) {
const hasZM = getHasZM(/** @type {import("../geom/LineString.js").default} */(geometry));
const lineString = /** @type {import("../geom/LineString.js").default} */ (geometry);
const hasZM = getHasZM(lineString);
return (
/** @type {EsriJSONPolyline} */ {
hasZ: hasZM.hasZ,
hasM: hasZM.hasM,
paths: [
/** @type {import("../geom/LineString.js").default} */ (geometry).getCoordinates()
/** @type {Array<EsriJSONPosition>} */ (lineString.getCoordinates())
]
}
);
@@ -471,13 +492,14 @@ function writeLineStringGeometry(geometry, opt_options) {
* @return {EsriJSONPolygon} EsriJSON geometry.
*/
function writePolygonGeometry(geometry, opt_options) {
const polygon = /** @type {import("../geom/Polygon.js").default} */ (geometry);
// Esri geometries use the left-hand rule
const hasZM = getHasZM(/** @type {import("../geom/Polygon.js").default} */(geometry));
const hasZM = getHasZM(polygon);
return (
/** @type {EsriJSONPolygon} */ {
hasZ: hasZM.hasZ,
hasM: hasZM.hasM,
rings: /** @type {import("../geom/Polygon.js").default} */ (geometry).getCoordinates(false)
rings: /** @type {Array<Array<EsriJSONPosition>>} */ (polygon.getCoordinates(false))
}
);
}
@@ -489,12 +511,13 @@ function writePolygonGeometry(geometry, opt_options) {
* @return {EsriJSONPolyline} EsriJSON geometry.
*/
function writeMultiLineStringGeometry(geometry, opt_options) {
const hasZM = getHasZM(/** @type {import("../geom/MultiLineString.js").default} */(geometry));
const multiLineString = /** @type {import("../geom/MultiLineString.js").default} */ (geometry);
const hasZM = getHasZM(multiLineString);
return (
/** @type {EsriJSONPolyline} */ {
hasZ: hasZM.hasZ,
hasM: hasZM.hasM,
paths: /** @type {import("../geom/MultiLineString.js").default} */ (geometry).getCoordinates()
paths: /** @type {Array<Array<EsriJSONPosition>>} */ (multiLineString.getCoordinates())
}
);
}
@@ -506,12 +529,13 @@ function writeMultiLineStringGeometry(geometry, opt_options) {
* @return {EsriJSONMultipoint} EsriJSON geometry.
*/
function writeMultiPointGeometry(geometry, opt_options) {
const hasZM = getHasZM(/** @type {import("../geom/MultiPoint.js").default} */(geometry));
const multiPoint = /** @type {import("../geom/MultiPoint.js").default} */ (geometry);
const hasZM = getHasZM(multiPoint);
return (
/** @type {EsriJSONMultipoint} */ {
hasZ: hasZM.hasZ,
hasM: hasZM.hasM,
points: /** @type {import("../geom/MultiPoint.js").default} */ (geometry).getCoordinates()
points: /** @type {Array<EsriJSONPosition>} */ (multiPoint.getCoordinates())
}
);
}

View File

@@ -1,8 +1,8 @@
/**
* @module ol/format/Feature
*/
import Geometry from '../geom/Geometry.js';
import {assign} from '../obj.js';
import {abstract} from '../util.js';
import {get as getProjection, equivalent as equivalentProjection, transformExtent} from '../proj.js';
@@ -123,7 +123,9 @@ class FeatureFormat {
* @abstract
* @return {import("./FormatType.js").default} Format.
*/
getType() {}
getType() {
return abstract();
}
/**
* Read a single feature from a source.
@@ -131,9 +133,11 @@ class FeatureFormat {
* @abstract
* @param {Document|Node|Object|string} source Source.
* @param {ReadOptions=} opt_options Read options.
* @return {import("../Feature.js").default} Feature.
* @return {import("../Feature.js").FeatureLike} Feature.
*/
readFeature(source, opt_options) {}
readFeature(source, opt_options) {
return abstract();
}
/**
* Read all features from a source.
@@ -141,9 +145,11 @@ class FeatureFormat {
* @abstract
* @param {Document|Node|ArrayBuffer|Object|string} source Source.
* @param {ReadOptions=} opt_options Read options.
* @return {Array<import("../Feature.js").default>} Features.
* @return {Array<import("../Feature.js").FeatureLike>} Features.
*/
readFeatures(source, opt_options) {}
readFeatures(source, opt_options) {
return abstract();
}
/**
* Read a single geometry from a source.
@@ -151,9 +157,11 @@ class FeatureFormat {
* @abstract
* @param {Document|Node|Object|string} source Source.
* @param {ReadOptions=} opt_options Read options.
* @return {Geometry} Geometry.
* @return {import("../geom/Geometry.js").default} Geometry.
*/
readGeometry(source, opt_options) {}
readGeometry(source, opt_options) {
return abstract();
}
/**
* Read the projection from a source.
@@ -162,7 +170,9 @@ class FeatureFormat {
* @param {Document|Node|Object|string} source Source.
* @return {import("../proj/Projection.js").default} Projection.
*/
readProjection(source) {}
readProjection(source) {
return abstract();
}
/**
* Encode a feature in this format.
@@ -172,7 +182,9 @@ class FeatureFormat {
* @param {WriteOptions=} opt_options Write options.
* @return {string} Result.
*/
writeFeature(feature, opt_options) {}
writeFeature(feature, opt_options) {
return abstract();
}
/**
* Encode an array of features in this format.
@@ -182,26 +194,30 @@ class FeatureFormat {
* @param {WriteOptions=} opt_options Write options.
* @return {string} Result.
*/
writeFeatures(features, opt_options) {}
writeFeatures(features, opt_options) {
return abstract();
}
/**
* Write a single geometry in this format.
*
* @abstract
* @param {Geometry} geometry Geometry.
* @param {import("../geom/Geometry.js").default} geometry Geometry.
* @param {WriteOptions=} opt_options Write options.
* @return {string} Result.
*/
writeGeometry(geometry, opt_options) {}
writeGeometry(geometry, opt_options) {
return abstract();
}
}
export default FeatureFormat;
/**
* @param {Geometry|import("../extent.js").Extent} geometry Geometry.
* @param {import("../geom/Geometry.js").default|import("../extent.js").Extent} geometry Geometry.
* @param {boolean} write Set to true for writing, false for reading.
* @param {(WriteOptions|ReadOptions)=} opt_options Options.
* @return {Geometry|import("../extent.js").Extent} Transformed geometry.
* @return {import("../geom/Geometry.js").default|import("../extent.js").Extent} Transformed geometry.
*/
export function transformWithOptions(geometry, write, opt_options) {
const featureProjection = opt_options ?
@@ -209,28 +225,29 @@ export function transformWithOptions(geometry, write, opt_options) {
const dataProjection = opt_options ?
getProjection(opt_options.dataProjection) : null;
/**
* @type {Geometry|import("../extent.js").Extent}
* @type {import("../geom/Geometry.js").default|import("../extent.js").Extent}
*/
let transformed;
if (featureProjection && dataProjection &&
!equivalentProjection(featureProjection, dataProjection)) {
if (geometry instanceof Geometry) {
transformed = (write ? geometry.clone() : geometry).transform(
write ? featureProjection : dataProjection,
write ? dataProjection : featureProjection);
} else {
if (Array.isArray(geometry)) {
// FIXME this is necessary because GML treats extents
// as geometries
transformed = transformExtent(
geometry,
dataProjection,
featureProjection);
} else {
transformed = (write ? /** @type {import("../geom/Geometry").default} */ (geometry).clone() : geometry).transform(
write ? featureProjection : dataProjection,
write ? dataProjection : featureProjection);
}
} else {
transformed = geometry;
}
if (write && opt_options && opt_options.decimals !== undefined) {
const power = Math.pow(10, opt_options.decimals);
if (write && opt_options && /** @type {WriteOptions} */ (opt_options).decimals !== undefined &&
!Array.isArray(transformed)) {
const power = Math.pow(10, /** @type {WriteOptions} */ (opt_options).decimals);
// if decimals option on write, round each coordinate appropriately
/**
* @param {Array<number>} coordinates Coordinates.
@@ -243,7 +260,7 @@ export function transformWithOptions(geometry, write, opt_options) {
return coordinates;
};
if (transformed === geometry) {
transformed = transformed.clone();
transformed = /** @type {import("../geom/Geometry").default} */ (geometry).clone();
}
transformed.applyTransform(transform);
}

View File

@@ -5,7 +5,6 @@ import {createOrUpdate} from '../extent.js';
import {transformWithOptions} from '../format/Feature.js';
import GMLBase, {GMLNS} from '../format/GMLBase.js';
import {writeStringTextNode} from '../format/xsd.js';
import Geometry from '../geom/Geometry.js';
import {assign} from '../obj.js';
import {get as getProjection, transformExtent} from '../proj.js';
import {createElementNS, getAllTextContent, makeArrayPusher, makeChildAppender,
@@ -179,7 +178,7 @@ class GML2 extends GMLBase {
writeFeatureElement(node, feature, objectStack) {
const fid = feature.getId();
if (fid) {
node.setAttribute('fid', fid);
node.setAttribute('fid', /** @type {string} */ (fid));
}
const context = /** @type {Object} */ (objectStack[objectStack.length - 1]);
const featureNS = context['featureNS'];
@@ -196,7 +195,7 @@ class GML2 extends GMLBase {
if (value !== null) {
keys.push(key);
values.push(value);
if (key == geometryName || value instanceof Geometry) {
if (key == geometryName || typeof /** @type {?} */ (value).getSimplifiedGeometry === 'function') {
if (!(key in context.serializers[featureNS])) {
context.serializers[featureNS][key] = makeChildAppender(
this.writeGeometryElement, this);
@@ -285,7 +284,7 @@ class GML2 extends GMLBase {
writeGeometryElement(node, geometry, objectStack) {
const context = /** @type {import("./Feature.js").WriteOptions} */ (objectStack[objectStack.length - 1]);
const item = assign({}, context);
item.node = node;
item['node'] = node;
let value;
if (Array.isArray(geometry)) {
if (context.dataProjection) {
@@ -588,9 +587,9 @@ class GML2 extends GMLBase {
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @private
* @protected
*/
GML2.prototype.GEOMETRY_FLAT_COORDINATES_PARSERS_ = {
GML2.prototype.GEOMETRY_FLAT_COORDINATES_PARSERS = {
'http://www.opengis.net/gml': {
'coordinates': makeReplacer(GML2.prototype.readFlatCoordinates_)
}
@@ -599,9 +598,9 @@ GML2.prototype.GEOMETRY_FLAT_COORDINATES_PARSERS_ = {
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @private
* @protected
*/
GML2.prototype.FLAT_LINEAR_RINGS_PARSERS_ = {
GML2.prototype.FLAT_LINEAR_RINGS_PARSERS = {
'http://www.opengis.net/gml': {
'innerBoundaryIs': GML2.prototype.innerBoundaryIsParser_,
'outerBoundaryIs': GML2.prototype.outerBoundaryIsParser_
@@ -623,9 +622,9 @@ GML2.prototype.BOX_PARSERS_ = {
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @private
* @protected
*/
GML2.prototype.GEOMETRY_PARSERS_ = {
GML2.prototype.GEOMETRY_PARSERS = {
'http://www.opengis.net/gml': {
'Point': makeReplacer(GMLBase.prototype.readPoint),
'MultiPoint': makeReplacer(

View File

@@ -6,7 +6,6 @@ import {createOrUpdate} from '../extent.js';
import {transformWithOptions} from '../format/Feature.js';
import GMLBase, {GMLNS} from '../format/GMLBase.js';
import {readNonNegativeIntegerString, writeStringTextNode} from '../format/xsd.js';
import Geometry from '../geom/Geometry.js';
import GeometryLayout from '../geom/GeometryLayout.js';
import LineString from '../geom/LineString.js';
import MultiLineString from '../geom/MultiLineString.js';
@@ -183,7 +182,7 @@ class GML3 extends GMLBase {
*/
readPolygonPatch_(node, objectStack) {
return pushParseAndPop([null],
this.FLAT_LINEAR_RINGS_PARSERS_, node, objectStack, this);
this.FLAT_LINEAR_RINGS_PARSERS, node, objectStack, this);
}
/**
@@ -194,7 +193,7 @@ class GML3 extends GMLBase {
*/
readLineStringSegment_(node, objectStack) {
return pushParseAndPop([null],
this.GEOMETRY_FLAT_COORDINATES_PARSERS_,
this.GEOMETRY_FLAT_COORDINATES_PARSERS,
node, objectStack, this);
}
@@ -357,9 +356,9 @@ class GML3 extends GMLBase {
} else if (node.getAttribute('dimension')) {
dim = readNonNegativeIntegerString(
node.getAttribute('dimension'));
} else if (node.parentNode.getAttribute('srsDimension')) {
} else if (/** @type {Element} */ (node.parentNode).getAttribute('srsDimension')) {
dim = readNonNegativeIntegerString(
node.parentNode.getAttribute('srsDimension'));
/** @type {Element} */ (node.parentNode).getAttribute('srsDimension'));
} else if (contextDimension) {
dim = readNonNegativeIntegerString(contextDimension);
}
@@ -387,7 +386,7 @@ class GML3 extends GMLBase {
writePos_(node, value, objectStack) {
const context = objectStack[objectStack.length - 1];
const hasZ = context['hasZ'];
const srsDimension = hasZ ? 3 : 2;
const srsDimension = hasZ ? '3' : '2';
node.setAttribute('srsDimension', srsDimension);
const srsName = context['srsName'];
let axisOrientation = 'enu';
@@ -443,7 +442,7 @@ class GML3 extends GMLBase {
writePosList_(node, value, objectStack) {
const context = objectStack[objectStack.length - 1];
const hasZ = context['hasZ'];
const srsDimension = hasZ ? 3 : 2;
const srsDimension = hasZ ? '3' : '2';
node.setAttribute('srsDimension', srsDimension);
const srsName = context['srsName'];
// only 2d for simple features profile
@@ -731,7 +730,7 @@ class GML3 extends GMLBase {
writeGeometryElement(node, geometry, objectStack) {
const context = /** @type {import("./Feature.js").WriteOptions} */ (objectStack[objectStack.length - 1]);
const item = assign({}, context);
item.node = node;
item['node'] = node;
let value;
if (Array.isArray(geometry)) {
if (context.dataProjection) {
@@ -757,7 +756,7 @@ class GML3 extends GMLBase {
writeFeatureElement(node, feature, objectStack) {
const fid = feature.getId();
if (fid) {
node.setAttribute('fid', fid);
node.setAttribute('fid', /** @type {string} */ (fid));
}
const context = /** @type {Object} */ (objectStack[objectStack.length - 1]);
const featureNS = context['featureNS'];
@@ -774,7 +773,7 @@ class GML3 extends GMLBase {
if (value !== null) {
keys.push(key);
values.push(value);
if (key == geometryName || value instanceof Geometry) {
if (key == geometryName || typeof /** @type {?} */ (value).getSimplifiedGeometry === 'function') {
if (!(key in context.serializers[featureNS])) {
context.serializers[featureNS][key] = makeChildAppender(
this.writeGeometryElement, this);
@@ -805,6 +804,7 @@ class GML3 extends GMLBase {
const context = /** @type {Object} */ (objectStack[objectStack.length - 1]);
const featureType = context['featureType'];
const featureNS = context['featureNS'];
/** @type {Object<string, Object<string, import("../xml.js").Serializer>>} */
const serializers = {};
serializers[featureNS] = {};
serializers[featureNS][featureType] = makeChildAppender(
@@ -828,7 +828,7 @@ class GML3 extends GMLBase {
*/
MULTIGEOMETRY_MEMBER_NODE_FACTORY_(value, objectStack, opt_nodeName) {
const parentNode = objectStack[objectStack.length - 1].node;
return createElementNS('http://www.opengis.net/gml',
return createElementNS(this.namespace,
MULTIGEOMETRY_TO_MEMBER_NODENAME[parentNode.nodeName]);
}
@@ -861,7 +861,7 @@ class GML3 extends GMLBase {
} else {
nodeName = 'Envelope';
}
return createElementNS('http://www.opengis.net/gml',
return createElementNS(this.namespace,
nodeName);
}
@@ -876,7 +876,7 @@ class GML3 extends GMLBase {
*/
writeGeometryNode(geometry, opt_options) {
opt_options = this.adaptOptions(opt_options);
const geom = createElementNS('http://www.opengis.net/gml', 'geom');
const geom = createElementNS(this.namespace, 'geom');
const context = {node: geom, hasZ: this.hasZ, srsName: this.srsName,
curve: this.curve_, surface: this.surface_,
multiSurface: this.multiSurface_, multiCurve: this.multiCurve_};
@@ -898,7 +898,7 @@ class GML3 extends GMLBase {
*/
writeFeaturesNode(features, opt_options) {
opt_options = this.adaptOptions(opt_options);
const node = createElementNS('http://www.opengis.net/gml', 'featureMembers');
const node = createElementNS(this.namespace, 'featureMembers');
node.setAttributeNS(XML_SCHEMA_INSTANCE_URI, 'xsi:schemaLocation', this.schemaLocation);
const context = {
srsName: this.srsName,
@@ -921,9 +921,9 @@ class GML3 extends GMLBase {
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @private
* @protected
*/
GML3.prototype.GEOMETRY_FLAT_COORDINATES_PARSERS_ = {
GML3.prototype.GEOMETRY_FLAT_COORDINATES_PARSERS = {
'http://www.opengis.net/gml': {
'pos': makeReplacer(GML3.prototype.readFlatPos_),
'posList': makeReplacer(GML3.prototype.readFlatPosList_)
@@ -934,9 +934,9 @@ GML3.prototype.GEOMETRY_FLAT_COORDINATES_PARSERS_ = {
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @private
* @protected
*/
GML3.prototype.FLAT_LINEAR_RINGS_PARSERS_ = {
GML3.prototype.FLAT_LINEAR_RINGS_PARSERS = {
'http://www.opengis.net/gml': {
'interior': GML3.prototype.interiorParser_,
'exterior': GML3.prototype.exteriorParser_
@@ -947,9 +947,9 @@ GML3.prototype.FLAT_LINEAR_RINGS_PARSERS_ = {
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @private
* @protected
*/
GML3.prototype.GEOMETRY_PARSERS_ = {
GML3.prototype.GEOMETRY_PARSERS = {
'http://www.opengis.net/gml': {
'Point': makeReplacer(GMLBase.prototype.readPoint),
'MultiPoint': makeReplacer(

386
src/ol/format/GML32.js Normal file
View File

@@ -0,0 +1,386 @@
/**
* @module ol/format/GML32
*/
import GML3 from './GML3.js';
import GMLBase from './GMLBase.js';
import {makeArrayPusher, makeReplacer, makeChildAppender} from '../xml.js';
import {writeStringTextNode} from '../format/xsd.js';
/**
* @classdesc Feature format for reading and writing data in the GML format
* version 3.2.1.
* @api
*/
class GML32 extends GML3 {
/**
* @param {import("./GMLBase.js").Options=} opt_options Optional configuration object.
*/
constructor(opt_options) {
const options = /** @type {import("./GMLBase.js").Options} */ (opt_options ? opt_options : {});
super(options);
/**
* @inheritDoc
*/
this.schemaLocation = options.schemaLocation ?
options.schemaLocation : this.namespace + ' http://schemas.opengis.net/gml/3.2.1/gml.xsd';
}
}
GML32.prototype.namespace = 'http://www.opengis.net/gml/3.2';
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @protected
*/
GML32.prototype.GEOMETRY_FLAT_COORDINATES_PARSERS = {
'http://www.opengis.net/gml/3.2': {
'pos': makeReplacer(GML3.prototype.readFlatPos_),
'posList': makeReplacer(GML3.prototype.readFlatPosList_)
}
};
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @protected
*/
GML32.prototype.FLAT_LINEAR_RINGS_PARSERS = {
'http://www.opengis.net/gml/3.2': {
'interior': GML3.prototype.interiorParser_,
'exterior': GML3.prototype.exteriorParser_
}
};
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @protected
*/
GML32.prototype.GEOMETRY_PARSERS = {
'http://www.opengis.net/gml/3.2': {
'Point': makeReplacer(GMLBase.prototype.readPoint),
'MultiPoint': makeReplacer(
GMLBase.prototype.readMultiPoint),
'LineString': makeReplacer(
GMLBase.prototype.readLineString),
'MultiLineString': makeReplacer(
GMLBase.prototype.readMultiLineString),
'LinearRing': makeReplacer(
GMLBase.prototype.readLinearRing),
'Polygon': makeReplacer(GMLBase.prototype.readPolygon),
'MultiPolygon': makeReplacer(
GMLBase.prototype.readMultiPolygon),
'Surface': makeReplacer(GML32.prototype.readSurface_),
'MultiSurface': makeReplacer(
GML3.prototype.readMultiSurface_),
'Curve': makeReplacer(GML32.prototype.readCurve_),
'MultiCurve': makeReplacer(
GML3.prototype.readMultiCurve_),
'Envelope': makeReplacer(GML32.prototype.readEnvelope_)
}
};
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @private
*/
GML32.prototype.MULTICURVE_PARSERS_ = {
'http://www.opengis.net/gml/3.2': {
'curveMember': makeArrayPusher(
GML3.prototype.curveMemberParser_),
'curveMembers': makeArrayPusher(
GML3.prototype.curveMemberParser_)
}
};
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @private
*/
GML32.prototype.MULTISURFACE_PARSERS_ = {
'http://www.opengis.net/gml/3.2': {
'surfaceMember': makeArrayPusher(
GML3.prototype.surfaceMemberParser_),
'surfaceMembers': makeArrayPusher(
GML3.prototype.surfaceMemberParser_)
}
};
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @private
*/
GML32.prototype.CURVEMEMBER_PARSERS_ = {
'http://www.opengis.net/gml/3.2': {
'LineString': makeArrayPusher(
GMLBase.prototype.readLineString),
'Curve': makeArrayPusher(GML3.prototype.readCurve_)
}
};
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @private
*/
GML32.prototype.SURFACEMEMBER_PARSERS_ = {
'http://www.opengis.net/gml/3.2': {
'Polygon': makeArrayPusher(GMLBase.prototype.readPolygon),
'Surface': makeArrayPusher(GML3.prototype.readSurface_)
}
};
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @private
*/
GML32.prototype.SURFACE_PARSERS_ = {
'http://www.opengis.net/gml/3.2': {
'patches': makeReplacer(GML3.prototype.readPatch_)
}
};
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @private
*/
GML32.prototype.CURVE_PARSERS_ = {
'http://www.opengis.net/gml/3.2': {
'segments': makeReplacer(GML3.prototype.readSegment_)
}
};
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @private
*/
GML32.prototype.ENVELOPE_PARSERS_ = {
'http://www.opengis.net/gml/3.2': {
'lowerCorner': makeArrayPusher(
GML3.prototype.readFlatPosList_),
'upperCorner': makeArrayPusher(
GML3.prototype.readFlatPosList_)
}
};
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @private
*/
GML32.prototype.PATCHES_PARSERS_ = {
'http://www.opengis.net/gml/3.2': {
'PolygonPatch': makeReplacer(
GML3.prototype.readPolygonPatch_)
}
};
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @private
*/
GML32.prototype.SEGMENTS_PARSERS_ = {
'http://www.opengis.net/gml/3.2': {
'LineStringSegment': makeReplacer(
GML3.prototype.readLineStringSegment_)
}
};
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @private
*/
GML32.prototype.MULTIPOINT_PARSERS_ = {
'http://www.opengis.net/gml/3.2': {
'pointMember': makeArrayPusher(
GMLBase.prototype.pointMemberParser_),
'pointMembers': makeArrayPusher(
GMLBase.prototype.pointMemberParser_)
}
};
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @private
*/
GML32.prototype.MULTILINESTRING_PARSERS_ = {
'http://www.opengis.net/gml/3.2': {
'lineStringMember': makeArrayPusher(
GMLBase.prototype.lineStringMemberParser_),
'lineStringMembers': makeArrayPusher(
GMLBase.prototype.lineStringMemberParser_)
}
};
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @private
*/
GML32.prototype.MULTIPOLYGON_PARSERS_ = {
'http://www.opengis.net/gml/3.2': {
'polygonMember': makeArrayPusher(
GMLBase.prototype.polygonMemberParser_),
'polygonMembers': makeArrayPusher(
GMLBase.prototype.polygonMemberParser_)
}
};
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @private
*/
GML32.prototype.POINTMEMBER_PARSERS_ = {
'http://www.opengis.net/gml/3.2': {
'Point': makeArrayPusher(
GMLBase.prototype.readFlatCoordinatesFromNode_)
}
};
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @private
*/
GML32.prototype.LINESTRINGMEMBER_PARSERS_ = {
'http://www.opengis.net/gml/3.2': {
'LineString': makeArrayPusher(
GMLBase.prototype.readLineString)
}
};
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @private
*/
GML32.prototype.POLYGONMEMBER_PARSERS_ = {
'http://www.opengis.net/gml/3.2': {
'Polygon': makeArrayPusher(
GMLBase.prototype.readPolygon)
}
};
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @protected
*/
GML32.prototype.RING_PARSERS = {
'http://www.opengis.net/gml/3.2': {
'LinearRing': makeReplacer(
GMLBase.prototype.readFlatLinearRing_)
}
};
/**
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
* @private
*/
GML32.prototype.RING_SERIALIZERS_ = {
'http://www.opengis.net/gml/3.2': {
'exterior': makeChildAppender(GML3.prototype.writeRing_),
'interior': makeChildAppender(GML3.prototype.writeRing_)
}
};
/**
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
* @private
*/
GML32.prototype.ENVELOPE_SERIALIZERS_ = {
'http://www.opengis.net/gml/3.2': {
'lowerCorner': makeChildAppender(writeStringTextNode),
'upperCorner': makeChildAppender(writeStringTextNode)
}
};
/**
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
* @private
*/
GML32.prototype.SURFACEORPOLYGONMEMBER_SERIALIZERS_ = {
'http://www.opengis.net/gml/3.2': {
'surfaceMember': makeChildAppender(
GML3.prototype.writeSurfaceOrPolygonMember_),
'polygonMember': makeChildAppender(
GML3.prototype.writeSurfaceOrPolygonMember_)
}
};
/**
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
* @private
*/
GML32.prototype.POINTMEMBER_SERIALIZERS_ = {
'http://www.opengis.net/gml/3.2': {
'pointMember': makeChildAppender(
GML3.prototype.writePointMember_)
}
};
/**
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
* @private
*/
GML32.prototype.LINESTRINGORCURVEMEMBER_SERIALIZERS_ = {
'http://www.opengis.net/gml/3.2': {
'lineStringMember': makeChildAppender(
GML3.prototype.writeLineStringOrCurveMember_),
'curveMember': makeChildAppender(
GML3.prototype.writeLineStringOrCurveMember_)
}
};
/**
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
* @private
*/
GML32.prototype.GEOMETRY_SERIALIZERS_ = {
'http://www.opengis.net/gml/3.2': {
'Curve': makeChildAppender(
GML3.prototype.writeCurveOrLineString_),
'MultiCurve': makeChildAppender(
GML3.prototype.writeMultiCurveOrLineString_),
'Point': makeChildAppender(GML32.prototype.writePoint_),
'MultiPoint': makeChildAppender(
GML3.prototype.writeMultiPoint_),
'LineString': makeChildAppender(
GML3.prototype.writeCurveOrLineString_),
'MultiLineString': makeChildAppender(
GML3.prototype.writeMultiCurveOrLineString_),
'LinearRing': makeChildAppender(
GML3.prototype.writeLinearRing_),
'Polygon': makeChildAppender(
GML3.prototype.writeSurfaceOrPolygon_),
'MultiPolygon': makeChildAppender(
GML3.prototype.writeMultiSurfaceOrPolygon_),
'Surface': makeChildAppender(
GML3.prototype.writeSurfaceOrPolygon_),
'MultiSurface': makeChildAppender(
GML3.prototype.writeMultiSurfaceOrPolygon_),
'Envelope': makeChildAppender(
GML3.prototype.writeEnvelope)
}
};
export default GML32;

View File

@@ -71,6 +71,7 @@ const ONLY_WHITESPACE_RE = /^[\s\xa0]*$/;
* gml:MultiPolygon. Since the latter is deprecated in GML 3.
* @property {string} [schemaLocation] Optional schemaLocation to use when
* writing out the GML, this will override the default provided.
* @property {boolean} [hasZ=false] If coordinates have a Z value.
*/
@@ -122,11 +123,10 @@ class GMLBase extends XMLFeature {
* @type {Object<string, Object<string, Object>>}
*/
this.FEATURE_COLLECTION_PARSERS = {};
this.FEATURE_COLLECTION_PARSERS[GMLNS] = {
'featureMember': makeReplacer(this.readFeaturesInternal),
this.FEATURE_COLLECTION_PARSERS[this.namespace] = {
'featureMember': makeArrayPusher(this.readFeaturesInternal),
'featureMembers': makeReplacer(this.readFeaturesInternal)
};
}
/**
@@ -138,15 +138,9 @@ class GMLBase extends XMLFeature {
const localName = node.localName;
let features = null;
if (localName == 'FeatureCollection') {
if (node.namespaceURI === 'http://www.opengis.net/wfs') {
features = pushParseAndPop([],
this.FEATURE_COLLECTION_PARSERS, node,
objectStack, this);
} else {
features = pushParseAndPop(null,
this.FEATURE_COLLECTION_PARSERS, node,
objectStack, this);
}
} else if (localName == 'featureMembers' || localName == 'featureMember') {
const context = objectStack[0];
let featureType = context['featureType'];
@@ -189,9 +183,11 @@ class GMLBase extends XMLFeature {
featureNS = {};
featureNS[defaultPrefix] = ns;
}
/** @type {Object<string, Object<string, import("../xml.js").Parser>>} */
const parsersNS = {};
const featureTypes = Array.isArray(featureType) ? featureType : [featureType];
for (const p in featureNS) {
/** @type {Object<string, import("../xml.js").Parser>} */
const parsers = {};
for (let i = 0, ii = featureTypes.length; i < ii; ++i) {
const featurePrefix = featureTypes[i].indexOf(':') === -1 ?
@@ -227,7 +223,7 @@ class GMLBase extends XMLFeature {
context['srsName'] = node.firstElementChild.getAttribute('srsName');
context['srsDimension'] = node.firstElementChild.getAttribute('srsDimension');
/** @type {import("../geom/Geometry.js").default} */
const geometry = pushParseAndPop(null, this.GEOMETRY_PARSERS_, node, objectStack, this);
const geometry = pushParseAndPop(null, this.GEOMETRY_PARSERS, node, objectStack, this);
if (geometry) {
return (
/** @type {import("../geom/Geometry.js").default} */ (transformWithOptions(geometry, false, context))
@@ -240,43 +236,78 @@ class GMLBase extends XMLFeature {
/**
* @param {Element} node Node.
* @param {Array<*>} objectStack Object stack.
* @return {Feature} Feature.
* @param {boolean} asFeature whether result should be wrapped as a feature.
* @return {Feature|Object} Feature
*/
readFeatureElement(node, objectStack) {
let n;
const fid = node.getAttribute('fid') || getAttributeNS(node, GMLNS, 'id');
const values = {};
readFeatureElementInternal(node, objectStack, asFeature) {
let geometryName;
for (n = node.firstElementChild; n; n = n.nextElementSibling) {
const values = {};
for (let n = node.firstElementChild; n; n = n.nextElementSibling) {
let value;
const localName = n.localName;
// Assume attribute elements have one child node and that the child
// is a text or CDATA node (to be treated as text).
// Otherwise assume it is a geometry node.
if (n.childNodes.length === 0 ||
(n.childNodes.length === 1 &&
(n.firstChild.nodeType === 3 || n.firstChild.nodeType === 4))) {
let value = getAllTextContent(n, false);
// first, check if it is simple attribute
if (n.childNodes.length === 0
|| (n.childNodes.length === 1 && (n.firstChild.nodeType === 3 || n.firstChild.nodeType === 4))) {
value = getAllTextContent(n, false);
if (ONLY_WHITESPACE_RE.test(value)) {
value = undefined;
}
values[localName] = value;
} else {
if (asFeature) {
//if feature, try it as a geometry
value = this.readGeometryElement(n, objectStack);
}
if (!value) { //if not a geometry or not a feature, treat it as a complex attribute
value = this.readFeatureElementInternal(n, objectStack, false);
} else if (localName !== 'boundedBy') {
// boundedBy is an extent and must not be considered as a geometry
if (localName !== 'boundedBy') {
geometryName = localName;
}
values[localName] = this.readGeometryElement(n, objectStack);
}
if (values[localName]) {
if (!(values[localName] instanceof Array)) {
values[localName] = [values[localName]];
}
values[localName].push(value);
} else {
values[localName] = value;
}
const len = n.attributes.length;
if (len > 0) {
values[localName] = {_content_: values[localName]};
for (let i = 0; i < len; i++) {
const attName = n.attributes[i].name;
values[localName][attName] = n.attributes[i].value;
}
}
}
if (!asFeature) {
return values;
} else {
const feature = new Feature(values);
if (geometryName) {
feature.setGeometryName(geometryName);
}
const fid = node.getAttribute('fid') ||
getAttributeNS(node, this.namespace, 'id');
if (fid) {
feature.setId(fid);
}
return feature;
}
}
/**
* @param {Element} node Node.
* @param {Array<*>} objectStack Object stack.
* @return {Feature} Feature.
*/
readFeatureElement(node, objectStack) {
return this.readFeatureElementInternal(node, objectStack, true);
}
/**
* @param {Element} node Node.
@@ -383,7 +414,7 @@ class GMLBase extends XMLFeature {
*/
readFlatLinearRing_(node, objectStack) {
const ring = pushParseAndPop(null,
this.GEOMETRY_FLAT_COORDINATES_PARSERS_, node,
this.GEOMETRY_FLAT_COORDINATES_PARSERS, node,
objectStack, this);
if (ring) {
return ring;
@@ -412,7 +443,7 @@ class GMLBase extends XMLFeature {
readPolygon(node, objectStack) {
/** @type {Array<Array<number>>} */
const flatLinearRings = pushParseAndPop([null],
this.FLAT_LINEAR_RINGS_PARSERS_, node, objectStack, this);
this.FLAT_LINEAR_RINGS_PARSERS, node, objectStack, this);
if (flatLinearRings && flatLinearRings[0]) {
const flatCoordinates = flatLinearRings[0];
const ends = [flatCoordinates.length];
@@ -434,7 +465,7 @@ class GMLBase extends XMLFeature {
* @return {Array<number>} Flat coordinates.
*/
readFlatCoordinatesFromNode_(node, objectStack) {
return pushParseAndPop(null, this.GEOMETRY_FLAT_COORDINATES_PARSERS_, node, objectStack, this);
return pushParseAndPop(null, this.GEOMETRY_FLAT_COORDINATES_PARSERS, node, objectStack, this);
}
/**
@@ -469,6 +500,40 @@ class GMLBase extends XMLFeature {
}
}
GMLBase.prototype.namespace = GMLNS;
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @protected
*/
GMLBase.prototype.FLAT_LINEAR_RINGS_PARSERS = {
'http://www.opengis.net/gml': {}
};
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @protected
*/
GMLBase.prototype.GEOMETRY_FLAT_COORDINATES_PARSERS = {
'http://www.opengis.net/gml': {}
};
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
* @protected
*/
GMLBase.prototype.GEOMETRY_PARSERS = {
'http://www.opengis.net/gml': {}
};
/**
* @const
* @type {Object<string, Object<string, import("../xml.js").Parser>>}

View File

@@ -7,6 +7,7 @@ import {transformWithOptions} from '../format/Feature.js';
import XMLFeature from '../format/XMLFeature.js';
import {readString, readDecimal, readNonNegativeInteger, readDateTime, writeStringTextNode, writeNonNegativeIntegerTextNode, writeDecimalTextNode, writeDateTimeTextNode} from '../format/xsd.js';
import GeometryLayout from '../geom/GeometryLayout.js';
import GeometryType from '../geom/GeometryType.js';
import LineString from '../geom/LineString.js';
import MultiLineString from '../geom/MultiLineString.js';
import Point from '../geom/Point.js';
@@ -738,8 +739,8 @@ function writeWptType(node, coordinate, objectStack) {
const namespaceURI = parentNode.namespaceURI;
const properties = context['properties'];
//FIXME Projection handling
node.setAttributeNS(null, 'lat', coordinate[1]);
node.setAttributeNS(null, 'lon', coordinate[0]);
node.setAttributeNS(null, 'lat', String(coordinate[1]));
node.setAttributeNS(null, 'lon', String(coordinate[0]));
const geometryLayout = context['geometryLayout'];
switch (geometryLayout) {
case GeometryLayout.XYZM:
@@ -779,12 +780,13 @@ function writeWptType(node, coordinate, objectStack) {
function writeRte(node, feature, objectStack) {
const options = /** @type {import("./Feature.js").WriteOptions} */ (objectStack[0]);
const properties = feature.getProperties();
const context = {node: node, 'properties': properties};
let geometry = feature.getGeometry();
if (geometry) {
geometry = /** @type {LineString} */ (transformWithOptions(geometry, true, options));
context['geometryLayout'] = geometry.getLayout();
properties['rtept'] = geometry.getCoordinates();
const context = {node: node};
context['properties'] = properties;
const geometry = feature.getGeometry();
if (geometry.getType() == GeometryType.LINE_STRING) {
const lineString = /** @type {LineString} */ (transformWithOptions(geometry, true, options));
context['geometryLayout'] = lineString.getLayout();
properties['rtept'] = lineString.getCoordinates();
}
const parentNode = objectStack[objectStack.length - 1].node;
const orderedKeys = RTE_SEQUENCE[parentNode.namespaceURI];
@@ -804,12 +806,12 @@ function writeTrk(node, feature, objectStack) {
const options = /** @type {import("./Feature.js").WriteOptions} */ (objectStack[0]);
const properties = feature.getProperties();
/** @type {import("../xml.js").NodeStackItem} */
const context = {node: node, 'properties': properties};
let geometry = feature.getGeometry();
if (geometry) {
geometry = /** @type {MultiLineString} */
(transformWithOptions(geometry, true, options));
properties['trkseg'] = geometry.getLineStrings();
const context = {node: node};
context['properties'] = properties;
const geometry = feature.getGeometry();
if (geometry.getType() == GeometryType.MULTI_LINE_STRING) {
const multiLineString = /** @type {MultiLineString} */ (transformWithOptions(geometry, true, options));
properties['trkseg'] = multiLineString.getLineStrings();
}
const parentNode = objectStack[objectStack.length - 1].node;
const orderedKeys = TRK_SEQUENCE[parentNode.namespaceURI];
@@ -827,8 +829,9 @@ function writeTrk(node, feature, objectStack) {
*/
function writeTrkSeg(node, lineString, objectStack) {
/** @type {import("../xml.js").NodeStackItem} */
const context = {node: node, 'geometryLayout': lineString.getLayout(),
'properties': {}};
const context = {node: node};
context['geometryLayout'] = lineString.getLayout();
context['properties'] = {};
pushSerializeAndPop(context,
TRKSEG_SERIALIZERS, TRKSEG_NODE_FACTORY,
lineString.getCoordinates(), objectStack);
@@ -844,12 +847,11 @@ function writeWpt(node, feature, objectStack) {
const options = /** @type {import("./Feature.js").WriteOptions} */ (objectStack[0]);
const context = objectStack[objectStack.length - 1];
context['properties'] = feature.getProperties();
let geometry = feature.getGeometry();
if (geometry) {
geometry = /** @type {Point} */
(transformWithOptions(geometry, true, options));
context['geometryLayout'] = geometry.getLayout();
writeWptType(node, geometry.getCoordinates(), objectStack);
const geometry = feature.getGeometry();
if (geometry.getType() == GeometryType.POINT) {
const point = /** @type {Point} */ (transformWithOptions(geometry, true, options));
context['geometryLayout'] = point.getLayout();
writeWptType(node, point.getCoordinates(), objectStack);
}
}

View File

@@ -293,14 +293,14 @@ function readGeometry(object, opt_options) {
throw new Error('Unsupported GeoJSON type: ' + object.type);
}
}
return transformWithOptions(geometry, false, opt_options);
return /** @type {import("../geom/Geometry.js").default} */ (transformWithOptions(geometry, false, opt_options));
}
/**
* @param {GeoJSONGeometryCollection} object Object.
* @param {import("./Feature.js").ReadOptions=} opt_options Read options.
* @return {import("../geom/GeometryCollection.js").default} Geometry collection.
* @return {GeometryCollection} Geometry collection.
*/
function readGeometryCollectionGeometry(object, opt_options) {
const geometries = object['geometries'].map(
@@ -317,7 +317,7 @@ function readGeometryCollectionGeometry(object, opt_options) {
/**
* @param {GeoJSONPoint} object Object.
* @return {import("../geom/Point.js").default} Point.
* @return {Point} Point.
*/
function readPointGeometry(object) {
return new Point(object['coordinates']);
@@ -326,7 +326,7 @@ function readPointGeometry(object) {
/**
* @param {GeoJSONLineString} object Object.
* @return {import("../geom/LineString.js").default} LineString.
* @return {LineString} LineString.
*/
function readLineStringGeometry(object) {
return new LineString(object['coordinates']);
@@ -335,7 +335,7 @@ function readLineStringGeometry(object) {
/**
* @param {GeoJSONMultiLineString} object Object.
* @return {import("../geom/MultiLineString.js").default} MultiLineString.
* @return {MultiLineString} MultiLineString.
*/
function readMultiLineStringGeometry(object) {
return new MultiLineString(object['coordinates']);
@@ -344,7 +344,7 @@ function readMultiLineStringGeometry(object) {
/**
* @param {GeoJSONMultiPoint} object Object.
* @return {import("../geom/MultiPoint.js").default} MultiPoint.
* @return {MultiPoint} MultiPoint.
*/
function readMultiPointGeometry(object) {
return new MultiPoint(object['coordinates']);
@@ -353,7 +353,7 @@ function readMultiPointGeometry(object) {
/**
* @param {GeoJSONMultiPolygon} object Object.
* @return {import("../geom/MultiPolygon.js").default} MultiPolygon.
* @return {MultiPolygon} MultiPolygon.
*/
function readMultiPolygonGeometry(object) {
return new MultiPolygon(object['coordinates']);
@@ -362,7 +362,7 @@ function readMultiPolygonGeometry(object) {
/**
* @param {GeoJSONPolygon} object Object.
* @return {import("../geom/Polygon.js").default} Polygon.
* @return {Polygon} Polygon.
*/
function readPolygonGeometry(object) {
return new Polygon(object['coordinates']);
@@ -375,38 +375,38 @@ function readPolygonGeometry(object) {
* @return {GeoJSONGeometry} GeoJSON geometry.
*/
function writeGeometry(geometry, opt_options) {
geometry = transformWithOptions(geometry, true, opt_options);
geometry = /** @type {import("../geom/Geometry.js").default} */ (transformWithOptions(geometry, true, opt_options));
const type = geometry.getType();
/** @type {GeoJSONGeometry} */
let geoJSON;
switch (type) {
case GeometryType.POINT: {
geoJSON = writePointGeometry(/** @type {import("../geom/Point.js").default} */ (geometry), opt_options);
geoJSON = writePointGeometry(/** @type {Point} */ (geometry), opt_options);
break;
}
case GeometryType.LINE_STRING: {
geoJSON = writeLineStringGeometry(/** @type {import("../geom/LineString.js").default} */ (geometry), opt_options);
geoJSON = writeLineStringGeometry(/** @type {LineString} */ (geometry), opt_options);
break;
}
case GeometryType.POLYGON: {
geoJSON = writePolygonGeometry(/** @type {import("../geom/Polygon.js").default} */ (geometry), opt_options);
geoJSON = writePolygonGeometry(/** @type {Polygon} */ (geometry), opt_options);
break;
}
case GeometryType.MULTI_POINT: {
geoJSON = writeMultiPointGeometry(/** @type {import("../geom/MultiPoint.js").default} */ (geometry), opt_options);
geoJSON = writeMultiPointGeometry(/** @type {MultiPoint} */ (geometry), opt_options);
break;
}
case GeometryType.MULTI_LINE_STRING: {
geoJSON = writeMultiLineStringGeometry(/** @type {import("../geom/MultiLineString.js").default} */ (geometry), opt_options);
geoJSON = writeMultiLineStringGeometry(/** @type {MultiLineString} */ (geometry), opt_options);
break;
}
case GeometryType.MULTI_POLYGON: {
geoJSON = writeMultiPolygonGeometry(/** @type {import("../geom/MultiPolygon.js").default} */ (geometry), opt_options);
geoJSON = writeMultiPolygonGeometry(/** @type {MultiPolygon} */ (geometry), opt_options);
break;
}
case GeometryType.GEOMETRY_COLLECTION: {
geoJSON = writeGeometryCollectionGeometry(/** @type {import("../geom/GeometryCollection.js").default} */ (geometry), opt_options);
geoJSON = writeGeometryCollectionGeometry(/** @type {GeometryCollection} */ (geometry), opt_options);
break;
}
case GeometryType.CIRCLE: {
@@ -425,7 +425,7 @@ function writeGeometry(geometry, opt_options) {
/**
* @param {import("../geom/GeometryCollection.js").default} geometry Geometry.
* @param {GeometryCollection} geometry Geometry.
* @param {import("./Feature.js").WriteOptions=} opt_options Write options.
* @return {GeoJSONGeometryCollection} GeoJSON geometry collection.
*/
@@ -443,7 +443,7 @@ function writeGeometryCollectionGeometry(geometry, opt_options) {
/**
* @param {import("../geom/LineString.js").default} geometry Geometry.
* @param {LineString} geometry Geometry.
* @param {import("./Feature.js").WriteOptions=} opt_options Write options.
* @return {GeoJSONGeometry} GeoJSON geometry.
*/
@@ -456,7 +456,7 @@ function writeLineStringGeometry(geometry, opt_options) {
/**
* @param {import("../geom/MultiLineString.js").default} geometry Geometry.
* @param {MultiLineString} geometry Geometry.
* @param {import("./Feature.js").WriteOptions=} opt_options Write options.
* @return {GeoJSONGeometry} GeoJSON geometry.
*/
@@ -469,7 +469,7 @@ function writeMultiLineStringGeometry(geometry, opt_options) {
/**
* @param {import("../geom/MultiPoint.js").default} geometry Geometry.
* @param {MultiPoint} geometry Geometry.
* @param {import("./Feature.js").WriteOptions=} opt_options Write options.
* @return {GeoJSONGeometry} GeoJSON geometry.
*/
@@ -482,7 +482,7 @@ function writeMultiPointGeometry(geometry, opt_options) {
/**
* @param {import("../geom/MultiPolygon.js").default} geometry Geometry.
* @param {MultiPolygon} geometry Geometry.
* @param {import("./Feature.js").WriteOptions=} opt_options Write options.
* @return {GeoJSONGeometry} GeoJSON geometry.
*/
@@ -499,7 +499,7 @@ function writeMultiPolygonGeometry(geometry, opt_options) {
/**
* @param {import("../geom/Point.js").default} geometry Geometry.
* @param {Point} geometry Geometry.
* @param {import("./Feature.js").WriteOptions=} opt_options Write options.
* @return {GeoJSONGeometry} GeoJSON geometry.
*/
@@ -512,7 +512,7 @@ function writePointGeometry(geometry, opt_options) {
/**
* @param {import("../geom/Polygon.js").default} geometry Geometry.
* @param {Polygon} geometry Geometry.
* @param {import("./Feature.js").WriteOptions=} opt_options Write options.
* @return {GeoJSONGeometry} GeoJSON geometry.
*/

View File

@@ -1,6 +1,7 @@
/**
* @module ol/format/JSONFeature
*/
import {abstract} from '../util.js';
import FeatureFormat from '../format/Feature.js';
import FormatType from '../format/FormatType.js';
@@ -59,7 +60,9 @@ class JSONFeature extends FeatureFormat {
* @protected
* @return {import("../Feature.js").default} Feature.
*/
readFeatureFromObject(object, opt_options) {}
readFeatureFromObject(object, opt_options) {
return abstract();
}
/**
* @abstract
@@ -68,7 +71,9 @@ class JSONFeature extends FeatureFormat {
* @protected
* @return {Array<import("../Feature.js").default>} Features.
*/
readFeaturesFromObject(object, opt_options) {}
readFeaturesFromObject(object, opt_options) {
return abstract();
}
/**
* Read a geometry.
@@ -90,7 +95,9 @@ class JSONFeature extends FeatureFormat {
* @protected
* @return {import("../geom/Geometry.js").default} Geometry.
*/
readGeometryFromObject(object, opt_options) {}
readGeometryFromObject(object, opt_options) {
return abstract();
}
/**
* Read the projection.
@@ -109,7 +116,9 @@ class JSONFeature extends FeatureFormat {
* @protected
* @return {import("../proj/Projection.js").default} Projection.
*/
readProjectionFromObject(object) {}
readProjectionFromObject(object) {
return abstract();
}
/**
* Encode a feature as string.
@@ -129,7 +138,9 @@ class JSONFeature extends FeatureFormat {
* @param {import("./Feature.js").WriteOptions=} opt_options Write options.
* @return {Object} Object.
*/
writeFeatureObject(feature, opt_options) {}
writeFeatureObject(feature, opt_options) {
return abstract();
}
/**
* Encode an array of features as string.
@@ -149,7 +160,9 @@ class JSONFeature extends FeatureFormat {
* @param {import("./Feature.js").WriteOptions=} opt_options Write options.
* @return {Object} Object.
*/
writeFeaturesObject(features, opt_options) {}
writeFeaturesObject(features, opt_options) {
return abstract();
}
/**
* Encode a geometry as string.
@@ -169,7 +182,9 @@ class JSONFeature extends FeatureFormat {
* @param {import("./Feature.js").WriteOptions=} opt_options Write options.
* @return {Object} Object.
*/
writeGeometryObject(geometry, opt_options) {}
writeGeometryObject(geometry, opt_options) {
return abstract();
}
}

View File

@@ -26,7 +26,7 @@ import IconOrigin from '../style/IconOrigin.js';
import Stroke from '../style/Stroke.js';
import Style from '../style/Style.js';
import Text from '../style/Text.js';
import {createElementNS, getAllTextContent, isDocument, isNode, makeArrayExtender,
import {createElementNS, getAllTextContent, isDocument, makeArrayExtender,
makeArrayPusher, makeChildAppender, makeObjectPropertySetter,
makeReplacer, makeSequence, makeSimpleNodeFactory, makeStructureNS,
OBJECT_PROPERTY_NODE_FACTORY, parse, parseNode, pushParseAndPop,
@@ -639,15 +639,15 @@ class KML extends XMLFeature {
* @api
*/
readName(source) {
if (isDocument(source)) {
return this.readNameFromDocument(/** @type {Document} */ (source));
} else if (isNode(source)) {
return this.readNameFromNode(/** @type {Element} */ (source));
if (!source) {
return undefined;
} else if (typeof source === 'string') {
const doc = parse(source);
return this.readNameFromDocument(doc);
} else if (isDocument(source)) {
return this.readNameFromDocument(/** @type {Document} */ (source));
} else {
return undefined;
return this.readNameFromNode(/** @type {Element} */ (source));
}
}
@@ -656,7 +656,7 @@ class KML extends XMLFeature {
* @return {string|undefined} Name.
*/
readNameFromDocument(doc) {
for (let n = doc.firstChild; n; n = n.nextSibling) {
for (let n = /** @type {Node} */ (doc.firstChild); n; n = n.nextSibling) {
if (n.nodeType == Node.ELEMENT_NODE) {
const name = this.readNameFromNode(/** @type {Element} */ (n));
if (name) {
@@ -703,15 +703,15 @@ class KML extends XMLFeature {
*/
readNetworkLinks(source) {
const networkLinks = [];
if (isDocument(source)) {
extend(networkLinks, this.readNetworkLinksFromDocument(
/** @type {Document} */ (source)));
} else if (isNode(source)) {
extend(networkLinks, this.readNetworkLinksFromNode(
/** @type {Element} */ (source)));
} else if (typeof source === 'string') {
if (typeof source === 'string') {
const doc = parse(source);
extend(networkLinks, this.readNetworkLinksFromDocument(doc));
} else if (isDocument(source)) {
extend(networkLinks, this.readNetworkLinksFromDocument(
/** @type {Document} */ (source)));
} else {
extend(networkLinks, this.readNetworkLinksFromNode(
/** @type {Element} */ (source)));
}
return networkLinks;
}
@@ -722,7 +722,7 @@ class KML extends XMLFeature {
*/
readNetworkLinksFromDocument(doc) {
const networkLinks = [];
for (let n = doc.firstChild; n; n = n.nextSibling) {
for (let n = /** @type {Node} */ (doc.firstChild); n; n = n.nextSibling) {
if (n.nodeType == Node.ELEMENT_NODE) {
extend(networkLinks, this.readNetworkLinksFromNode(/** @type {Element} */ (n)));
}
@@ -765,15 +765,15 @@ class KML extends XMLFeature {
*/
readRegion(source) {
const regions = [];
if (isDocument(source)) {
extend(regions, this.readRegionFromDocument(
/** @type {Document} */ (source)));
} else if (isNode(source)) {
extend(regions, this.readRegionFromNode(
/** @type {Element} */ (source)));
} else if (typeof source === 'string') {
if (typeof source === 'string') {
const doc = parse(source);
extend(regions, this.readRegionFromDocument(doc));
} else if (isDocument(source)) {
extend(regions, this.readRegionFromDocument(
/** @type {Document} */ (source)));
} else {
extend(regions, this.readRegionFromNode(
/** @type {Element} */ (source)));
}
return regions;
}
@@ -784,7 +784,7 @@ class KML extends XMLFeature {
*/
readRegionFromDocument(doc) {
const regions = [];
for (let n = doc.firstChild; n; n = n.nextSibling) {
for (let n = /** @type {Node} */ (doc.firstChild); n; n = n.nextSibling) {
if (n.nodeType == Node.ELEMENT_NODE) {
extend(regions, this.readRegionFromNode(/** @type {Element} */ (n)));
}
@@ -838,6 +838,7 @@ class KML extends XMLFeature {
kml.setAttributeNS(XML_SCHEMA_INSTANCE_URI, 'xsi:schemaLocation', SCHEMA_LOCATION);
const /** @type {import("../xml.js").NodeStackItem} */ context = {node: kml};
/** @type {!Object<string, (Array<Feature>|Feature|undefined)>} */
const properties = {};
if (features.length > 1) {
properties['Document'] = features;
@@ -931,7 +932,7 @@ function createFeatureStyleFunction(style, styleUrl, defaultStyle, sharedStyles,
if (drawName) {
name = /** @type {string} */ (feature.get('name'));
drawName = drawName && name;
drawName = drawName && !!name;
}
if (style) {
@@ -1714,11 +1715,13 @@ function readStyle(node, objectStack) {
if (fill !== undefined && !fill) {
fillStyle = null;
}
let imageStyle = /** @type {import("../style/Image.js").default} */
('imageStyle' in styleObject ?
styleObject['imageStyle'] : DEFAULT_IMAGE_STYLE);
if (imageStyle == DEFAULT_NO_IMAGE_STYLE) {
imageStyle = undefined;
let imageStyle;
if ('imageStyle' in styleObject) {
if (styleObject['imageStyle'] != DEFAULT_NO_IMAGE_STYLE) {
imageStyle = styleObject['imageStyle'];
}
} else {
imageStyle = DEFAULT_IMAGE_STYLE;
}
const textStyle = /** @type {Text} */
('textStyle' in styleObject ?
@@ -2073,9 +2076,10 @@ function whenParser(node, objectStack) {
function writeColorTextNode(node, color) {
const rgba = asArray(color);
const opacity = (rgba.length == 4) ? rgba[3] : 1;
/** @type {Array<string|number>} */
const abgr = [opacity * 255, rgba[2], rgba[1], rgba[0]];
for (let i = 0; i < 4; ++i) {
const hex = parseInt(abgr[i], 10).toString(16);
const hex = Math.floor(/** @type {number} */ (abgr[i])).toString(16);
abgr[i] = (hex.length == 1) ? '0' + hex : hex;
}
writeStringTextNode(node, abgr.join(''));
@@ -2666,7 +2670,7 @@ function writePlacemark(node, feature, objectStack) {
// set id
if (feature.getId()) {
node.setAttribute('id', feature.getId());
node.setAttribute('id', /** @type {string} */ (feature.getId()));
}
// serialize properties (properties unknown to KML are not serialized)
@@ -2713,7 +2717,7 @@ function writePlacemark(node, feature, objectStack) {
const options = /** @type {import("./Feature.js").WriteOptions} */ (objectStack[0]);
let geometry = feature.getGeometry();
if (geometry) {
geometry = transformWithOptions(geometry, true, options);
geometry = /** @type {import("../geom/Geometry.js").default} */ (transformWithOptions(geometry, true, options));
}
pushSerializeAndPop(context, PLACEMARK_SERIALIZERS,
GEOMETRY_NODE_FACTORY, [geometry], objectStack);
@@ -2893,7 +2897,7 @@ function writeStyle(node, style, objectStack) {
const strokeStyle = style.getStroke();
const imageStyle = style.getImage();
const textStyle = style.getText();
if (imageStyle instanceof Icon) {
if (imageStyle && typeof /** @type {?} */ (imageStyle).getSrc === 'function') {
properties['IconStyle'] = imageStyle;
}
if (textStyle) {
@@ -2918,8 +2922,8 @@ function writeStyle(node, style, objectStack) {
* @param {Vec2} vec2 Vec2.
*/
function writeVec2(node, vec2) {
node.setAttribute('x', vec2.x);
node.setAttribute('y', vec2.y);
node.setAttribute('x', String(vec2.x));
node.setAttribute('y', String(vec2.y));
node.setAttribute('xunits', vec2.xunits);
node.setAttribute('yunits', vec2.yunits);
}

View File

@@ -5,8 +5,8 @@
import {assert} from '../asserts.js';
import PBF from 'pbf';
import FeatureFormat, {transformWithOptions} from '../format/Feature.js';
import FormatType from '../format/FormatType.js';
import FeatureFormat, {transformWithOptions} from './Feature.js';
import FormatType from './FormatType.js';
import GeometryLayout from '../geom/GeometryLayout.js';
import GeometryType from '../geom/GeometryType.js';
import LineString from '../geom/LineString.js';
@@ -23,17 +23,14 @@ import RenderFeature from '../render/Feature.js';
/**
* @typedef {Object} Options
* @property {function((import("../geom/Geometry.js").default|Object<string,*>)=)|function(GeometryType,Array<number>,(Array<number>|Array<Array<number>>),Object<string,*>,number)} [featureClass]
* Class for features returned by {@link module:ol/format/MVT#readFeatures}. Set to
* {@link module:ol/Feature~Feature} to get full editing and geometry support at the cost of
* decreased rendering performance. The default is {@link module:ol/render/Feature~RenderFeature},
* which is optimized for rendering and hit detection.
* @property {string} [geometryName='geometry'] Geometry name to use when creating
* features.
* @property {string} [layerName='layer'] Name of the feature attribute that
* holds the layer name.
* @property {Array<string>} [layers] Layers to read features from. If not
* provided, features will be read from all layers.
* @property {import("../Feature.js").FeatureClass} [featureClass] Class for features returned by
* {@link module:ol/format/MVT#readFeatures}. Set to {@link module:ol/Feature~Feature} to get full editing and geometry
* support at the cost of decreased rendering performance. The default is
* {@link module:ol/render/Feature~RenderFeature}, which is optimized for rendering and hit detection.
* @property {string} [geometryName='geometry'] Geometry name to use when creating features.
* @property {string} [layerName='layer'] Name of the feature attribute that holds the layer name.
* @property {Array<string>} [layers] Layers to read features from. If not provided, features will be read from all
* layers.
*/
@@ -64,12 +61,9 @@ class MVT extends FeatureFormat {
/**
* @private
* @type {function((import("../geom/Geometry.js").default|Object<string,*>)=)|
* function(GeometryType,Array<number>,
* (Array<number>|Array<Array<number>>),Object<string,*>,number)}
* @type {import("../Feature.js").FeatureClass}
*/
this.featureClass_ = options.featureClass ?
options.featureClass : RenderFeature;
this.featureClass_ = options.featureClass ? options.featureClass : RenderFeature;
/**
* @private
@@ -167,7 +161,7 @@ class MVT extends FeatureFormat {
* @param {Object} pbf PBF
* @param {Object} rawFeature Raw Mapbox feature.
* @param {import("./Feature.js").ReadOptions=} opt_options Read options.
* @return {import("../Feature.js").default|RenderFeature} Feature.
* @return {import("../Feature.js").FeatureLike} Feature.
*/
createFeature_(pbf, rawFeature, opt_options) {
const type = rawFeature.type;
@@ -215,11 +209,13 @@ class MVT extends FeatureFormat {
geometryType === GeometryType.MULTI_LINE_STRING ? new MultiLineString(flatCoordinates, GeometryLayout.XY, ends) :
null;
}
feature = new this.featureClass_();
const ctor = /** @type {typeof import("../Feature.js").default} */ (this.featureClass_);
feature = new ctor();
if (this.geometryName_) {
feature.setGeometryName(this.geometryName_);
}
const geometry = transformWithOptions(geom, false, this.adaptOptions(opt_options));
const geometry = /** @type {import("../geom/Geometry.js").default} */ (transformWithOptions(geom, false,
this.adaptOptions(opt_options)));
feature.setGeometry(geometry);
feature.setId(id);
feature.setProperties(values);
@@ -252,7 +248,7 @@ class MVT extends FeatureFormat {
const pbf = new PBF(/** @type {ArrayBuffer} */ (source));
const pbfLayers = pbf.readFields(layersPBFReader, {});
/** @type {Array<import("../Feature.js").default|RenderFeature>} */
/** @type {Array<import("../Feature.js").FeatureLike>} */
const features = [];
for (const name in pbfLayers) {
if (layers && layers.indexOf(name) == -1) {

Some files were not shown because too many files have changed in this diff Show More