mapshaper 0.7.11 → 0.7.13
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 +364 -114
- package/package.json +3 -3
- package/www/index.html +27 -29
- package/www/mapshaper-gui.js +367 -106
- package/www/mapshaper.js +364 -114
- package/www/page.css +247 -110
package/www/mapshaper-gui.js
CHANGED
|
@@ -6097,6 +6097,7 @@
|
|
|
6097
6097
|
// gui.container.addClass('queued-files');
|
|
6098
6098
|
El('#import-options').show();
|
|
6099
6099
|
gui.container.classed('queued-files', queuedFiles.length > 0);
|
|
6100
|
+
updateSidebarTabZIndex();
|
|
6100
6101
|
El('#path-import-options').classed('hidden', !filesMayContainPaths(queuedFiles));
|
|
6101
6102
|
showQueuedFiles();
|
|
6102
6103
|
updateGeoPackageLayerSelectionMenu();
|
|
@@ -6104,9 +6105,15 @@
|
|
|
6104
6105
|
|
|
6105
6106
|
function hideImportMenu() {
|
|
6106
6107
|
// gui.container.removeClass('queued-files');
|
|
6108
|
+
gui.container.removeClass('sidebar-tabs-over-popup');
|
|
6107
6109
|
El('#import-options').hide();
|
|
6108
6110
|
}
|
|
6109
6111
|
|
|
6112
|
+
function updateSidebarTabZIndex() {
|
|
6113
|
+
gui.container.classed('sidebar-tabs-over-popup',
|
|
6114
|
+
queuedFiles.length === 0 && !gui.sidebarPanelIsOpen());
|
|
6115
|
+
}
|
|
6116
|
+
|
|
6110
6117
|
function getFileNames(files) {
|
|
6111
6118
|
return Array.from(files).map(function(f) {return f.name;});
|
|
6112
6119
|
}
|
|
@@ -6726,13 +6733,11 @@
|
|
|
6726
6733
|
|
|
6727
6734
|
function message() {
|
|
6728
6735
|
var msg = GUI.formatMessageArgs(arguments);
|
|
6729
|
-
if (gui.notify) {
|
|
6730
|
-
gui.notify({severity: 'info', body: msg});
|
|
6731
|
-
} else {
|
|
6736
|
+
if (!gui.notify) {
|
|
6732
6737
|
// Fallback for early messages before MessageControl is constructed
|
|
6733
6738
|
gui.message(msg);
|
|
6734
|
-
internal.logArgs(arguments);
|
|
6735
6739
|
}
|
|
6740
|
+
internal.logArgs(arguments);
|
|
6736
6741
|
}
|
|
6737
6742
|
|
|
6738
6743
|
// CLI warnings used to surface as modal alerts, which interrupt the user
|
|
@@ -7929,7 +7934,7 @@
|
|
|
7929
7934
|
function Console(gui) {
|
|
7930
7935
|
var model = gui.model;
|
|
7931
7936
|
var CURSOR = '$ ';
|
|
7932
|
-
var PROMPT = 'Enter mapshaper commands or type "tips" for
|
|
7937
|
+
var PROMPT = 'Enter mapshaper commands or type "tips" for console help.';
|
|
7933
7938
|
var el = gui.container.findChild('.console').hide();
|
|
7934
7939
|
var content = el.findChild('.console-buffer');
|
|
7935
7940
|
var log = El('div').appendTo(content);
|
|
@@ -7950,6 +7955,7 @@
|
|
|
7950
7955
|
.on('keydown', function(e) {
|
|
7951
7956
|
if (e.key == 'Enter' || e.key == ' ') {
|
|
7952
7957
|
e.preventDefault();
|
|
7958
|
+
e.stopPropagation();
|
|
7953
7959
|
toggle();
|
|
7954
7960
|
}
|
|
7955
7961
|
});
|
|
@@ -7965,7 +7971,7 @@
|
|
|
7965
7971
|
this.runCommand = function(str) {
|
|
7966
7972
|
str = str.trim();
|
|
7967
7973
|
if (!str) return;
|
|
7968
|
-
|
|
7974
|
+
gui.setSidebarPanel('console');
|
|
7969
7975
|
submit(str);
|
|
7970
7976
|
};
|
|
7971
7977
|
|
|
@@ -7983,10 +7989,17 @@
|
|
|
7983
7989
|
});
|
|
7984
7990
|
|
|
7985
7991
|
function toggle() {
|
|
7986
|
-
|
|
7987
|
-
else turnOn();
|
|
7992
|
+
gui.toggleSidebarPanel('console');
|
|
7988
7993
|
}
|
|
7989
7994
|
|
|
7995
|
+
gui.on('sidebar', function(e) {
|
|
7996
|
+
if (e.name == 'console') {
|
|
7997
|
+
turnOn();
|
|
7998
|
+
} else if (e.prev == 'console') {
|
|
7999
|
+
turnOff();
|
|
8000
|
+
}
|
|
8001
|
+
});
|
|
8002
|
+
|
|
7990
8003
|
function getHistory() {
|
|
7991
8004
|
return GUI.getSavedValue('console_history') || [];
|
|
7992
8005
|
}
|
|
@@ -8006,10 +8019,30 @@
|
|
|
8006
8019
|
scrollDown();
|
|
8007
8020
|
}
|
|
8008
8021
|
|
|
8022
|
+
function toLogNode(node, cname) {
|
|
8023
|
+
var msg = El('div').appendTo(log);
|
|
8024
|
+
if (cname) {
|
|
8025
|
+
msg.addClass(cname);
|
|
8026
|
+
}
|
|
8027
|
+
msg.node().appendChild(node);
|
|
8028
|
+
scrollDown();
|
|
8029
|
+
}
|
|
8030
|
+
|
|
8031
|
+
function getStructuredConsoleMessage(args) {
|
|
8032
|
+
var arr = utils$1.toArray(args);
|
|
8033
|
+
var msg;
|
|
8034
|
+
// print() sends its arguments as one array argument.
|
|
8035
|
+
if (arr.length == 1 && Array.isArray(arr[0])) {
|
|
8036
|
+
arr = arr[0];
|
|
8037
|
+
}
|
|
8038
|
+
msg = arr[arr.length - 1];
|
|
8039
|
+
return msg && msg.type && /^mapshaper-console-/.test(msg.type) ? msg : null;
|
|
8040
|
+
}
|
|
8041
|
+
|
|
8009
8042
|
function turnOn() {
|
|
8010
8043
|
// if (!_isOpen && !model.isEmpty()) {
|
|
8011
8044
|
if (!_isOpen) {
|
|
8012
|
-
btn.addClass('active');
|
|
8045
|
+
btn.addClass('active').attr('aria-expanded', 'true');
|
|
8013
8046
|
_isOpen = true;
|
|
8014
8047
|
// Route logging output to the in-app console while it's open, so a
|
|
8015
8048
|
// user typing CLI commands here sees the results inline -- the same
|
|
@@ -8021,9 +8054,7 @@
|
|
|
8021
8054
|
// gui instances with the console open. E.g. console could close
|
|
8022
8055
|
// when an instance loses focus.
|
|
8023
8056
|
internal.setLoggingFunctions(consoleMessage, consoleError, consoleStop, consoleWarn);
|
|
8024
|
-
gui.container.addClass('console-open');
|
|
8025
8057
|
el.show();
|
|
8026
|
-
gui.dispatchEvent('resize');
|
|
8027
8058
|
input.node().focus();
|
|
8028
8059
|
history = getHistory();
|
|
8029
8060
|
}
|
|
@@ -8031,7 +8062,7 @@
|
|
|
8031
8062
|
|
|
8032
8063
|
function turnOff() {
|
|
8033
8064
|
if (_isOpen) {
|
|
8034
|
-
btn.removeClass('active');
|
|
8065
|
+
btn.removeClass('active').attr('aria-expanded', 'false');
|
|
8035
8066
|
_isOpen = false;
|
|
8036
8067
|
if (GUI.isActiveInstance(gui)) {
|
|
8037
8068
|
setLoggingForGUI(gui); // reset stop, message and error functions
|
|
@@ -8039,8 +8070,6 @@
|
|
|
8039
8070
|
el.hide();
|
|
8040
8071
|
input.node().blur();
|
|
8041
8072
|
saveHistory();
|
|
8042
|
-
gui.container.removeClass('console-open');
|
|
8043
|
-
gui.dispatchEvent('resize');
|
|
8044
8073
|
}
|
|
8045
8074
|
}
|
|
8046
8075
|
|
|
@@ -8100,7 +8129,7 @@
|
|
|
8100
8129
|
if (gui.getMode()) {
|
|
8101
8130
|
gui.clearMode(); // esc closes any open panels
|
|
8102
8131
|
} else {
|
|
8103
|
-
|
|
8132
|
+
gui.setSidebarPanel(null);
|
|
8104
8133
|
}
|
|
8105
8134
|
capture = true;
|
|
8106
8135
|
|
|
@@ -8136,8 +8165,8 @@
|
|
|
8136
8165
|
} else if (kc == 40) {
|
|
8137
8166
|
forward();
|
|
8138
8167
|
} else if (kc == 32 && (!typing || (inputText === '' && typingInConsole))) {
|
|
8139
|
-
// space bar
|
|
8140
|
-
|
|
8168
|
+
// space bar toggles the sidebar if nothing has been typed
|
|
8169
|
+
gui.toggleSidebar();
|
|
8141
8170
|
} else if (!typing && e.target != input.node() && !metaKey(e)) {
|
|
8142
8171
|
// typing returns focus, unless a meta key is down (to allow Cmd-C copy)
|
|
8143
8172
|
// or user is typing in a different input area somewhere
|
|
@@ -8154,9 +8183,9 @@
|
|
|
8154
8183
|
|
|
8155
8184
|
// various shortcuts (while not typing in an input field or editable el)
|
|
8156
8185
|
} else if (!typing) {
|
|
8157
|
-
if (kc == 32) { // space bar
|
|
8186
|
+
if (kc == 32) { // space bar toggles the sidebar
|
|
8158
8187
|
capture = true;
|
|
8159
|
-
|
|
8188
|
+
gui.toggleSidebar();
|
|
8160
8189
|
// } else if (kc == 73) { // letter i opens inspector
|
|
8161
8190
|
// gui.dispatchEvent('interaction_toggle');
|
|
8162
8191
|
} else if (kc == 72) { // letter h resets map extent
|
|
@@ -8537,9 +8566,15 @@
|
|
|
8537
8566
|
}
|
|
8538
8567
|
|
|
8539
8568
|
function consoleMessage() {
|
|
8540
|
-
var
|
|
8569
|
+
var structured = getStructuredConsoleMessage(arguments);
|
|
8570
|
+
var msg;
|
|
8541
8571
|
if (internal.loggingEnabled()) {
|
|
8542
|
-
|
|
8572
|
+
if (structured) {
|
|
8573
|
+
toLogNode(renderStructuredConsoleMessage(structured), 'console-message');
|
|
8574
|
+
} else {
|
|
8575
|
+
msg = GUI.formatMessageArgs(arguments);
|
|
8576
|
+
toLog(msg, 'console-message');
|
|
8577
|
+
}
|
|
8543
8578
|
}
|
|
8544
8579
|
}
|
|
8545
8580
|
|
|
@@ -8564,6 +8599,137 @@
|
|
|
8564
8599
|
printExample("Clear the console", "$ clear");
|
|
8565
8600
|
}
|
|
8566
8601
|
|
|
8602
|
+
function renderStructuredConsoleMessage(msg) {
|
|
8603
|
+
if (msg.type == 'mapshaper-console-help') {
|
|
8604
|
+
return renderHelpMessage(msg.lines);
|
|
8605
|
+
}
|
|
8606
|
+
if (msg.type == 'mapshaper-console-info') {
|
|
8607
|
+
return renderInfoMessage(msg.layers);
|
|
8608
|
+
}
|
|
8609
|
+
return document.createTextNode('');
|
|
8610
|
+
}
|
|
8611
|
+
|
|
8612
|
+
function renderHelpMessage(lines) {
|
|
8613
|
+
var container = document.createElement('div');
|
|
8614
|
+
var rows = [];
|
|
8615
|
+
container.className = 'console-help';
|
|
8616
|
+
(lines || []).forEach(function(line) {
|
|
8617
|
+
if (Array.isArray(line)) {
|
|
8618
|
+
rows.push(line);
|
|
8619
|
+
} else {
|
|
8620
|
+
flushRows();
|
|
8621
|
+
appendHelpLine(container, line);
|
|
8622
|
+
}
|
|
8623
|
+
});
|
|
8624
|
+
flushRows();
|
|
8625
|
+
return container;
|
|
8626
|
+
|
|
8627
|
+
function flushRows() {
|
|
8628
|
+
if (rows.length > 0) {
|
|
8629
|
+
container.appendChild(renderKeyValueTable(rows, 'console-help-table'));
|
|
8630
|
+
rows = [];
|
|
8631
|
+
}
|
|
8632
|
+
}
|
|
8633
|
+
}
|
|
8634
|
+
|
|
8635
|
+
function appendHelpLine(container, line) {
|
|
8636
|
+
var div = document.createElement('div');
|
|
8637
|
+
div.className = line ? 'console-help-line' : 'console-help-spacer';
|
|
8638
|
+
div.textContent = line || '';
|
|
8639
|
+
container.appendChild(div);
|
|
8640
|
+
}
|
|
8641
|
+
|
|
8642
|
+
function renderInfoMessage(layers) {
|
|
8643
|
+
var container = document.createElement('div');
|
|
8644
|
+
container.className = 'console-info';
|
|
8645
|
+
(layers || []).forEach(function(info) {
|
|
8646
|
+
var section = document.createElement('div');
|
|
8647
|
+
var title = document.createElement('div');
|
|
8648
|
+
section.className = 'console-info-layer';
|
|
8649
|
+
title.className = 'console-info-title';
|
|
8650
|
+
title.textContent = 'Layer: ' + (info.layer_name || '[unnamed layer]');
|
|
8651
|
+
section.appendChild(title);
|
|
8652
|
+
section.appendChild(renderKeyValueTable(getInfoRows(info), 'console-info-table'));
|
|
8653
|
+
section.appendChild(renderAttributeInfoTable(info.attribute_data));
|
|
8654
|
+
container.appendChild(section);
|
|
8655
|
+
});
|
|
8656
|
+
return container;
|
|
8657
|
+
}
|
|
8658
|
+
|
|
8659
|
+
function getInfoRows(info) {
|
|
8660
|
+
var rows = [
|
|
8661
|
+
['Type', info.geometry_type || 'tabular data'],
|
|
8662
|
+
['Records', utils$1.format('%,d', info.feature_count)]
|
|
8663
|
+
];
|
|
8664
|
+
if (info.null_shape_count > 0) {
|
|
8665
|
+
rows.push(['Nulls', utils$1.format("%'d", info.null_shape_count)]);
|
|
8666
|
+
}
|
|
8667
|
+
if (info.geometry_type && info.feature_count > info.null_shape_count) {
|
|
8668
|
+
rows.push(['Bounds', info.bbox.join(',')]);
|
|
8669
|
+
rows.push(['CRS', info.proj4]);
|
|
8670
|
+
}
|
|
8671
|
+
rows.push(['Source', info.source_file || 'n/a']);
|
|
8672
|
+
return rows;
|
|
8673
|
+
}
|
|
8674
|
+
|
|
8675
|
+
function renderAttributeInfoTable(fields) {
|
|
8676
|
+
var wrapper = document.createElement('div');
|
|
8677
|
+
var title = document.createElement('div');
|
|
8678
|
+
wrapper.className = 'console-attribute-info';
|
|
8679
|
+
title.className = 'console-info-subtitle';
|
|
8680
|
+
title.textContent = 'Attribute data';
|
|
8681
|
+
wrapper.appendChild(title);
|
|
8682
|
+
if (!fields) {
|
|
8683
|
+
var none = document.createElement('div');
|
|
8684
|
+
none.className = 'console-info-empty';
|
|
8685
|
+
none.textContent = '[none]';
|
|
8686
|
+
wrapper.appendChild(none);
|
|
8687
|
+
return wrapper;
|
|
8688
|
+
}
|
|
8689
|
+
wrapper.appendChild(renderDataTable(
|
|
8690
|
+
[['Field', 'First value']].concat(fields.map(function(o) {
|
|
8691
|
+
var valKey = 'first_value' in o ? 'first_value' : 'value';
|
|
8692
|
+
return [o.field, formatInfoValue(o[valKey])];
|
|
8693
|
+
})),
|
|
8694
|
+
'console-attribute-table'
|
|
8695
|
+
));
|
|
8696
|
+
return wrapper;
|
|
8697
|
+
}
|
|
8698
|
+
|
|
8699
|
+
function renderKeyValueTable(rows, className) {
|
|
8700
|
+
return renderDataTable(rows, className + ' console-key-value-table');
|
|
8701
|
+
}
|
|
8702
|
+
|
|
8703
|
+
function renderDataTable(rows, className) {
|
|
8704
|
+
var table = document.createElement('table');
|
|
8705
|
+
var tbody = document.createElement('tbody');
|
|
8706
|
+
table.className = className;
|
|
8707
|
+
rows.forEach(function(row, i) {
|
|
8708
|
+
var tr = document.createElement('tr');
|
|
8709
|
+
row.forEach(function(val) {
|
|
8710
|
+
var cell = document.createElement(i === 0 && rows.length > 1 && className == 'console-attribute-table' ? 'th' : 'td');
|
|
8711
|
+
cell.textContent = val == null ? '' : String(val);
|
|
8712
|
+
tr.appendChild(cell);
|
|
8713
|
+
});
|
|
8714
|
+
tbody.appendChild(tr);
|
|
8715
|
+
});
|
|
8716
|
+
table.appendChild(tbody);
|
|
8717
|
+
return table;
|
|
8718
|
+
}
|
|
8719
|
+
|
|
8720
|
+
function formatInfoValue(val) {
|
|
8721
|
+
if (val === null || val === undefined) return '';
|
|
8722
|
+
if (utils$1.isString(val)) {
|
|
8723
|
+
return "'" + val.replace(/[\r\t\n]/g, function(c) {
|
|
8724
|
+
return c == '\n' ? '\\n' : c == '\r' ? '\\r' : '\\t';
|
|
8725
|
+
}) + "'";
|
|
8726
|
+
}
|
|
8727
|
+
if (utils$1.isNumber(val) || val === true || val === false) {
|
|
8728
|
+
return String(val);
|
|
8729
|
+
}
|
|
8730
|
+
return JSON.stringify(val);
|
|
8731
|
+
}
|
|
8732
|
+
|
|
8567
8733
|
function saveRuntimeContext() {
|
|
8568
8734
|
var json = stringifyRuntimeStateContext(gui);
|
|
8569
8735
|
saveBlobToLocalFile2('mapshaper-runtime-context.json', new Blob([json], {type: 'application/json'}));
|
|
@@ -9150,6 +9316,7 @@
|
|
|
9150
9316
|
}
|
|
9151
9317
|
|
|
9152
9318
|
var openMenu;
|
|
9319
|
+
var openMenuId;
|
|
9153
9320
|
|
|
9154
9321
|
document.addEventListener('mousedown', function(e) {
|
|
9155
9322
|
if (e.target.classList.contains('contextmenu-item')) {
|
|
@@ -9158,17 +9325,23 @@
|
|
|
9158
9325
|
closeOpenMenu();
|
|
9159
9326
|
});
|
|
9160
9327
|
|
|
9161
|
-
function closeOpenMenu() {
|
|
9328
|
+
function closeOpenMenu(immediate) {
|
|
9162
9329
|
if (openMenu) {
|
|
9163
|
-
openMenu.close();
|
|
9330
|
+
openMenu.close(immediate);
|
|
9164
9331
|
openMenu = null;
|
|
9332
|
+
openMenuId = null;
|
|
9165
9333
|
}
|
|
9166
9334
|
}
|
|
9167
9335
|
|
|
9168
9336
|
function openContextMenu(e, lyr, parent) {
|
|
9169
9337
|
var menu = new ContextMenu(parent);
|
|
9170
|
-
|
|
9338
|
+
if (e.contextMenuId && e.contextMenuId == openMenuId) {
|
|
9339
|
+
closeOpenMenu(true);
|
|
9340
|
+
return;
|
|
9341
|
+
}
|
|
9342
|
+
closeOpenMenu(true);
|
|
9171
9343
|
menu.open(e, lyr);
|
|
9344
|
+
openMenuId = e.contextMenuId || null;
|
|
9172
9345
|
}
|
|
9173
9346
|
|
|
9174
9347
|
function ContextMenu(parentArg) {
|
|
@@ -9185,9 +9358,14 @@
|
|
|
9185
9358
|
|
|
9186
9359
|
this.close = close;
|
|
9187
9360
|
|
|
9188
|
-
function close() {
|
|
9361
|
+
function close(immediate) {
|
|
9189
9362
|
var count = _openCount;
|
|
9190
9363
|
if (!_open) return;
|
|
9364
|
+
if (immediate) {
|
|
9365
|
+
menu.hide();
|
|
9366
|
+
_open = false;
|
|
9367
|
+
return;
|
|
9368
|
+
}
|
|
9191
9369
|
setTimeout(function() {
|
|
9192
9370
|
if (count == _openCount) {
|
|
9193
9371
|
menu.hide();
|
|
@@ -9348,8 +9526,10 @@
|
|
|
9348
9526
|
function LayerControl(gui) {
|
|
9349
9527
|
var model = gui.model;
|
|
9350
9528
|
var map = gui.map;
|
|
9351
|
-
var el = gui.container.findChild(".layer-control")
|
|
9529
|
+
var el = gui.container.findChild(".layer-control");
|
|
9352
9530
|
var btn = gui.container.findChild('.layer-control-btn');
|
|
9531
|
+
var headerBtn = btn.findChild('.active-layer-label');
|
|
9532
|
+
var tab = gui.container.findChild('.layer-tab');
|
|
9353
9533
|
var isOpen = false;
|
|
9354
9534
|
var cache = new DomCache();
|
|
9355
9535
|
var pinAll = el.findChild('.pin-all'); // button for toggling layer visibility
|
|
@@ -9359,7 +9539,34 @@
|
|
|
9359
9539
|
var dragging = false;
|
|
9360
9540
|
var layerOrderSlug;
|
|
9361
9541
|
|
|
9362
|
-
|
|
9542
|
+
headerBtn.on('click', function() {
|
|
9543
|
+
toggle();
|
|
9544
|
+
}).on('keydown', function(e) {
|
|
9545
|
+
if (e.key == 'Enter' || e.key == ' ') {
|
|
9546
|
+
e.preventDefault();
|
|
9547
|
+
e.stopPropagation();
|
|
9548
|
+
toggle();
|
|
9549
|
+
}
|
|
9550
|
+
});
|
|
9551
|
+
tab.on('click', toggle).on('keydown', function(e) {
|
|
9552
|
+
if (e.key == 'Enter' || e.key == ' ') {
|
|
9553
|
+
e.preventDefault();
|
|
9554
|
+
e.stopPropagation();
|
|
9555
|
+
toggle();
|
|
9556
|
+
}
|
|
9557
|
+
});
|
|
9558
|
+
|
|
9559
|
+
function toggle() {
|
|
9560
|
+
gui.toggleSidebarPanel('layers');
|
|
9561
|
+
}
|
|
9562
|
+
|
|
9563
|
+
gui.on('sidebar', function(e) {
|
|
9564
|
+
if (e.name == 'layers') {
|
|
9565
|
+
turnOn();
|
|
9566
|
+
} else if (e.prev == 'layers') {
|
|
9567
|
+
turnOff();
|
|
9568
|
+
}
|
|
9569
|
+
});
|
|
9363
9570
|
|
|
9364
9571
|
// kludge to show menu button after initial import dialog is dismissed
|
|
9365
9572
|
gui.on('mode', function(e) {
|
|
@@ -9445,53 +9652,33 @@
|
|
|
9445
9652
|
}
|
|
9446
9653
|
|
|
9447
9654
|
function turnOn() {
|
|
9655
|
+
if (isOpen) return;
|
|
9448
9656
|
isOpen = true;
|
|
9449
|
-
|
|
9657
|
+
tab.addClass('active').attr('aria-expanded', 'true');
|
|
9450
9658
|
render();
|
|
9451
9659
|
el.show();
|
|
9452
9660
|
}
|
|
9453
9661
|
|
|
9454
9662
|
function turnOff() {
|
|
9663
|
+
if (!isOpen) return;
|
|
9455
9664
|
stopDragging();
|
|
9456
9665
|
isOpen = false;
|
|
9666
|
+
tab.removeClass('active').attr('aria-expanded', 'false');
|
|
9457
9667
|
el.hide();
|
|
9458
9668
|
}
|
|
9459
9669
|
|
|
9460
9670
|
function updateMenuBtn() {
|
|
9461
9671
|
var lyr = model.getActiveLayer()?.layer;
|
|
9462
9672
|
var lyrName = lyr?.name || '';
|
|
9463
|
-
var menuTitle = lyrName || lyr && '[unnamed layer]' || '[no data]';
|
|
9464
9673
|
var pageTitle = lyrName || 'mapshaper';
|
|
9465
|
-
btn.classed('active',
|
|
9674
|
+
btn.classed('active', !!lyr);
|
|
9675
|
+
headerBtn.text(lyr ? 'Active: ' + formatLayerNameForDisplay(lyr.name) : '');
|
|
9466
9676
|
window.document.title = pageTitle;
|
|
9467
9677
|
}
|
|
9468
9678
|
|
|
9469
9679
|
function render() {
|
|
9470
9680
|
renderLayerList();
|
|
9471
|
-
renderSourceFileList();
|
|
9472
|
-
}
|
|
9473
|
-
|
|
9474
|
-
function renderSourceFileList() {
|
|
9475
9681
|
el.findChild('.no-layer-note').classed('hidden', model.getActiveLayer());
|
|
9476
|
-
el.findChild('.source-file-section').classed('hidden', !model.getActiveLayer());
|
|
9477
|
-
var list = el.findChild('.file-list');
|
|
9478
|
-
var files = [];
|
|
9479
|
-
list.empty();
|
|
9480
|
-
model.forEachLayer(function(lyr, dataset) {
|
|
9481
|
-
var file = internal.getLayerSourceFile(lyr, dataset);
|
|
9482
|
-
if (!file || files.includes(file)) return;
|
|
9483
|
-
files.push(file);
|
|
9484
|
-
var warnings = getWarnings(lyr, dataset);
|
|
9485
|
-
var html = '<div class="layer-item">';
|
|
9486
|
-
html += rowHTML('name', file);
|
|
9487
|
-
if (warnings) {
|
|
9488
|
-
// html += rowHTML('problems', warnings, 'layer-problems');
|
|
9489
|
-
html += rowHTML('', warnings, 'layer-problems');
|
|
9490
|
-
}
|
|
9491
|
-
html += '</div>';
|
|
9492
|
-
list.appendChild(El('div').html(html).firstChild());
|
|
9493
|
-
});
|
|
9494
|
-
|
|
9495
9682
|
}
|
|
9496
9683
|
|
|
9497
9684
|
function renderLayerList() {
|
|
@@ -9552,10 +9739,10 @@
|
|
|
9552
9739
|
html = '<!-- ' + lyr.menu_id + '--><div class="' + classes + '">';
|
|
9553
9740
|
html += rowHTML('name', '<span class="layer-name colored-text dot-underline">' + formatLayerNameForDisplay(lyr.name) + '</span>', 'row1');
|
|
9554
9741
|
html += rowHTML('contents', describeLyr(lyr, dataset));
|
|
9555
|
-
|
|
9742
|
+
html += '<span class="more-btn layer-btn" role="button" tabindex="0" aria-label="More layer options"></span>';
|
|
9556
9743
|
if (opts.pinnable) {
|
|
9557
|
-
html += '<img class="eye-btn black-eye" draggable="false" src="images/eye.png">';
|
|
9558
|
-
html += '<img class="eye-btn green-eye" draggable="false" src="images/eye2.png">';
|
|
9744
|
+
html += '<img class="eye-btn black-eye layer-btn" draggable="false" src="images/eye.png">';
|
|
9745
|
+
html += '<img class="eye-btn green-eye layer-btn" draggable="false" src="images/eye2.png">';
|
|
9559
9746
|
}
|
|
9560
9747
|
html += '</div>';
|
|
9561
9748
|
return html;
|
|
@@ -9563,8 +9750,10 @@
|
|
|
9563
9750
|
|
|
9564
9751
|
function initMouseEvents(entry, id, pinnable) {
|
|
9565
9752
|
entry.on('mouseover', init);
|
|
9753
|
+
entry.on('focusin', init);
|
|
9566
9754
|
function init() {
|
|
9567
9755
|
entry.removeEventListener('mouseover', init);
|
|
9756
|
+
entry.removeEventListener('focusin', init);
|
|
9568
9757
|
initMouseEvents2(entry, id, pinnable);
|
|
9569
9758
|
}
|
|
9570
9759
|
}
|
|
@@ -9580,10 +9769,6 @@
|
|
|
9580
9769
|
}
|
|
9581
9770
|
// start dragging when button is first pressed
|
|
9582
9771
|
if (e.buttons && !dragTargetId) {
|
|
9583
|
-
// don't start dragging if pointer is over the close button
|
|
9584
|
-
// (before, clicking this button wqs finicky -- the mouse had to remain
|
|
9585
|
-
// perfectly still between mousedown and mouseup)
|
|
9586
|
-
if (El(e.target).hasClass('close-btn')) return;
|
|
9587
9772
|
dragTargetId = id;
|
|
9588
9773
|
entry.addClass('drag-target');
|
|
9589
9774
|
}
|
|
@@ -9608,6 +9793,7 @@
|
|
|
9608
9793
|
}
|
|
9609
9794
|
|
|
9610
9795
|
function initMouseEvents2(entry, id, pinnable) {
|
|
9796
|
+
var moreBtn = entry.findChild('.more-btn');
|
|
9611
9797
|
initLayerDragging(entry, id);
|
|
9612
9798
|
|
|
9613
9799
|
function deleteLayer() {
|
|
@@ -9632,7 +9818,7 @@
|
|
|
9632
9818
|
}
|
|
9633
9819
|
}
|
|
9634
9820
|
|
|
9635
|
-
function selectLayer(
|
|
9821
|
+
function selectLayer() {
|
|
9636
9822
|
var target = findLayerById(id);
|
|
9637
9823
|
// don't select if user is typing or dragging
|
|
9638
9824
|
if (GUI.textIsSelected() || dragging) return;
|
|
@@ -9641,17 +9827,24 @@
|
|
|
9641
9827
|
if (!map.isActiveLayer(target.layer)) {
|
|
9642
9828
|
model.selectLayer(target.layer, target.dataset);
|
|
9643
9829
|
}
|
|
9644
|
-
// close menu after a delay
|
|
9645
|
-
if (closeMenu === true) setTimeout(function() {
|
|
9646
|
-
gui.clearMode();
|
|
9647
|
-
}, 230);
|
|
9648
9830
|
}
|
|
9649
9831
|
|
|
9650
|
-
|
|
9651
|
-
|
|
9652
|
-
|
|
9653
|
-
|
|
9654
|
-
|
|
9832
|
+
function openLayerMenu(e) {
|
|
9833
|
+
var menuEvent = e;
|
|
9834
|
+
e.stopPropagation();
|
|
9835
|
+
if (!isFinite(e.pageX) || !isFinite(e.pageY)) {
|
|
9836
|
+
var rect = moreBtn.node().getBoundingClientRect();
|
|
9837
|
+
menuEvent = {
|
|
9838
|
+
pageX: rect.right,
|
|
9839
|
+
pageY: rect.top + rect.height / 2
|
|
9840
|
+
};
|
|
9841
|
+
}
|
|
9842
|
+
menuEvent.deleteLayer = deleteLayer;
|
|
9843
|
+
menuEvent.selectLayer = selectLayer;
|
|
9844
|
+
menuEvent.contextMenuId = 'layer-' + id;
|
|
9845
|
+
openContextMenu(menuEvent, null, null);
|
|
9846
|
+
}
|
|
9847
|
+
|
|
9655
9848
|
|
|
9656
9849
|
if (pinnable) {
|
|
9657
9850
|
// init pin button
|
|
@@ -9694,18 +9887,22 @@
|
|
|
9694
9887
|
renameLayer(target, str);
|
|
9695
9888
|
});
|
|
9696
9889
|
|
|
9890
|
+
moreBtn.on('mousedown', function(e) {
|
|
9891
|
+
e.stopPropagation();
|
|
9892
|
+
});
|
|
9893
|
+
GUI.onClick(moreBtn, openLayerMenu);
|
|
9894
|
+
moreBtn.on('keydown', function(e) {
|
|
9895
|
+
if (e.key == 'Enter' || e.key == ' ') {
|
|
9896
|
+
e.preventDefault();
|
|
9897
|
+
openLayerMenu(e);
|
|
9898
|
+
}
|
|
9899
|
+
});
|
|
9900
|
+
|
|
9697
9901
|
// init click-to-select
|
|
9698
9902
|
GUI.onClick(entry, function() {
|
|
9699
|
-
selectLayer(
|
|
9903
|
+
selectLayer();
|
|
9700
9904
|
});
|
|
9701
9905
|
|
|
9702
|
-
GUI.onContextClick(entry, function(e) {
|
|
9703
|
-
e.deleteLayer = deleteLayer;
|
|
9704
|
-
e.selectLayer = selectLayer;
|
|
9705
|
-
// contextMenu.open(e);
|
|
9706
|
-
// openContextMenu(e, null, entry.node())
|
|
9707
|
-
openContextMenu(e, null, null);
|
|
9708
|
-
});
|
|
9709
9906
|
}
|
|
9710
9907
|
|
|
9711
9908
|
function describeLyr(lyr, dataset) {
|
|
@@ -9752,30 +9949,6 @@
|
|
|
9752
9949
|
}
|
|
9753
9950
|
}
|
|
9754
9951
|
|
|
9755
|
-
function getWarnings(lyr, dataset) {
|
|
9756
|
-
var file = internal.getLayerSourceFile(lyr, dataset);
|
|
9757
|
-
var missing = [];
|
|
9758
|
-
var msg;
|
|
9759
|
-
// show missing file warning for first layer in dataset
|
|
9760
|
-
// (assuming it represents the content of the original file)
|
|
9761
|
-
if (utils$1.endsWith(file, '.shp') && lyr == dataset.layers[0]) {
|
|
9762
|
-
if (!lyr.data) {
|
|
9763
|
-
missing.push('.dbf');
|
|
9764
|
-
}
|
|
9765
|
-
if (!dataset.info.wkt1 && !dataset.info.crs) {
|
|
9766
|
-
missing.push('.prj');
|
|
9767
|
-
}
|
|
9768
|
-
}
|
|
9769
|
-
if (missing.length) {
|
|
9770
|
-
msg = 'missing ' + missing.join(' and ') + ' data';
|
|
9771
|
-
}
|
|
9772
|
-
return msg;
|
|
9773
|
-
}
|
|
9774
|
-
|
|
9775
|
-
function describeSrc(lyr, dataset) {
|
|
9776
|
-
return internal.getLayerSourceFile(lyr, dataset);
|
|
9777
|
-
}
|
|
9778
|
-
|
|
9779
9952
|
function isPinnable(lyr) {
|
|
9780
9953
|
return internal.layerIsGeometric(lyr) || internal.layerHasFurniture(lyr);
|
|
9781
9954
|
}
|
|
@@ -9972,7 +10145,7 @@
|
|
|
9972
10145
|
function getRestoreDataNote(gui) {
|
|
9973
10146
|
var stats = getUndoPayloadStats(gui);
|
|
9974
10147
|
var bytes = stats ? stats.ownBytes || 0 : 0;
|
|
9975
|
-
return '
|
|
10148
|
+
return 'restore data stored on-disk: ' + formatBytes(bytes);
|
|
9976
10149
|
}
|
|
9977
10150
|
|
|
9978
10151
|
function getUndoPayloadStats(gui) {
|
|
@@ -11993,8 +12166,8 @@
|
|
|
11993
12166
|
// DELETE key
|
|
11994
12167
|
// delete pinned feature
|
|
11995
12168
|
// to help protect against inadvertent deletion, don't delete
|
|
11996
|
-
// when
|
|
11997
|
-
if (!gui.getMode() && !gui.
|
|
12169
|
+
// when a sidebar panel or popup menu is open
|
|
12170
|
+
if (!gui.getMode() && !gui.sidebarPanelIsOpen()) {
|
|
11998
12171
|
internal.deleteFeatureById(targetLayer, pinnedId());
|
|
11999
12172
|
self.clearSelection();
|
|
12000
12173
|
gui.model.updated({flags: 'filter'}); // signal map to update
|
|
@@ -18328,6 +18501,10 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
18328
18501
|
|
|
18329
18502
|
|
|
18330
18503
|
gui.state = {};
|
|
18504
|
+
var sidebarPanel = null;
|
|
18505
|
+
var lastSidebarPanel = 'console';
|
|
18506
|
+
var sidebarWidth = GUI.getSavedValue('sidebar_width') || 0;
|
|
18507
|
+
var sidebarResizeFrame = null;
|
|
18331
18508
|
|
|
18332
18509
|
var msgCount = 0;
|
|
18333
18510
|
var clearMsg;
|
|
@@ -18368,10 +18545,50 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
18368
18545
|
// if (gui.progressMessage) gui.progressMessage.hide();
|
|
18369
18546
|
};
|
|
18370
18547
|
|
|
18548
|
+
if (sidebarWidth) {
|
|
18549
|
+
setSidebarWidth(sidebarWidth);
|
|
18550
|
+
}
|
|
18551
|
+
|
|
18552
|
+
gui.getSidebarPanel = function() {
|
|
18553
|
+
return sidebarPanel;
|
|
18554
|
+
};
|
|
18555
|
+
|
|
18556
|
+
gui.setSidebarPanel = function(name) {
|
|
18557
|
+
var prev = sidebarPanel;
|
|
18558
|
+
sidebarPanel = name || null;
|
|
18559
|
+
if (sidebarPanel && gui.getMode()) {
|
|
18560
|
+
gui.clearMode();
|
|
18561
|
+
}
|
|
18562
|
+
if (sidebarPanel == prev) return;
|
|
18563
|
+
if (sidebarPanel) {
|
|
18564
|
+
lastSidebarPanel = sidebarPanel;
|
|
18565
|
+
}
|
|
18566
|
+
gui.container
|
|
18567
|
+
.classed('sidebar-open', !!sidebarPanel)
|
|
18568
|
+
.classed('layers-open', sidebarPanel == 'layers')
|
|
18569
|
+
.classed('console-open', sidebarPanel == 'console');
|
|
18570
|
+
gui.dispatchEvent('sidebar', {name: sidebarPanel, prev: prev});
|
|
18571
|
+
gui.dispatchEvent('resize');
|
|
18572
|
+
};
|
|
18573
|
+
|
|
18574
|
+
gui.toggleSidebarPanel = function(name) {
|
|
18575
|
+
gui.setSidebarPanel(sidebarPanel == name ? null : name);
|
|
18576
|
+
};
|
|
18577
|
+
|
|
18578
|
+
gui.toggleSidebar = function() {
|
|
18579
|
+
gui.setSidebarPanel(sidebarPanel ? null : lastSidebarPanel);
|
|
18580
|
+
};
|
|
18581
|
+
|
|
18582
|
+
gui.sidebarPanelIsOpen = function() {
|
|
18583
|
+
return !!sidebarPanel;
|
|
18584
|
+
};
|
|
18585
|
+
|
|
18371
18586
|
gui.consoleIsOpen = function() {
|
|
18372
|
-
return
|
|
18587
|
+
return sidebarPanel == 'console';
|
|
18373
18588
|
};
|
|
18374
18589
|
|
|
18590
|
+
initSidebarResizing();
|
|
18591
|
+
|
|
18375
18592
|
gui.getRuntimeStateContext = function() {
|
|
18376
18593
|
return getRuntimeStateContext(gui);
|
|
18377
18594
|
};
|
|
@@ -18413,6 +18630,50 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
18413
18630
|
}
|
|
18414
18631
|
|
|
18415
18632
|
return gui;
|
|
18633
|
+
|
|
18634
|
+
function initSidebarResizing() {
|
|
18635
|
+
var handle = gui.container.findChild('.sidebar-resize-handle');
|
|
18636
|
+
if (!handle) return;
|
|
18637
|
+
handle.on('mousedown', function(e) {
|
|
18638
|
+
if (!gui.sidebarPanelIsOpen()) return;
|
|
18639
|
+
e.preventDefault();
|
|
18640
|
+
e.stopPropagation();
|
|
18641
|
+
gui.container.addClass('sidebar-resizing');
|
|
18642
|
+
window.addEventListener('mousemove', onMove);
|
|
18643
|
+
window.addEventListener('mouseup', onRelease);
|
|
18644
|
+
});
|
|
18645
|
+
|
|
18646
|
+
function onMove(e) {
|
|
18647
|
+
setSidebarWidth(e.pageX);
|
|
18648
|
+
scheduleSidebarResize();
|
|
18649
|
+
}
|
|
18650
|
+
|
|
18651
|
+
function onRelease() {
|
|
18652
|
+
window.removeEventListener('mousemove', onMove);
|
|
18653
|
+
window.removeEventListener('mouseup', onRelease);
|
|
18654
|
+
gui.container.removeClass('sidebar-resizing');
|
|
18655
|
+
GUI.setSavedValue('sidebar_width', sidebarWidth);
|
|
18656
|
+
scheduleSidebarResize();
|
|
18657
|
+
}
|
|
18658
|
+
}
|
|
18659
|
+
|
|
18660
|
+
function setSidebarWidth(width) {
|
|
18661
|
+
sidebarWidth = clampSidebarWidth(width);
|
|
18662
|
+
gui.container.node().style.setProperty('--left-sidebar-width', sidebarWidth + 'px');
|
|
18663
|
+
}
|
|
18664
|
+
|
|
18665
|
+
function clampSidebarWidth(width) {
|
|
18666
|
+
var max = Math.min(720, Math.round(window.innerWidth * 0.6));
|
|
18667
|
+
return Math.max(220, Math.min(max, Math.round(width)));
|
|
18668
|
+
}
|
|
18669
|
+
|
|
18670
|
+
function scheduleSidebarResize() {
|
|
18671
|
+
if (sidebarResizeFrame) return;
|
|
18672
|
+
sidebarResizeFrame = requestAnimationFrame(function() {
|
|
18673
|
+
sidebarResizeFrame = null;
|
|
18674
|
+
gui.dispatchEvent('resize');
|
|
18675
|
+
});
|
|
18676
|
+
}
|
|
18416
18677
|
}
|
|
18417
18678
|
|
|
18418
18679
|
function createUndoTestApi(gui) {
|