mapshaper 0.6.110 → 0.6.112
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/mapshaper.js +985 -1646
- package/package.json +1 -1
- package/www/mapshaper-gui.js +80 -27
- package/www/mapshaper.js +985 -1646
- package/www/page.css +1 -1
package/package.json
CHANGED
package/www/mapshaper-gui.js
CHANGED
|
@@ -1937,8 +1937,20 @@
|
|
|
1937
1937
|
.on('paste', onpaste);
|
|
1938
1938
|
area.node().addEventListener('paste', onpaste);
|
|
1939
1939
|
function ondrop(e) {
|
|
1940
|
+
var files = e.dataTransfer.files;
|
|
1941
|
+
var types = e.dataTransfer.types;
|
|
1940
1942
|
block(e);
|
|
1941
|
-
|
|
1943
|
+
if (files.length) {
|
|
1944
|
+
cb(files);
|
|
1945
|
+
} else if (types.includes('text/uri-list')) {
|
|
1946
|
+
cb(e.dataTransfer.getData('text/uri-list').split(','));
|
|
1947
|
+
} else if (types.includes('text/html')) {
|
|
1948
|
+
// drag-dropping a highlighted link may pull in a chunk of html
|
|
1949
|
+
var urls = e.dataTransfer.getData('text/html').match(/https?:[^"']+/);
|
|
1950
|
+
if (urls.length) {
|
|
1951
|
+
cb(urls);
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1942
1954
|
}
|
|
1943
1955
|
function onpaste(e) {
|
|
1944
1956
|
var types = Array.from(e.clipboardData.types || []).join(',');
|
|
@@ -1955,15 +1967,18 @@
|
|
|
1955
1967
|
// Single files of all types are pasted as a string and an image/png
|
|
1956
1968
|
// Multiple files are pasted as a string containing a list of file names
|
|
1957
1969
|
|
|
1958
|
-
// import text from the clipboard (could be csv, json, etc)
|
|
1970
|
+
// import text from the clipboard (could be csv, json, a url, etc)
|
|
1959
1971
|
// formatted text can be available as both text/plain and text/html (e.g.
|
|
1960
1972
|
// a JSON data object copied from a GitHub issue).
|
|
1961
1973
|
//
|
|
1962
1974
|
if (types.includes('text/plain')) {
|
|
1963
|
-
// if (types == 'text/plain') {
|
|
1964
1975
|
// text from clipboard (supported by Chrome, FF, Safari)
|
|
1965
1976
|
// TODO: handle FF case of string containing multiple file names.
|
|
1966
|
-
|
|
1977
|
+
var str = e.clipboardData.getData('text/plain');
|
|
1978
|
+
if (isUrl(str)) {
|
|
1979
|
+
return cb(str.split(','));
|
|
1980
|
+
}
|
|
1981
|
+
files = [pastedTextToFile(str)];
|
|
1967
1982
|
} else {
|
|
1968
1983
|
files = items.map(function(item) {
|
|
1969
1984
|
return item.kind == 'file' && !item.type.includes('image') ?
|
|
@@ -1997,6 +2012,10 @@
|
|
|
1997
2012
|
return new File([blob], name);
|
|
1998
2013
|
}
|
|
1999
2014
|
|
|
2015
|
+
function isUrl(str) {
|
|
2016
|
+
return /^https?:\/\//.test(str);
|
|
2017
|
+
}
|
|
2018
|
+
|
|
2000
2019
|
// @el DOM element for select button
|
|
2001
2020
|
// @cb function(<FileList>)
|
|
2002
2021
|
function FileChooser(el, cb) {
|
|
@@ -2040,7 +2059,7 @@
|
|
|
2040
2059
|
|
|
2041
2060
|
var submitBtn = new SimpleButton('#import-options .submit-btn').on('click', importQueuedFiles);
|
|
2042
2061
|
new SimpleButton('#import-options .cancel-btn').on('click', gui.clearMode);
|
|
2043
|
-
new DropControl(gui, 'body',
|
|
2062
|
+
new DropControl(gui, 'body', receiveDroppedItems);
|
|
2044
2063
|
new FileChooser('#import-options .add-btn', receiveFilesWithOption);
|
|
2045
2064
|
new FileChooser('#add-file-btn', receiveFiles);
|
|
2046
2065
|
new SimpleButton('#add-empty-btn').on('click', function() {
|
|
@@ -2056,7 +2075,7 @@
|
|
|
2056
2075
|
|
|
2057
2076
|
function turnOn() {
|
|
2058
2077
|
if (manifestFiles.length > 0) {
|
|
2059
|
-
downloadFiles(manifestFiles
|
|
2078
|
+
downloadFiles(manifestFiles);
|
|
2060
2079
|
manifestFiles = [];
|
|
2061
2080
|
} else if (model.isEmpty()) {
|
|
2062
2081
|
showImportMenu();
|
|
@@ -2157,6 +2176,14 @@
|
|
|
2157
2176
|
submitBtn.classed('disabled', queuedFiles.length === 0);
|
|
2158
2177
|
}
|
|
2159
2178
|
|
|
2179
|
+
function receiveDroppedItems(arr) {
|
|
2180
|
+
if (utils$1.isString(arr[0])) { // assume array of URLs
|
|
2181
|
+
downloadFiles(arr);
|
|
2182
|
+
} else { // assume array of Files
|
|
2183
|
+
receiveFilesWithOption(arr);
|
|
2184
|
+
}
|
|
2185
|
+
}
|
|
2186
|
+
|
|
2160
2187
|
function receiveFilesWithOption(files) {
|
|
2161
2188
|
var quickView = !El('.advanced-import-options').node().checked;
|
|
2162
2189
|
receiveFiles(files, quickView);
|
|
@@ -2312,9 +2339,8 @@
|
|
|
2312
2339
|
|
|
2313
2340
|
function prepFilesForDownload(names) {
|
|
2314
2341
|
var items = names.map(function(name) {
|
|
2315
|
-
var isUrl = /:\/\//.test(name);
|
|
2316
2342
|
var item = {name: name};
|
|
2317
|
-
if (isUrl) {
|
|
2343
|
+
if (isUrl(name)) {
|
|
2318
2344
|
item.url = name;
|
|
2319
2345
|
item.basename = GUI.getUrlFilename(name);
|
|
2320
2346
|
|
|
@@ -2667,7 +2693,7 @@
|
|
|
2667
2693
|
var lyr;
|
|
2668
2694
|
if (memo) return memo; // already found a match
|
|
2669
2695
|
// try to match import filename of this dataset
|
|
2670
|
-
if (d.info
|
|
2696
|
+
if (d.info?.input_files?.[0] == src) return d;
|
|
2671
2697
|
// try to match name of a layer in this dataset
|
|
2672
2698
|
lyr = utils$1.find(d.layers, function(lyr) {return lyr.name == src;});
|
|
2673
2699
|
return lyr ? internal.isolateLayer(lyr, d) : null;
|
|
@@ -4176,13 +4202,6 @@
|
|
|
4176
4202
|
flags.union || flags.mosaic || flags.snap || flags.clean || flags.drop || false;
|
|
4177
4203
|
}
|
|
4178
4204
|
|
|
4179
|
-
// check for operations that may change the number of self intersections in the
|
|
4180
|
-
// target layer.
|
|
4181
|
-
function intersectionsMayHaveChanged(flags) {
|
|
4182
|
-
return arcsMayHaveChanged(flags) || flags.select || flags['merge-layers'] ||
|
|
4183
|
-
flags.filter || flags.dissolve || flags.dissolve2;
|
|
4184
|
-
}
|
|
4185
|
-
|
|
4186
4205
|
// Test if an update allows hover popup to stay open
|
|
4187
4206
|
function popupCanStayOpen(flags) {
|
|
4188
4207
|
// keeping popup open after -drop geometry causes problems...
|
|
@@ -4207,7 +4226,7 @@
|
|
|
4207
4226
|
return c;
|
|
4208
4227
|
}
|
|
4209
4228
|
|
|
4210
|
-
function
|
|
4229
|
+
function IntersectionControl(gui) {
|
|
4211
4230
|
var map = gui.map,
|
|
4212
4231
|
model = gui.model,
|
|
4213
4232
|
el = gui.container.findChild(".intersection-display"),
|
|
@@ -4243,12 +4262,24 @@
|
|
|
4243
4262
|
gui.session.simplificationRepair();
|
|
4244
4263
|
});
|
|
4245
4264
|
|
|
4265
|
+
// check for operations that may change the number of self intersections in the
|
|
4266
|
+
// target layer.
|
|
4267
|
+
function intersectionsMayHaveChanged(flags) {
|
|
4268
|
+
return arcsMayHaveChanged(flags) || flags.select || flags.repair ||
|
|
4269
|
+
flags.clean || flags.filter || flags.dissolve || flags.dissolve2 ||
|
|
4270
|
+
flags['merge-layers'] || flags.simplify_method || flags.simplify ||
|
|
4271
|
+
flags.split;
|
|
4272
|
+
}
|
|
4273
|
+
|
|
4274
|
+
|
|
4246
4275
|
model.on('update', function(e) {
|
|
4247
|
-
var needRefresh = e.flags
|
|
4248
|
-
e.flags.repair || e.flags.clean || e.flags.select || intersectionsMayHaveChanged(e.flags);
|
|
4276
|
+
var needRefresh = intersectionsMayHaveChanged(e.flags);
|
|
4249
4277
|
if (!intersectionsAreOn()) {
|
|
4250
4278
|
reset();
|
|
4251
4279
|
} else if (needRefresh) {
|
|
4280
|
+
// don't continue to show old intersections when map redraws
|
|
4281
|
+
map.setIntersectionLayer(null, null, false);
|
|
4282
|
+
// regenerate intersections and redraw map
|
|
4252
4283
|
updateAsync();
|
|
4253
4284
|
} else if (e.flags.simplify_amount) {
|
|
4254
4285
|
// slider is being dragged - hide readout and dots, retain data
|
|
@@ -4256,7 +4287,7 @@
|
|
|
4256
4287
|
} else {
|
|
4257
4288
|
// keep displaying the current intersections
|
|
4258
4289
|
}
|
|
4259
|
-
});
|
|
4290
|
+
}, 10);
|
|
4260
4291
|
|
|
4261
4292
|
function updateRepairBtn() {
|
|
4262
4293
|
if (intersectionsAreOn() && gui.getMode() == 'simplify' &&
|
|
@@ -4340,7 +4371,7 @@
|
|
|
4340
4371
|
}
|
|
4341
4372
|
}
|
|
4342
4373
|
|
|
4343
|
-
utils$1.inherit(
|
|
4374
|
+
utils$1.inherit(IntersectionControl, EventDispatcher);
|
|
4344
4375
|
|
|
4345
4376
|
async function saveFileContentToClipboard(content) {
|
|
4346
4377
|
var str = utils$1.isString(content) ? content : content.toString();
|
|
@@ -5063,7 +5094,7 @@
|
|
|
5063
5094
|
var lyr = o.layer;
|
|
5064
5095
|
var opts = {
|
|
5065
5096
|
show_source: layerCount < 5,
|
|
5066
|
-
pinnable: pinnableCount >
|
|
5097
|
+
pinnable: pinnableCount > 0 && isPinnable(lyr)
|
|
5067
5098
|
};
|
|
5068
5099
|
var html, element;
|
|
5069
5100
|
html = renderLayer(lyr, o.dataset, opts);
|
|
@@ -6294,6 +6325,18 @@
|
|
|
6294
6325
|
}
|
|
6295
6326
|
}
|
|
6296
6327
|
|
|
6328
|
+
function time(slug) {
|
|
6329
|
+
if (useDebug()) {
|
|
6330
|
+
console.time(slug);
|
|
6331
|
+
}
|
|
6332
|
+
}
|
|
6333
|
+
|
|
6334
|
+
function timeEnd(slug) {
|
|
6335
|
+
if (useDebug()) {
|
|
6336
|
+
console.timeEnd(slug);
|
|
6337
|
+
}
|
|
6338
|
+
}
|
|
6339
|
+
|
|
6297
6340
|
function printError(err) {
|
|
6298
6341
|
var msg;
|
|
6299
6342
|
if (!LOGGING) return;
|
|
@@ -7457,8 +7500,13 @@
|
|
|
7457
7500
|
if (len >= 2) {
|
|
7458
7501
|
first = str.charAt(0);
|
|
7459
7502
|
last = str.charAt(len-1);
|
|
7460
|
-
if (first == '"' && last == '"' && !str.includes('","') ||
|
|
7461
|
-
|
|
7503
|
+
// if (first == '"' && last == '"' && !str.includes('","') ||
|
|
7504
|
+
// first == "'" && last == "'" && !str.includes("','")) {
|
|
7505
|
+
// don't strip if there are unescaped quotes
|
|
7506
|
+
// e.g. expressions that start and end with quotes
|
|
7507
|
+
// e.g. comma-separated list of quoted values
|
|
7508
|
+
if (first == '"' && last == '"' && !/[^\\]"./.test(str) ||
|
|
7509
|
+
first == "'" && last == "'" && !/[^\\]'./.test(str)) {
|
|
7462
7510
|
str = str.substr(1, len-2);
|
|
7463
7511
|
// remove string escapes
|
|
7464
7512
|
str = str.replace(first == '"' ? /\\(?=")/g : /\\(?=')/g, '');
|
|
@@ -10100,6 +10148,9 @@
|
|
|
10100
10148
|
// special overlay: shape editing mode
|
|
10101
10149
|
lyr = getOverlayLayer(activeLyr, hitData.ids);
|
|
10102
10150
|
lyr.gui.style = getLineEditingStyle(hitData);
|
|
10151
|
+
if (activeLyr.geometry_type == 'polygon') {
|
|
10152
|
+
lyr.gui.style.fillColor = hoverFill;
|
|
10153
|
+
}
|
|
10103
10154
|
return [lyr];
|
|
10104
10155
|
}
|
|
10105
10156
|
layers = [];
|
|
@@ -13014,7 +13065,7 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13014
13065
|
});
|
|
13015
13066
|
|
|
13016
13067
|
// Update display of segment intersections
|
|
13017
|
-
this.setIntersectionLayer = function(lyr, dataset) {
|
|
13068
|
+
this.setIntersectionLayer = function(lyr, dataset, redraw) {
|
|
13018
13069
|
if (lyr == _intersectionLyr) return; // no change
|
|
13019
13070
|
if (lyr) {
|
|
13020
13071
|
enhanceLayerForDisplay(lyr, dataset, getDisplayOptions());
|
|
@@ -13024,7 +13075,9 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13024
13075
|
_intersectionLyr = null;
|
|
13025
13076
|
}
|
|
13026
13077
|
// TODO: try to avoid redrawing layers twice (in some situations)
|
|
13027
|
-
|
|
13078
|
+
if (redraw !== false) {
|
|
13079
|
+
drawLayers();
|
|
13080
|
+
}
|
|
13028
13081
|
};
|
|
13029
13082
|
|
|
13030
13083
|
this.pixelCoordsToLngLatCoords = function(x, y) {
|
|
@@ -13996,7 +14049,7 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13996
14049
|
// }
|
|
13997
14050
|
|
|
13998
14051
|
new AlertControl(gui);
|
|
13999
|
-
new
|
|
14052
|
+
new IntersectionControl(gui);
|
|
14000
14053
|
new SimplifyControl(gui);
|
|
14001
14054
|
new ImportControl(gui, importOpts);
|
|
14002
14055
|
new ExportControl(gui);
|