mapshaper 0.6.61 → 0.6.62
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 +154 -134
- package/package.json +1 -1
- package/www/__New_Hampshire_Political_Boundaries.geojson +266 -0
- package/www/__mapshaper_snapshot_09-29.msx +0 -0
- package/www/index.html +3 -0
- package/www/mapshaper-gui.js +120 -77
- package/www/mapshaper.js +154 -134
- package/www/page.css +1 -1
|
Binary file
|
package/www/index.html
CHANGED
|
@@ -132,9 +132,12 @@
|
|
|
132
132
|
<div>
|
|
133
133
|
<div class="delete-btn btn dialog-btn">Delete</div>
|
|
134
134
|
<div class="filter-btn btn dialog-btn">Keep</div>
|
|
135
|
+
<div class="duplicate-btn btn dialog-btn">Duplicate</div>
|
|
135
136
|
<div class="split-btn btn dialog-btn">Split</div>
|
|
137
|
+
<div class="coords-btn btn dialog-btn">Coords</div>
|
|
136
138
|
<div class="cancel-btn btn dialog-btn">Clear</div>
|
|
137
139
|
</div>
|
|
140
|
+
<div class="box-coords selectable"></div>
|
|
138
141
|
</div>
|
|
139
142
|
</div>
|
|
140
143
|
|
package/www/mapshaper-gui.js
CHANGED
|
@@ -1070,35 +1070,6 @@
|
|
|
1070
1070
|
|
|
1071
1071
|
utils$1.inherit(Checkbox, EventDispatcher);
|
|
1072
1072
|
|
|
1073
|
-
function xSimpleButton(ref) {
|
|
1074
|
-
var _el = El(ref),
|
|
1075
|
-
_self = this,
|
|
1076
|
-
_active = !_el.hasClass('disabled');
|
|
1077
|
-
|
|
1078
|
-
_el.on('click', function(e) {
|
|
1079
|
-
if (_active) _self.dispatchEvent('click');
|
|
1080
|
-
return false;
|
|
1081
|
-
});
|
|
1082
|
-
|
|
1083
|
-
this.active = function(a) {
|
|
1084
|
-
if (a === void 0) return _active;
|
|
1085
|
-
if (a !== _active) {
|
|
1086
|
-
_active = a;
|
|
1087
|
-
_el.toggleClass('disabled');
|
|
1088
|
-
}
|
|
1089
|
-
return this;
|
|
1090
|
-
};
|
|
1091
|
-
|
|
1092
|
-
this.node = function() {return _el.node();};
|
|
1093
|
-
|
|
1094
|
-
function isVisible() {
|
|
1095
|
-
var el = _el.node();
|
|
1096
|
-
return el.offsetParent !== null;
|
|
1097
|
-
}
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
//utils.inherit(SimpleButton, EventDispatcher);
|
|
1101
|
-
|
|
1102
1073
|
function SimpleButton(ref) {
|
|
1103
1074
|
var _el = El(ref),
|
|
1104
1075
|
_active = !_el.hasClass('disabled');
|
|
@@ -1121,8 +1092,6 @@
|
|
|
1121
1092
|
return _el;
|
|
1122
1093
|
}
|
|
1123
1094
|
|
|
1124
|
-
// utils.inherit(SimpleButton, EventDispatcher);
|
|
1125
|
-
|
|
1126
1095
|
function showPopupAlert(msg, title) {
|
|
1127
1096
|
var self = {}, html = '';
|
|
1128
1097
|
var _cancel, _close;
|
|
@@ -1181,6 +1150,7 @@
|
|
|
1181
1150
|
function AlertControl(gui) {
|
|
1182
1151
|
var openAlert; // error popup
|
|
1183
1152
|
var openPopup; // any popup
|
|
1153
|
+
var quiet = false;
|
|
1184
1154
|
|
|
1185
1155
|
gui.addMode('alert', function() {}, closePopup);
|
|
1186
1156
|
|
|
@@ -1192,7 +1162,12 @@
|
|
|
1192
1162
|
gui.enterMode('alert');
|
|
1193
1163
|
};
|
|
1194
1164
|
|
|
1165
|
+
gui.quiet = function(flag) {
|
|
1166
|
+
quiet = !!flag;
|
|
1167
|
+
};
|
|
1168
|
+
|
|
1195
1169
|
gui.message = function(str, title) {
|
|
1170
|
+
if (quiet) return;
|
|
1196
1171
|
if (openPopup) return; // don't stomp on another popup
|
|
1197
1172
|
openPopup = showPopupAlert(str, title);
|
|
1198
1173
|
openPopup.onClose(function() {openPopup = null;});
|
|
@@ -4507,8 +4482,8 @@
|
|
|
4507
4482
|
}
|
|
4508
4483
|
};
|
|
4509
4484
|
|
|
4510
|
-
this.dataValueUpdated = function(
|
|
4511
|
-
var cmd = `-each 'd[${JSON.stringify(field)}] = ${JSON.stringify(value)}'
|
|
4485
|
+
this.dataValueUpdated = function(ids, field, value) {
|
|
4486
|
+
var cmd = `-each 'd[${JSON.stringify(field)}] = ${JSON.stringify(value)}' ids=${ids.join(",")}`;
|
|
4512
4487
|
commands.push(cmd);
|
|
4513
4488
|
};
|
|
4514
4489
|
|
|
@@ -4591,6 +4566,28 @@
|
|
|
4591
4566
|
return (e.ctrlKey || e.metaKey) && (e.shiftKey && e.key == 'z' || !e.shiftKey && e.key == 'y');
|
|
4592
4567
|
}
|
|
4593
4568
|
|
|
4569
|
+
function makeMultiDataSetter(ids) {
|
|
4570
|
+
if (ids.length == 1) return makeDataSetter(ids[0]);
|
|
4571
|
+
var target = gui.model.getActiveLayer();
|
|
4572
|
+
var recs = ids.map(id => copyRecord(target.layer.data.getRecordAt(id)));
|
|
4573
|
+
return function() {
|
|
4574
|
+
var data = target.layer.data.getRecords();
|
|
4575
|
+
for (var i=0; i<ids.length; i++) {
|
|
4576
|
+
data[ids[i]] = recs[i];
|
|
4577
|
+
}
|
|
4578
|
+
gui.dispatchEvent('popup-needs-refresh');
|
|
4579
|
+
};
|
|
4580
|
+
}
|
|
4581
|
+
|
|
4582
|
+
function makeDataSetter(id) {
|
|
4583
|
+
var target = gui.model.getActiveLayer();
|
|
4584
|
+
var rec = copyRecord(target.layer.data.getRecordAt(id));
|
|
4585
|
+
return function() {
|
|
4586
|
+
target.layer.data.getRecords()[id] = rec;
|
|
4587
|
+
gui.dispatchEvent('popup-needs-refresh');
|
|
4588
|
+
};
|
|
4589
|
+
}
|
|
4590
|
+
|
|
4594
4591
|
gui.keyboard.on('keydown', function(evt) {
|
|
4595
4592
|
var e = evt.originalEvent,
|
|
4596
4593
|
kc = e.keyCode;
|
|
@@ -4614,31 +4611,31 @@
|
|
|
4614
4611
|
var redo = function() {
|
|
4615
4612
|
setPointCoords(target, e.FID, e.endCoords);
|
|
4616
4613
|
};
|
|
4617
|
-
|
|
4618
|
-
}
|
|
4614
|
+
addHistoryState(undo, redo);
|
|
4615
|
+
});
|
|
4619
4616
|
|
|
4620
4617
|
// undo/redo label dragging
|
|
4621
4618
|
//
|
|
4622
4619
|
gui.on('label_dragstart', function(e) {
|
|
4623
|
-
stashedUndo =
|
|
4624
|
-
}
|
|
4620
|
+
stashedUndo = makeDataSetter(e.FID);
|
|
4621
|
+
});
|
|
4625
4622
|
|
|
4626
4623
|
gui.on('label_dragend', function(e) {
|
|
4627
|
-
var redo =
|
|
4628
|
-
|
|
4629
|
-
}
|
|
4624
|
+
var redo = makeDataSetter(e.FID);
|
|
4625
|
+
addHistoryState(stashedUndo, redo);
|
|
4626
|
+
});
|
|
4630
4627
|
|
|
4631
4628
|
// undo/redo data editing
|
|
4632
4629
|
// TODO: consider setting selected feature to the undo/redo target feature
|
|
4633
4630
|
//
|
|
4634
4631
|
gui.on('data_preupdate', function(e) {
|
|
4635
|
-
stashedUndo =
|
|
4636
|
-
}
|
|
4632
|
+
stashedUndo = makeMultiDataSetter(e.ids);
|
|
4633
|
+
});
|
|
4637
4634
|
|
|
4638
4635
|
gui.on('data_postupdate', function(e) {
|
|
4639
|
-
var redo =
|
|
4640
|
-
|
|
4641
|
-
}
|
|
4636
|
+
var redo = makeMultiDataSetter(e.ids);
|
|
4637
|
+
addHistoryState(stashedUndo, redo);
|
|
4638
|
+
});
|
|
4642
4639
|
|
|
4643
4640
|
gui.on('vertex_dragend', function(e) {
|
|
4644
4641
|
var target = e.data.target;
|
|
@@ -4657,8 +4654,8 @@
|
|
|
4657
4654
|
}
|
|
4658
4655
|
setVertexCoords(target, e.ids, endPoint);
|
|
4659
4656
|
};
|
|
4660
|
-
|
|
4661
|
-
}
|
|
4657
|
+
addHistoryState(undo, redo);
|
|
4658
|
+
});
|
|
4662
4659
|
|
|
4663
4660
|
gui.on('vertex_delete', function(e) {
|
|
4664
4661
|
// get vertex coords in data coordinates (not display coordinates);
|
|
@@ -4669,29 +4666,20 @@
|
|
|
4669
4666
|
var undo = function() {
|
|
4670
4667
|
insertVertex$1(e.data.target, e.vertex_id, p);
|
|
4671
4668
|
};
|
|
4672
|
-
|
|
4673
|
-
}
|
|
4669
|
+
addHistoryState(undo, redo);
|
|
4670
|
+
});
|
|
4674
4671
|
|
|
4675
4672
|
this.clear = function() {
|
|
4676
4673
|
reset();
|
|
4677
4674
|
};
|
|
4678
4675
|
|
|
4679
|
-
|
|
4680
|
-
var target = gui.model.getActiveLayer();
|
|
4681
|
-
var rec = copyRecord(target.layer.data.getRecordAt(id));
|
|
4682
|
-
return function() {
|
|
4683
|
-
target.layer.data.getRecords()[id] = rec;
|
|
4684
|
-
gui.dispatchEvent('popup-needs-refresh');
|
|
4685
|
-
};
|
|
4686
|
-
};
|
|
4687
|
-
|
|
4688
|
-
this.addHistoryState = function(undo, redo) {
|
|
4676
|
+
function addHistoryState(undo, redo) {
|
|
4689
4677
|
if (offset > 0) {
|
|
4690
4678
|
history.splice(-offset);
|
|
4691
4679
|
offset = 0;
|
|
4692
4680
|
}
|
|
4693
4681
|
history.push({undo, redo});
|
|
4694
|
-
}
|
|
4682
|
+
}
|
|
4695
4683
|
|
|
4696
4684
|
this.undo = function() {
|
|
4697
4685
|
var item = getHistoryItem();
|
|
@@ -6957,7 +6945,7 @@
|
|
|
6957
6945
|
};
|
|
6958
6946
|
}
|
|
6959
6947
|
|
|
6960
|
-
function
|
|
6948
|
+
function HitControl(gui, ext, mouse) {
|
|
6961
6949
|
var self = new EventDispatcher();
|
|
6962
6950
|
var storedData = noHitData(); // may include additional data from SVG symbol hit (e.g. hit node)
|
|
6963
6951
|
var selectionIds = [];
|
|
@@ -7032,7 +7020,7 @@
|
|
|
7032
7020
|
}
|
|
7033
7021
|
|
|
7034
7022
|
function pinnable() {
|
|
7035
|
-
return clickable() &&
|
|
7023
|
+
return clickable() && !selectable();
|
|
7036
7024
|
}
|
|
7037
7025
|
|
|
7038
7026
|
function draggable() {
|
|
@@ -7152,7 +7140,7 @@
|
|
|
7152
7140
|
|
|
7153
7141
|
// TODO: move pinning to inspection control?
|
|
7154
7142
|
if (clickable()) {
|
|
7155
|
-
updateSelectionState(
|
|
7143
|
+
updateSelectionState(convertClickDataToSelectionData(hitTest(e)));
|
|
7156
7144
|
}
|
|
7157
7145
|
triggerHitEvent('click', e.data);
|
|
7158
7146
|
}, null, priority);
|
|
@@ -7184,7 +7172,9 @@
|
|
|
7184
7172
|
|
|
7185
7173
|
function noHitData() {return {ids: [], id: -1, pinned: false};}
|
|
7186
7174
|
|
|
7187
|
-
|
|
7175
|
+
// Translates feature hit data from a mouse click into feature selection data
|
|
7176
|
+
// hitData: hit data from a mouse click
|
|
7177
|
+
function convertClickDataToSelectionData(hitData) {
|
|
7188
7178
|
// mergeCurrentState(hitData);
|
|
7189
7179
|
// TOGGLE pinned state under some conditions
|
|
7190
7180
|
var id = hitData.ids.length > 0 ? hitData.ids[0] : -1;
|
|
@@ -8146,6 +8136,7 @@
|
|
|
8146
8136
|
function SelectionTool(gui, ext, hit) {
|
|
8147
8137
|
var popup = gui.container.findChild('.selection-tool-options');
|
|
8148
8138
|
var box = new HighlightBox(gui);
|
|
8139
|
+
var coords = popup.findChild('.box-coords').hide();
|
|
8149
8140
|
var _on = false;
|
|
8150
8141
|
|
|
8151
8142
|
gui.addMode('selection_tool', turnOn, turnOff);
|
|
@@ -8214,8 +8205,10 @@
|
|
|
8214
8205
|
// (this closes any other active mode, e.g. box_tool)
|
|
8215
8206
|
gui.enterMode('selection_tool');
|
|
8216
8207
|
popup.show();
|
|
8208
|
+
updateCoords();
|
|
8217
8209
|
} else {
|
|
8218
8210
|
popup.hide();
|
|
8211
|
+
hideCoords();
|
|
8219
8212
|
}
|
|
8220
8213
|
});
|
|
8221
8214
|
|
|
@@ -8234,13 +8227,59 @@
|
|
|
8234
8227
|
runCommand(cmd);
|
|
8235
8228
|
});
|
|
8236
8229
|
|
|
8230
|
+
new SimpleButton(popup.findChild('.duplicate-btn')).on('click', function() {
|
|
8231
|
+
var cmd = '-filter + name=selection ids=' + getIdsOpt();
|
|
8232
|
+
runCommand(cmd);
|
|
8233
|
+
});
|
|
8234
|
+
|
|
8235
|
+
var coordsBtn = new SimpleButton(popup.findChild('.coords-btn')).on('click', function() {
|
|
8236
|
+
if (coords.visible()) hideCoords(); else showCoords();
|
|
8237
|
+
});
|
|
8238
|
+
|
|
8237
8239
|
new SimpleButton(popup.findChild('.cancel-btn')).on('click', function() {
|
|
8238
8240
|
hit.clearSelection();
|
|
8239
8241
|
});
|
|
8240
8242
|
|
|
8243
|
+
function getSelectionBounds() {
|
|
8244
|
+
var ids = hit.getSelectionIds();
|
|
8245
|
+
if (ids.length === 0) return null;
|
|
8246
|
+
var {layer, dataset} = gui.model.getActiveLayer();
|
|
8247
|
+
var filtered = {
|
|
8248
|
+
geometry_type: layer.geometry_type,
|
|
8249
|
+
shapes: ids.map(id => layer.shapes[id])
|
|
8250
|
+
};
|
|
8251
|
+
var bbox = internal.getLayerBounds(filtered, dataset.arcs).toArray();
|
|
8252
|
+
return internal.getRoundedCoords(bbox, internal.getBoundsPrecisionForDisplay(bbox));
|
|
8253
|
+
}
|
|
8254
|
+
|
|
8255
|
+
function updateCoords() {
|
|
8256
|
+
if (coords.visible()) {
|
|
8257
|
+
showCoords();
|
|
8258
|
+
}
|
|
8259
|
+
}
|
|
8260
|
+
|
|
8261
|
+
function showCoords() {
|
|
8262
|
+
var bbox = getSelectionBounds();
|
|
8263
|
+
if (!bbox) {
|
|
8264
|
+
hideCoords();
|
|
8265
|
+
return;
|
|
8266
|
+
}
|
|
8267
|
+
El(coordsBtn.node()).addClass('selected-btn');
|
|
8268
|
+
coords.text(bbox.join(','));
|
|
8269
|
+
coords.show();
|
|
8270
|
+
GUI.selectElement(coords.node());
|
|
8271
|
+
}
|
|
8272
|
+
|
|
8273
|
+
function hideCoords() {
|
|
8274
|
+
El(coordsBtn.node()).removeClass('selected-btn');
|
|
8275
|
+
coords.hide();
|
|
8276
|
+
}
|
|
8277
|
+
|
|
8241
8278
|
function runCommand(cmd, turnOff) {
|
|
8242
8279
|
popup.hide();
|
|
8280
|
+
gui.quiet(true);
|
|
8243
8281
|
if (gui.console) gui.console.runMapshaperCommands(cmd, function(err) {
|
|
8282
|
+
gui.quiet(false);
|
|
8244
8283
|
reset();
|
|
8245
8284
|
if (turnOff) gui.clearMode();
|
|
8246
8285
|
});
|
|
@@ -8260,7 +8299,7 @@
|
|
|
8260
8299
|
var navInfo = El('span').addClass('popup-nav-info').appendTo(nav);
|
|
8261
8300
|
var nextLink = El('span').addClass('popup-nav-arrow colored-text').appendTo(nav).text('▶');
|
|
8262
8301
|
var refresh = null;
|
|
8263
|
-
var
|
|
8302
|
+
var currIds = [];
|
|
8264
8303
|
|
|
8265
8304
|
el.addClass('rollover'); // used as a sentinel for the hover function
|
|
8266
8305
|
|
|
@@ -8273,7 +8312,7 @@
|
|
|
8273
8312
|
self.show = function(id, ids, lyr, pinned) {
|
|
8274
8313
|
var editable = pinned && gui.interaction.getMode() == 'data';
|
|
8275
8314
|
var maxHeight = parent.node().clientHeight - 36;
|
|
8276
|
-
|
|
8315
|
+
currIds = [id];
|
|
8277
8316
|
// stash a function for refreshing the current popup when data changes
|
|
8278
8317
|
// while the popup is being displayed (e.g. while dragging a label)
|
|
8279
8318
|
refresh = function() {
|
|
@@ -8294,7 +8333,7 @@
|
|
|
8294
8333
|
self.hide = function() {
|
|
8295
8334
|
if (!isOpen()) return;
|
|
8296
8335
|
refresh = null;
|
|
8297
|
-
|
|
8336
|
+
currIds = [];
|
|
8298
8337
|
// make sure any pending edits are made before re-rendering popup
|
|
8299
8338
|
GUI.blurActiveElement(); // this should be more selective -- could cause a glitch if typing in console
|
|
8300
8339
|
content.empty();
|
|
@@ -8317,6 +8356,7 @@
|
|
|
8317
8356
|
}
|
|
8318
8357
|
|
|
8319
8358
|
function render(el, recId, lyr, editable) {
|
|
8359
|
+
var recIds = [recId]; // TODO: support multiple ids
|
|
8320
8360
|
var table = lyr.data; // table can be null (e.g. if layer has no attribute data)
|
|
8321
8361
|
var rec = table && (editable ? table.getRecordAt(recId) : table.getReadOnlyRecordAt(recId)) || {};
|
|
8322
8362
|
var tableEl = El('table').addClass('selectable'),
|
|
@@ -8361,12 +8401,12 @@
|
|
|
8361
8401
|
var line = El('div').appendTo(el);
|
|
8362
8402
|
El('span').addClass('add-field-btn').appendTo(line).on('click', async function(e) {
|
|
8363
8403
|
// show "add field" dialog
|
|
8364
|
-
renderAddFieldPopup(
|
|
8404
|
+
renderAddFieldPopup(recIds, lyr);
|
|
8365
8405
|
}).text('+ add field');
|
|
8366
8406
|
}
|
|
8367
8407
|
}
|
|
8368
8408
|
|
|
8369
|
-
function renderAddFieldPopup(
|
|
8409
|
+
function renderAddFieldPopup(ids, lyr) {
|
|
8370
8410
|
var popup = showPopupAlert('', 'Add field');
|
|
8371
8411
|
var el = popup.container();
|
|
8372
8412
|
el.addClass('option-menu');
|
|
@@ -8397,9 +8437,12 @@
|
|
|
8397
8437
|
|
|
8398
8438
|
var cmdStr = `-each "d['${nameStr}'] = `;
|
|
8399
8439
|
if (!all) {
|
|
8400
|
-
cmdStr +=
|
|
8440
|
+
cmdStr += ids.length == 1 ?
|
|
8441
|
+
`this.id != ${ids[0]}` :
|
|
8442
|
+
`!${JSON.stringify(ids)}.includes(this.id)`;
|
|
8443
|
+
cmdStr += ' ? null : ';
|
|
8401
8444
|
}
|
|
8402
|
-
valStr = JSON.stringify(JSON.stringify(value));
|
|
8445
|
+
valStr = JSON.stringify(JSON.stringify(value)); // add escapes to strings
|
|
8403
8446
|
cmdStr = valStr.replace('"', cmdStr);
|
|
8404
8447
|
|
|
8405
8448
|
gui.console.runMapshaperCommands(cmdStr, function(err) {
|
|
@@ -8451,12 +8494,12 @@
|
|
|
8451
8494
|
} else if (strval != strval2) {
|
|
8452
8495
|
// field content has changed
|
|
8453
8496
|
strval = strval2;
|
|
8454
|
-
gui.dispatchEvent('data_preupdate', {
|
|
8497
|
+
gui.dispatchEvent('data_preupdate', {ids: currIds}); // for undo/redo
|
|
8455
8498
|
rec[key] = val2;
|
|
8456
|
-
gui.dispatchEvent('data_postupdate', {
|
|
8499
|
+
gui.dispatchEvent('data_postupdate', {ids: currIds});
|
|
8457
8500
|
input.value(strval);
|
|
8458
8501
|
setFieldClass(el, val2, type);
|
|
8459
|
-
self.dispatchEvent('
|
|
8502
|
+
self.dispatchEvent('data_updated', {field: key, value: val2, ids: currIds});
|
|
8460
8503
|
}
|
|
8461
8504
|
});
|
|
8462
8505
|
}
|
|
@@ -8540,10 +8583,10 @@
|
|
|
8540
8583
|
}
|
|
8541
8584
|
});
|
|
8542
8585
|
|
|
8543
|
-
_popup.on('
|
|
8586
|
+
_popup.on('data_updated', function(e) {
|
|
8544
8587
|
// data_change event no longer needed (update is handled below)
|
|
8545
8588
|
// _self.dispatchEvent('data_change', e.data); // let map know which field has changed
|
|
8546
|
-
gui.session.dataValueUpdated(e.
|
|
8589
|
+
gui.session.dataValueUpdated(e.ids, e.field, e.value);
|
|
8547
8590
|
// Refresh the display if a style variable has been changed interactively
|
|
8548
8591
|
if (internal.isSupportedSvgStyleProperty(e.field)) {
|
|
8549
8592
|
// drawLayers();
|
|
@@ -11325,7 +11368,7 @@
|
|
|
11325
11368
|
gui.buttons.show();
|
|
11326
11369
|
|
|
11327
11370
|
if (opts.inspectorControl) {
|
|
11328
|
-
_hit = new
|
|
11371
|
+
_hit = new HitControl(gui, _ext, _mouse),
|
|
11329
11372
|
new InspectionControl2(gui, _hit);
|
|
11330
11373
|
new SelectionTool(gui, _ext, _hit),
|
|
11331
11374
|
new BoxTool(gui, _ext, _nav),
|