mapshaper 0.7.1 → 0.7.3
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/LICENSE +1 -1
- package/mapshaper.js +1 -1
- package/package.json +5 -2
- package/www/.nojekyll +0 -0
- package/www/index.html +22 -6
- package/www/mapshaper-gui.js +292 -4
- package/www/mapshaper.js +1 -1
- package/www/page.css +188 -10
- package/www/docs/_assets/cmd-search.js +0 -213
- package/www/docs/_assets/docs.css +0 -712
- package/www/docs/_assets/docs.js +0 -75
- package/www/docs/_assets/highlight.css +0 -10
- package/www/docs/essentials/command-line.html +0 -127
- package/www/docs/essentials/command-line.html.md +0 -112
- package/www/docs/essentials/web-app.html +0 -138
- package/www/docs/essentials/web-app.html.md +0 -106
- package/www/docs/examples/basics.html +0 -276
- package/www/docs/examples/basics.html.md +0 -371
- package/www/docs/examples/data/Makefile +0 -31
- package/www/docs/examples/data/globe.msx +0 -0
- package/www/docs/examples/data/globe.svg +0 -616
- package/www/docs/examples/data/globe.txt +0 -21
- package/www/docs/examples/data/globe.zip +0 -0
- package/www/docs/examples/data/ne_50m_admin_0_countries.geojson +0 -1
- package/www/docs/examples/data/ne_50m_admin_1_states_provinces_lakes.geojson +0 -1
- package/www/docs/examples/data/us-states.msx +0 -0
- package/www/docs/examples/data/us-states.svg +0 -56
- package/www/docs/examples/data/us-states.txt +0 -6
- package/www/docs/examples/data/us-states.zip +0 -0
- package/www/docs/examples/globe.html +0 -108
- package/www/docs/examples/globe.html.md +0 -64
- package/www/docs/examples/us-states.html +0 -88
- package/www/docs/examples/us-states.html.md +0 -44
- package/www/docs/formats/csv.html +0 -127
- package/www/docs/formats/csv.html.md +0 -97
- package/www/docs/formats/dbf.html +0 -87
- package/www/docs/formats/dbf.html.md +0 -39
- package/www/docs/formats/flatgeobuf.html +0 -86
- package/www/docs/formats/flatgeobuf.html.md +0 -42
- package/www/docs/formats/geojson.html +0 -107
- package/www/docs/formats/geojson.html.md +0 -65
- package/www/docs/formats/geopackage.html +0 -87
- package/www/docs/formats/geopackage.html.md +0 -42
- package/www/docs/formats/json.html +0 -83
- package/www/docs/formats/json.html.md +0 -35
- package/www/docs/formats/kml.html +0 -82
- package/www/docs/formats/kml.html.md +0 -39
- package/www/docs/formats/overview.html +0 -192
- package/www/docs/formats/overview.html.md +0 -35
- package/www/docs/formats/shapefile.html +0 -123
- package/www/docs/formats/shapefile.html.md +0 -84
- package/www/docs/formats/snapshot.html +0 -87
- package/www/docs/formats/snapshot.html.md +0 -39
- package/www/docs/formats/svg.html +0 -99
- package/www/docs/formats/svg.html.md +0 -51
- package/www/docs/formats/topojson.html +0 -102
- package/www/docs/formats/topojson.html.md +0 -54
- package/www/docs/gallery/index.html +0 -80
- package/www/docs/gallery/index.html.md +0 -29
- package/www/docs/guides/combining-layers.html +0 -105
- package/www/docs/guides/combining-layers.html.md +0 -81
- package/www/docs/guides/expressions.html +0 -600
- package/www/docs/guides/expressions.html.md +0 -376
- package/www/docs/guides/programmatic.html +0 -117
- package/www/docs/guides/programmatic.html.md +0 -91
- package/www/docs/guides/projections.html +0 -158
- package/www/docs/guides/projections.html.md +0 -118
- package/www/docs/guides/simplification.html +0 -110
- package/www/docs/guides/simplification.html.md +0 -94
- package/www/docs/guides/topology.html +0 -90
- package/www/docs/guides/topology.html.md +0 -63
- package/www/docs/images/simplification-detail.png +0 -0
- package/www/docs/images/simplification-dp.png +0 -0
- package/www/docs/images/simplification-mod2.png +0 -0
- package/www/docs/index.html +0 -101
- package/www/docs/index.html.md +0 -59
- package/www/docs/reference.html +0 -1302
- package/www/docs/reference.html.md +0 -1817
- package/www/docs/whats-new.html +0 -76
- package/www/docs/whats-new.html.md +0 -53
- package/www/llms-full.txt +0 -4040
- package/www/llms.txt +0 -55
package/LICENSE
CHANGED
package/mapshaper.js
CHANGED
|
@@ -52127,7 +52127,7 @@ ${svg}
|
|
|
52127
52127
|
});
|
|
52128
52128
|
}
|
|
52129
52129
|
|
|
52130
|
-
var version = "0.7.
|
|
52130
|
+
var version = "0.7.3";
|
|
52131
52131
|
|
|
52132
52132
|
// Parse command line args into commands and run them
|
|
52133
52133
|
// Function takes an optional Node-style callback. A Promise is returned if no callback is given.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mapshaper",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.3",
|
|
4
4
|
"description": "A tool for editing vector datasets for mapping and GIS.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"shapefile",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"test": "mocha test",
|
|
27
27
|
"build": "rollup --config",
|
|
28
28
|
"docs": "node build-docs.mjs",
|
|
29
|
+
"roadmap": "node build-roadmap.mjs",
|
|
29
30
|
"lint": "eslint --ext mjs src/",
|
|
30
31
|
"prepublishOnly": "npm test; ./pre-publish",
|
|
31
32
|
"postpublish": "./release_web_ui; ./release_github_version",
|
|
@@ -37,7 +38,9 @@
|
|
|
37
38
|
"/www/**",
|
|
38
39
|
"!/www/nacis/**",
|
|
39
40
|
"/mapshaper.js",
|
|
40
|
-
"!.DS_Store"
|
|
41
|
+
"!.DS_Store",
|
|
42
|
+
"!/www/docs/**",
|
|
43
|
+
"!/www/llms*"
|
|
41
44
|
],
|
|
42
45
|
"dependencies": {
|
|
43
46
|
"@ngageoint/geopackage": "^4.2.6",
|
package/www/.nojekyll
ADDED
|
File without changes
|
package/www/index.html
CHANGED
|
@@ -43,6 +43,14 @@
|
|
|
43
43
|
<polygon points="8 14.5 13 19 13 4 3 4 3 19 8 14.5" fill="#30d4ef"/>
|
|
44
44
|
</svg>
|
|
45
45
|
|
|
46
|
+
<svg id="undo-icon" version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
|
47
|
+
<path d="M1.5,8 L7,4.5 L7,7 C10,7 12,9 12,11 L12,13 L10,13 L10,11 C10,10 9,9 7,9 L7,11.5 Z"/>
|
|
48
|
+
</svg>
|
|
49
|
+
|
|
50
|
+
<svg id="redo-icon" version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
|
51
|
+
<path d="M14.5,8 L9,4.5 L9,7 C6,7 4,9 4,11 L4,13 L6,13 L6,11 C6,10 7,9 9,9 L9,11.5 Z"/>
|
|
52
|
+
</svg>
|
|
53
|
+
|
|
46
54
|
</div>
|
|
47
55
|
|
|
48
56
|
<div class="page-header">
|
|
@@ -60,10 +68,17 @@
|
|
|
60
68
|
</div></div>
|
|
61
69
|
<div id="mode-buttons" class="page-header-buttons">
|
|
62
70
|
<!-- <span class="project-btn header-btn btn">Project</span><span class="separator"> -->
|
|
63
|
-
<span class="console-btn header-btn btn">Console</span><span class="display-btn header-btn btn">Display</span><span class="separator"></span><span class="separator"></span></span><span class="simplify-btn header-btn btn">Simplify</span><span class="separator"></span><span class="export-btn header-btn btn">Export</span>
|
|
71
|
+
<span class="console-btn header-btn btn">Console</span><span class="display-btn header-btn btn">Display</span><span class="separator"></span><span class="separator"></span></span><span class="simplify-btn header-btn btn">Simplify</span><span class="separator"></span><span class="export-btn header-btn btn">Export</span><span class="separator"></span><span id="header-menu-btn" class="header-btn btn" role="button" aria-label="More links" aria-haspopup="true" aria-expanded="false" tabindex="0"><svg viewBox="0 0 16 16" aria-hidden="true" width="16" height="14"><rect x="1" y="3" width="14" height="2"/><rect x="1" y="7" width="14" height="2"/><rect x="1" y="11" width="14" height="2"/></svg></span>
|
|
72
|
+
<div id="header-menu-dropdown" class="hidden" role="menu" aria-labelledby="header-menu-btn">
|
|
73
|
+
<a class="header-menu-item" href="/docs/" target="_blank" rel="noopener" role="menuitem">Docs</a>
|
|
74
|
+
<a class="header-menu-item" href="https://github.com/mbloch/mapshaper" target="_blank" rel="noopener" role="menuitem">GitHub</a>
|
|
75
|
+
<a class="header-menu-item survey-en-link" href="https://tally.so/r/44Njok" target="_blank" rel="noopener" role="menuitem">1-minute survey</a>
|
|
76
|
+
<a class="header-menu-item survey-zh-link" href="https://tally.so/r/vGx7KQ" target="_blank" rel="noopener" lang="zh-CN" style="display:none" role="menuitem">意见反馈</a>
|
|
77
|
+
<a class="header-menu-item header-menu-sponsor" href="sponsor.html" target="_blank" rel="noopener" role="menuitem"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/></svg>Become a sponsor</a>
|
|
78
|
+
</div>
|
|
64
79
|
</div>
|
|
65
80
|
<div id="splash-buttons" class="page-header-buttons">
|
|
66
|
-
<a href="/docs/"><span id="wiki-btn" class="header-btn btn">Docs</span></a><span class="separator"></span><a href="https://github.com/mbloch/mapshaper"><span id="github-btn" class="header-btn btn">GitHub</span></a><span class="separator"></span><a
|
|
81
|
+
<a href="/docs/"><span id="wiki-btn" class="header-btn btn">Docs</span></a><span class="separator"></span><a href="https://github.com/mbloch/mapshaper"><span id="github-btn" class="header-btn btn">GitHub</span></a><span class="separator"></span><a class="survey-en-link" href="https://tally.so/r/44Njok" target="_blank" rel="noopener"><span id="survey-en-btn" class="header-btn btn">1-minute survey</span></a><a class="survey-zh-link" href="https://tally.so/r/vGx7KQ" target="_blank" rel="noopener" style="display:none"><span id="survey-zh-btn" class="header-btn btn" lang="zh-CN">意见反馈</span></a><span class="separator"></span><a href="sponsor.html"><span id="sponsor-btn" class="header-btn btn"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/></svg> Become a sponsor</span></a>
|
|
67
82
|
</div>
|
|
68
83
|
</div>
|
|
69
84
|
|
|
@@ -351,10 +366,11 @@ encoding=big5</span>. Click to see all options.</div></div></div>
|
|
|
351
366
|
if (/^zh(-Hans)?-CN\b/i.test(langs[i])) isChina = true;
|
|
352
367
|
}
|
|
353
368
|
if (isChina) {
|
|
354
|
-
|
|
355
|
-
var
|
|
356
|
-
|
|
357
|
-
|
|
369
|
+
// Swap every copy of the survey link (splash bar + hamburger menu)
|
|
370
|
+
var zhLinks = document.querySelectorAll('.survey-zh-link');
|
|
371
|
+
var enLinks = document.querySelectorAll('.survey-en-link');
|
|
372
|
+
for (var j = 0; j < zhLinks.length; j++) zhLinks[j].style.display = '';
|
|
373
|
+
for (var k = 0; k < enLinks.length; k++) enLinks[k].style.display = 'none';
|
|
358
374
|
}
|
|
359
375
|
})();
|
|
360
376
|
</script>
|
package/www/mapshaper-gui.js
CHANGED
|
@@ -5655,6 +5655,56 @@
|
|
|
5655
5655
|
}
|
|
5656
5656
|
}
|
|
5657
5657
|
|
|
5658
|
+
// Hamburger menu in the top-right of the header. After the user starts
|
|
5659
|
+
// editing, the splash bar (Docs / GitHub / Survey / Sponsor) is hidden by
|
|
5660
|
+
// gui.mjs; this menu is the post-edit replacement, exposing the same links
|
|
5661
|
+
// from a single button so the editing controls don't have to share the row.
|
|
5662
|
+
|
|
5663
|
+
|
|
5664
|
+
function HeaderMenu() {
|
|
5665
|
+
var btn = El('#header-menu-btn');
|
|
5666
|
+
var dropdown = El('#header-menu-dropdown');
|
|
5667
|
+
if (!btn.node() || !dropdown.node()) return; // markup missing; nothing to do
|
|
5668
|
+
|
|
5669
|
+
var open = false;
|
|
5670
|
+
|
|
5671
|
+
function setOpen(state) {
|
|
5672
|
+
if (state === open) return;
|
|
5673
|
+
open = state;
|
|
5674
|
+
dropdown.classed('hidden', !open);
|
|
5675
|
+
btn.attr('aria-expanded', open ? 'true' : 'false');
|
|
5676
|
+
}
|
|
5677
|
+
|
|
5678
|
+
btn.on('click', function(e) {
|
|
5679
|
+
e.stopPropagation();
|
|
5680
|
+
setOpen(!open);
|
|
5681
|
+
});
|
|
5682
|
+
|
|
5683
|
+
// Keyboard activation matches button semantics for the role="button" span.
|
|
5684
|
+
btn.on('keydown', function(e) {
|
|
5685
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
5686
|
+
e.preventDefault();
|
|
5687
|
+
setOpen(!open);
|
|
5688
|
+
}
|
|
5689
|
+
});
|
|
5690
|
+
|
|
5691
|
+
// Outside click closes the menu. Clicks on menu items also close it (they
|
|
5692
|
+
// navigate or open in a new tab; either way the menu shouldn't linger).
|
|
5693
|
+
document.addEventListener('click', function(e) {
|
|
5694
|
+
if (!open) return;
|
|
5695
|
+
var target = e.target;
|
|
5696
|
+
if (btn.node().contains(target)) return;
|
|
5697
|
+
setOpen(false);
|
|
5698
|
+
});
|
|
5699
|
+
|
|
5700
|
+
document.addEventListener('keydown', function(e) {
|
|
5701
|
+
if (open && e.key === 'Escape') {
|
|
5702
|
+
setOpen(false);
|
|
5703
|
+
btn.node().focus();
|
|
5704
|
+
}
|
|
5705
|
+
});
|
|
5706
|
+
}
|
|
5707
|
+
|
|
5658
5708
|
function SessionHistory(gui) {
|
|
5659
5709
|
var commands = [];
|
|
5660
5710
|
// index of first command after the last "save" boundary; commands at indices
|
|
@@ -5993,6 +6043,15 @@
|
|
|
5993
6043
|
|
|
5994
6044
|
this.clear = function() {
|
|
5995
6045
|
reset();
|
|
6046
|
+
fireHistoryChange();
|
|
6047
|
+
};
|
|
6048
|
+
|
|
6049
|
+
this.canUndo = function() {
|
|
6050
|
+
return history.length - offset > 0;
|
|
6051
|
+
};
|
|
6052
|
+
|
|
6053
|
+
this.canRedo = function() {
|
|
6054
|
+
return offset > 0;
|
|
5996
6055
|
};
|
|
5997
6056
|
|
|
5998
6057
|
function addHistoryState(undo, redo) {
|
|
@@ -6001,6 +6060,14 @@
|
|
|
6001
6060
|
offset = 0;
|
|
6002
6061
|
}
|
|
6003
6062
|
history.push({undo, redo});
|
|
6063
|
+
fireHistoryChange();
|
|
6064
|
+
}
|
|
6065
|
+
|
|
6066
|
+
function fireHistoryChange() {
|
|
6067
|
+
gui.dispatchEvent('history_change', {
|
|
6068
|
+
canUndo: history.length - offset > 0,
|
|
6069
|
+
canRedo: offset > 0
|
|
6070
|
+
});
|
|
6004
6071
|
}
|
|
6005
6072
|
|
|
6006
6073
|
this.undo = function() {
|
|
@@ -6013,6 +6080,7 @@
|
|
|
6013
6080
|
item.undo();
|
|
6014
6081
|
gui.dispatchEvent('undo_redo_post', {type: 'undo'});
|
|
6015
6082
|
gui.dispatchEvent('map-needs-refresh');
|
|
6083
|
+
fireHistoryChange();
|
|
6016
6084
|
}
|
|
6017
6085
|
};
|
|
6018
6086
|
|
|
@@ -6024,6 +6092,7 @@
|
|
|
6024
6092
|
item.redo();
|
|
6025
6093
|
gui.dispatchEvent('undo_redo_post', {type: 'redo'});
|
|
6026
6094
|
gui.dispatchEvent('map-needs-refresh');
|
|
6095
|
+
fireHistoryChange();
|
|
6027
6096
|
};
|
|
6028
6097
|
|
|
6029
6098
|
function getHistoryItem() {
|
|
@@ -6337,6 +6406,10 @@
|
|
|
6337
6406
|
return ['info', 'selection', 'data', 'box', 'labels', 'edit_points', 'rectangles'].includes(mode);
|
|
6338
6407
|
};
|
|
6339
6408
|
|
|
6409
|
+
this.modeSupportsUndo = function(mode) {
|
|
6410
|
+
return ['data', 'labels', 'edit_points', 'edit_lines', 'edit_polygons', 'vertices', 'rectangles'].includes(mode);
|
|
6411
|
+
};
|
|
6412
|
+
|
|
6340
6413
|
this.getMode = getInteractionMode;
|
|
6341
6414
|
|
|
6342
6415
|
this.setMode = function(mode) {
|
|
@@ -6479,6 +6552,214 @@
|
|
|
6479
6552
|
}
|
|
6480
6553
|
}
|
|
6481
6554
|
|
|
6555
|
+
// A reusable floating toolbar anchored at the bottom-center of the map area.
|
|
6556
|
+
//
|
|
6557
|
+
// Multiple toolbars stack vertically inside a shared container, so additional
|
|
6558
|
+
// per-mode toolbars (e.g. feature styling) can coexist with the edit toolbar.
|
|
6559
|
+
//
|
|
6560
|
+
// The DOM is structured to leave room for a future drag handle without
|
|
6561
|
+
// requiring rework: the toolbar element is a flex row with a content slot,
|
|
6562
|
+
// and a sibling drag-handle slot can be added later.
|
|
6563
|
+
//
|
|
6564
|
+
// Constructor options:
|
|
6565
|
+
// name: optional CSS class added to the toolbar element
|
|
6566
|
+
// transition: ms for the show/hide transition (default 150)
|
|
6567
|
+
//
|
|
6568
|
+
// API:
|
|
6569
|
+
// toolbar.addButton(iconRef, opts) -> ToolbarButton
|
|
6570
|
+
// toolbar.addSeparator()
|
|
6571
|
+
// toolbar.show()
|
|
6572
|
+
// toolbar.hide()
|
|
6573
|
+
// toolbar.visible()
|
|
6574
|
+
// toolbar.node()
|
|
6575
|
+
|
|
6576
|
+
function FloatingToolbar(gui, opts) {
|
|
6577
|
+
opts = opts || {};
|
|
6578
|
+
var transitionMs = opts.transition || 150;
|
|
6579
|
+
var root = gui.container.findChild('.mshp-main-map');
|
|
6580
|
+
var stack = root.findChild('.floating-toolbar-stack');
|
|
6581
|
+
if (!stack) {
|
|
6582
|
+
stack = El('div').addClass('floating-toolbar-stack').appendTo(root);
|
|
6583
|
+
}
|
|
6584
|
+
var el = El('div').addClass('floating-toolbar');
|
|
6585
|
+
if (opts.name) el.addClass(opts.name);
|
|
6586
|
+
var content = El('div').addClass('floating-toolbar-content').appendTo(el);
|
|
6587
|
+
var visible = false;
|
|
6588
|
+
var hideTimer = null;
|
|
6589
|
+
|
|
6590
|
+
el.appendTo(stack);
|
|
6591
|
+
el.css('display', 'none');
|
|
6592
|
+
|
|
6593
|
+
// Hide when this gui instance becomes inactive (e.g. multi-instance mode)
|
|
6594
|
+
gui.on('active', updateVisibility);
|
|
6595
|
+
gui.on('inactive', updateVisibility);
|
|
6596
|
+
|
|
6597
|
+
this.addButton = function(iconRef, btnOpts) {
|
|
6598
|
+
return new ToolbarButton(content, iconRef, btnOpts || {});
|
|
6599
|
+
};
|
|
6600
|
+
|
|
6601
|
+
this.addSeparator = function() {
|
|
6602
|
+
return El('div').addClass('floating-toolbar-separator').appendTo(content);
|
|
6603
|
+
};
|
|
6604
|
+
|
|
6605
|
+
this.show = function() {
|
|
6606
|
+
if (visible) return;
|
|
6607
|
+
visible = true;
|
|
6608
|
+
updateVisibility();
|
|
6609
|
+
};
|
|
6610
|
+
|
|
6611
|
+
this.hide = function() {
|
|
6612
|
+
if (!visible) return;
|
|
6613
|
+
visible = false;
|
|
6614
|
+
updateVisibility();
|
|
6615
|
+
};
|
|
6616
|
+
|
|
6617
|
+
this.visible = function() {
|
|
6618
|
+
return visible;
|
|
6619
|
+
};
|
|
6620
|
+
|
|
6621
|
+
this.node = function() {
|
|
6622
|
+
return el.node();
|
|
6623
|
+
};
|
|
6624
|
+
|
|
6625
|
+
function updateVisibility() {
|
|
6626
|
+
var shouldShow = visible && GUI.isActiveInstance(gui);
|
|
6627
|
+
if (shouldShow) {
|
|
6628
|
+
clearTimeout(hideTimer);
|
|
6629
|
+
hideTimer = null;
|
|
6630
|
+
el.css('display', 'flex');
|
|
6631
|
+
// wait one frame so the browser registers the initial state before
|
|
6632
|
+
// the transition kicks in
|
|
6633
|
+
requestAnimationFrame(function() {
|
|
6634
|
+
el.addClass('visible');
|
|
6635
|
+
});
|
|
6636
|
+
} else {
|
|
6637
|
+
el.removeClass('visible');
|
|
6638
|
+
// wait for the transition to finish before hiding completely
|
|
6639
|
+
clearTimeout(hideTimer);
|
|
6640
|
+
hideTimer = setTimeout(function() {
|
|
6641
|
+
if (!(visible && GUI.isActiveInstance(gui))) {
|
|
6642
|
+
el.css('display', 'none');
|
|
6643
|
+
}
|
|
6644
|
+
}, transitionMs);
|
|
6645
|
+
}
|
|
6646
|
+
}
|
|
6647
|
+
}
|
|
6648
|
+
|
|
6649
|
+
function ToolbarButton(parent, iconRef, opts) {
|
|
6650
|
+
var btn = El('div').addClass('floating-toolbar-btn').appendTo(parent);
|
|
6651
|
+
if (iconRef) {
|
|
6652
|
+
var iconNode = El('body').findChild(iconRef);
|
|
6653
|
+
if (iconNode) {
|
|
6654
|
+
var icon = iconNode.node().cloneNode(true);
|
|
6655
|
+
if (icon.hasAttribute('id')) icon.removeAttribute('id');
|
|
6656
|
+
btn.node().appendChild(icon);
|
|
6657
|
+
}
|
|
6658
|
+
}
|
|
6659
|
+
var enabled = true;
|
|
6660
|
+
var clickHandlers = [];
|
|
6661
|
+
|
|
6662
|
+
if (opts.tooltip) setTooltip(opts.tooltip);
|
|
6663
|
+
|
|
6664
|
+
// Block native dblclick to avoid the map's double-click zoom
|
|
6665
|
+
btn.on('dblclick', function(e) { e.stopPropagation(); });
|
|
6666
|
+
|
|
6667
|
+
btn.on('click', function(e) {
|
|
6668
|
+
if (!enabled) return;
|
|
6669
|
+
for (var i = 0; i < clickHandlers.length; i++) {
|
|
6670
|
+
clickHandlers[i](e);
|
|
6671
|
+
}
|
|
6672
|
+
});
|
|
6673
|
+
|
|
6674
|
+
this.on = function(event, fn) {
|
|
6675
|
+
if (event == 'click') {
|
|
6676
|
+
clickHandlers.push(fn);
|
|
6677
|
+
} else {
|
|
6678
|
+
btn.on(event, fn);
|
|
6679
|
+
}
|
|
6680
|
+
return this;
|
|
6681
|
+
};
|
|
6682
|
+
|
|
6683
|
+
this.enable = function() { return this.setEnabled(true); };
|
|
6684
|
+
this.disable = function() { return this.setEnabled(false); };
|
|
6685
|
+
|
|
6686
|
+
this.setEnabled = function(b) {
|
|
6687
|
+
enabled = !!b;
|
|
6688
|
+
btn.classed('disabled', !enabled);
|
|
6689
|
+
return this;
|
|
6690
|
+
};
|
|
6691
|
+
|
|
6692
|
+
this.setTooltip = setTooltip;
|
|
6693
|
+
|
|
6694
|
+
this.node = function() {
|
|
6695
|
+
return btn.node();
|
|
6696
|
+
};
|
|
6697
|
+
|
|
6698
|
+
function setTooltip(text) {
|
|
6699
|
+
btn.attr('data-tooltip', text);
|
|
6700
|
+
}
|
|
6701
|
+
}
|
|
6702
|
+
|
|
6703
|
+
// Floating toolbar that exposes undo/redo while the user is in an editing
|
|
6704
|
+
// interaction mode. The toolbar is the first consumer of FloatingToolbar;
|
|
6705
|
+
// future per-mode toolbars (e.g. feature styling) can follow the same pattern.
|
|
6706
|
+
|
|
6707
|
+
function EditToolbar(gui) {
|
|
6708
|
+
var toolbar = new FloatingToolbar(gui, { name: 'edit-toolbar' });
|
|
6709
|
+
var isMac = navigator.userAgent.includes('Mac');
|
|
6710
|
+
var modKey = isMac ? '\u2318' : 'Ctrl+';
|
|
6711
|
+
var shiftKey = isMac ? '\u21e7' : 'Shift+';
|
|
6712
|
+
|
|
6713
|
+
var undoBtn = toolbar.addButton('#undo-icon', {
|
|
6714
|
+
tooltip: 'Undo (' + modKey + 'Z)'
|
|
6715
|
+
}).on('click', function() {
|
|
6716
|
+
gui.undo.undo();
|
|
6717
|
+
});
|
|
6718
|
+
|
|
6719
|
+
var redoBtn = toolbar.addButton('#redo-icon', {
|
|
6720
|
+
tooltip: 'Redo (' + shiftKey + modKey + 'Z)'
|
|
6721
|
+
}).on('click', function() {
|
|
6722
|
+
gui.undo.redo();
|
|
6723
|
+
});
|
|
6724
|
+
|
|
6725
|
+
updateButtons();
|
|
6726
|
+
|
|
6727
|
+
gui.on('interaction_mode_change', function() {
|
|
6728
|
+
updateVisibility();
|
|
6729
|
+
// history is cleared on mode change; refresh button states next tick
|
|
6730
|
+
updateButtons();
|
|
6731
|
+
});
|
|
6732
|
+
|
|
6733
|
+
gui.on('history_change', function(e) {
|
|
6734
|
+
undoBtn.setEnabled(!!e.canUndo);
|
|
6735
|
+
redoBtn.setEnabled(!!e.canRedo);
|
|
6736
|
+
// Visibility may also depend on history (e.g. attribute edits via popup
|
|
6737
|
+
// happen in modes that don't otherwise support undo).
|
|
6738
|
+
updateVisibility();
|
|
6739
|
+
});
|
|
6740
|
+
|
|
6741
|
+
updateVisibility();
|
|
6742
|
+
|
|
6743
|
+
function updateVisibility() {
|
|
6744
|
+
if (!gui.interaction) {
|
|
6745
|
+
toolbar.hide();
|
|
6746
|
+
return;
|
|
6747
|
+
}
|
|
6748
|
+
var mode = gui.interaction.getMode();
|
|
6749
|
+
var hasHistory = gui.undo.canUndo() || gui.undo.canRedo();
|
|
6750
|
+
if (gui.interaction.modeSupportsUndo(mode) || hasHistory) {
|
|
6751
|
+
toolbar.show();
|
|
6752
|
+
} else {
|
|
6753
|
+
toolbar.hide();
|
|
6754
|
+
}
|
|
6755
|
+
}
|
|
6756
|
+
|
|
6757
|
+
function updateButtons() {
|
|
6758
|
+
undoBtn.setEnabled(gui.undo.canUndo());
|
|
6759
|
+
redoBtn.setEnabled(gui.undo.canRedo());
|
|
6760
|
+
}
|
|
6761
|
+
}
|
|
6762
|
+
|
|
6482
6763
|
function Model(gui) {
|
|
6483
6764
|
var self = new internal.Catalog();
|
|
6484
6765
|
var deleteLayer = self.deleteLayer;
|
|
@@ -9576,6 +9857,10 @@
|
|
|
9576
9857
|
|
|
9577
9858
|
box.setDataCoords = function(bbox) {
|
|
9578
9859
|
boxCoords = bbox;
|
|
9860
|
+
// Box is being placed programmatically (e.g. around a pinned rectangle);
|
|
9861
|
+
// enable pointer events on the handles so they can be dragged. Without
|
|
9862
|
+
// this, mousedowns fall through to the map and trigger pan.
|
|
9863
|
+
el.classed('hittable', true);
|
|
9579
9864
|
redraw();
|
|
9580
9865
|
};
|
|
9581
9866
|
|
|
@@ -9599,6 +9884,7 @@
|
|
|
9599
9884
|
// remove the current box (if any)
|
|
9600
9885
|
box.hide = function() {
|
|
9601
9886
|
el.hide();
|
|
9887
|
+
el.classed('hittable', false);
|
|
9602
9888
|
boxCoords = null;
|
|
9603
9889
|
_visible = false;
|
|
9604
9890
|
clickStartPoint = null;
|
|
@@ -10949,8 +11235,8 @@
|
|
|
10949
11235
|
function showInstructions() {
|
|
10950
11236
|
var isMac = navigator.userAgent.includes('Mac');
|
|
10951
11237
|
var symbol = isMac ? '⌘' : '^';
|
|
10952
|
-
var msg = `Instructions:
|
|
10953
|
-
alert = showPopupAlert(msg, null, { non_blocking: true, max_width: '
|
|
11238
|
+
var msg = `Instructions: click on the map to add points. Move points by dragging.`;
|
|
11239
|
+
alert = showPopupAlert(msg, null, { non_blocking: true, max_width: '290px'});
|
|
10954
11240
|
}
|
|
10955
11241
|
|
|
10956
11242
|
gui.on('interaction_mode_change', function(e) {
|
|
@@ -11167,9 +11453,9 @@
|
|
|
11167
11453
|
function showInstructions() {
|
|
11168
11454
|
var isMac = navigator.userAgent.includes('Mac');
|
|
11169
11455
|
var undoKey = isMac ? '⌘' : '^';
|
|
11170
|
-
var msg = `Instructions: click to start a path, click or drag to keep drawing. Drag vertices to reshape a path
|
|
11456
|
+
var msg = `Instructions: click to start a path, click or drag to keep drawing. Drag vertices to reshape a path.`;
|
|
11171
11457
|
alert = showPopupAlert(msg, null, {
|
|
11172
|
-
non_blocking: true, max_width: '
|
|
11458
|
+
non_blocking: true, max_width: '350px'});
|
|
11173
11459
|
}
|
|
11174
11460
|
|
|
11175
11461
|
function hideInstructions() {
|
|
@@ -14631,6 +14917,7 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
14631
14917
|
new SessionSnapshots(gui);
|
|
14632
14918
|
}
|
|
14633
14919
|
gui.interaction = new InteractionMode(gui);
|
|
14920
|
+
gui.editToolbar = new EditToolbar(gui);
|
|
14634
14921
|
|
|
14635
14922
|
gui.showProgressMessage = function(msg) {
|
|
14636
14923
|
if (!gui.progressMessage) {
|
|
@@ -14755,6 +15042,7 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
14755
15042
|
new ImportControl(gui, importOpts);
|
|
14756
15043
|
new ExportControl(gui);
|
|
14757
15044
|
new LayerControl(gui);
|
|
15045
|
+
HeaderMenu();
|
|
14758
15046
|
gui.console = new Console(gui);
|
|
14759
15047
|
|
|
14760
15048
|
startEditing = function() {};
|
package/www/mapshaper.js
CHANGED
|
@@ -52127,7 +52127,7 @@ ${svg}
|
|
|
52127
52127
|
});
|
|
52128
52128
|
}
|
|
52129
52129
|
|
|
52130
|
-
var version = "0.7.
|
|
52130
|
+
var version = "0.7.3";
|
|
52131
52131
|
|
|
52132
52132
|
// Parse command line args into commands and run them
|
|
52133
52133
|
// Function takes an optional Node-style callback. A Promise is returned if no callback is given.
|