mapshaper 0.6.65 → 0.6.66
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 +147 -33
- package/package.json +1 -1
- package/www/index.html +4 -3
- package/www/mapshaper-gui.js +379 -241
- package/www/mapshaper.js +147 -33
- package/www/page.css +7 -1
package/www/mapshaper-gui.js
CHANGED
|
@@ -1714,6 +1714,47 @@
|
|
|
1714
1714
|
}
|
|
1715
1715
|
}
|
|
1716
1716
|
|
|
1717
|
+
function openAddLayerPopup(gui) {
|
|
1718
|
+
var popup = showPopupAlert('', 'Add empty layer');
|
|
1719
|
+
var el = popup.container();
|
|
1720
|
+
el.addClass('option-menu');
|
|
1721
|
+
var html = `<div><input type="text" class="layer-name text-input" placeholder="layer name"></div>
|
|
1722
|
+
<div style="margin: 2px 0 4px;">
|
|
1723
|
+
Type:
|
|
1724
|
+
<label><input type="radio" name="geomtype" checked value="point" class="radio">point</label>
|
|
1725
|
+
<label><input type="radio" name="geomtype" value="polygon" class="radio">polygon</label>
|
|
1726
|
+
<label><input type="radio" name="geomtype" value="polyline" class="radio">line</label>
|
|
1727
|
+
</div>
|
|
1728
|
+
<div tabindex="0" class="btn dialog-btn">Create</div></span>`;
|
|
1729
|
+
el.html(html);
|
|
1730
|
+
var name = el.findChild('.layer-name');
|
|
1731
|
+
name.node().focus();
|
|
1732
|
+
var btn = el.findChild('.btn').on('click', function() {
|
|
1733
|
+
var nameStr = name.node().value.trim();
|
|
1734
|
+
var type = el.findChild('input:checked').node().value;
|
|
1735
|
+
addLayer(gui, nameStr, type);
|
|
1736
|
+
popup.close();
|
|
1737
|
+
});
|
|
1738
|
+
}
|
|
1739
|
+
|
|
1740
|
+
function addLayer(gui, name, type) {
|
|
1741
|
+
var targ = gui.model.getActiveLayer();
|
|
1742
|
+
var crsInfo = targ && internal.getDatasetCrsInfo(targ.dataset);
|
|
1743
|
+
var dataset = {
|
|
1744
|
+
layers: [{
|
|
1745
|
+
name: name || undefined,
|
|
1746
|
+
geometry_type: type,
|
|
1747
|
+
shapes: []
|
|
1748
|
+
}],
|
|
1749
|
+
info: {}
|
|
1750
|
+
};
|
|
1751
|
+
if (crsInfo) {
|
|
1752
|
+
internal.setDatasetCrsInfo(dataset, crsInfo);
|
|
1753
|
+
}
|
|
1754
|
+
gui.model.addDataset(dataset);
|
|
1755
|
+
gui.model.updated({select: true});
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1717
1758
|
// @cb function(<FileList>)
|
|
1718
1759
|
function DropControl(gui, el, cb) {
|
|
1719
1760
|
var area = El(el);
|
|
@@ -1832,7 +1873,10 @@
|
|
|
1832
1873
|
new FileChooser('#file-selection-btn', receiveFiles);
|
|
1833
1874
|
new FileChooser('#import-buttons .add-btn', receiveFiles);
|
|
1834
1875
|
new FileChooser('#add-file-btn', receiveFiles);
|
|
1835
|
-
|
|
1876
|
+
new SimpleButton('#add-empty-btn').on('click', function() {
|
|
1877
|
+
gui.clearMode(); // close import dialog
|
|
1878
|
+
openAddLayerPopup(gui);
|
|
1879
|
+
});
|
|
1836
1880
|
initDropArea('#import-quick-drop', true);
|
|
1837
1881
|
initDropArea('#import-drop');
|
|
1838
1882
|
gui.keyboard.onMenuSubmit(El('#import-options'), importQueuedFiles);
|
|
@@ -2040,18 +2084,7 @@
|
|
|
2040
2084
|
return true;
|
|
2041
2085
|
}
|
|
2042
2086
|
|
|
2043
|
-
|
|
2044
|
-
var dataset = {
|
|
2045
|
-
layers: [{
|
|
2046
|
-
name: 'New layer',
|
|
2047
|
-
geometry_type: 'point',
|
|
2048
|
-
shapes: []
|
|
2049
|
-
}],
|
|
2050
|
-
info: {}
|
|
2051
|
-
};
|
|
2052
|
-
model.addDataset(dataset);
|
|
2053
|
-
gui.clearMode();
|
|
2054
|
-
}
|
|
2087
|
+
|
|
2055
2088
|
|
|
2056
2089
|
function filesMayContainPaths(files) {
|
|
2057
2090
|
return utils$1.some(files, function(f) {
|
|
@@ -2565,6 +2598,7 @@
|
|
|
2565
2598
|
}
|
|
2566
2599
|
}
|
|
2567
2600
|
|
|
2601
|
+
// coords: [x, y] point in data CRS (not display CRS)
|
|
2568
2602
|
function setPointCoords(lyr, fid, coords) {
|
|
2569
2603
|
lyr.source.layer.shapes[fid] = coords;
|
|
2570
2604
|
if (isProjectedLayer(lyr)) {
|
|
@@ -2602,7 +2636,7 @@
|
|
|
2602
2636
|
return !!(lyr.source && lyr.invertPoint);
|
|
2603
2637
|
}
|
|
2604
2638
|
|
|
2605
|
-
// Update data coordinates by projecting display coordinates
|
|
2639
|
+
// Update source data coordinates by projecting display coordinates
|
|
2606
2640
|
function updatePointCoords(lyr, fid) {
|
|
2607
2641
|
if (!isProjectedLayer(lyr)) return;
|
|
2608
2642
|
var displayShp = lyr.layer.shapes[fid];
|
|
@@ -3875,7 +3909,7 @@
|
|
|
3875
3909
|
async function exportMenuSelection(targets) {
|
|
3876
3910
|
var opts = getExportOpts();
|
|
3877
3911
|
// note: command line "target" option gets ignored
|
|
3878
|
-
var files = await internal.exportTargetLayers(targets, opts);
|
|
3912
|
+
var files = await internal.exportTargetLayers(model, targets, opts);
|
|
3879
3913
|
gui.session.layersExported(getTargetLayerIds(), getExportOptsAsString());
|
|
3880
3914
|
if (files.length == 1 && checkboxOn(clipboardCheckbox)) {
|
|
3881
3915
|
await saveFileContentToClipboard(files[0].content);
|
|
@@ -4656,6 +4690,19 @@
|
|
|
4656
4690
|
addHistoryState(stashedUndo, redo);
|
|
4657
4691
|
});
|
|
4658
4692
|
|
|
4693
|
+
gui.on('rectangle_dragend', function(e) {
|
|
4694
|
+
var target = e.data.target;
|
|
4695
|
+
var points1 = e.points;
|
|
4696
|
+
var points2 = e.ids.map(id => getVertexCoords(target, id));
|
|
4697
|
+
var undo = function() {
|
|
4698
|
+
setRectangleCoords(target, e.ids, points1);
|
|
4699
|
+
};
|
|
4700
|
+
var redo = function() {
|
|
4701
|
+
setRectangleCoords(target, e.ids, points2);
|
|
4702
|
+
};
|
|
4703
|
+
addHistoryState(undo, redo);
|
|
4704
|
+
});
|
|
4705
|
+
|
|
4659
4706
|
gui.on('vertex_dragend', function(e) {
|
|
4660
4707
|
var target = e.data.target;
|
|
4661
4708
|
var startPoint = e.points[0]; // in data coords
|
|
@@ -4701,6 +4748,9 @@
|
|
|
4701
4748
|
}
|
|
4702
4749
|
|
|
4703
4750
|
this.undo = function() {
|
|
4751
|
+
// firing even if history is empty
|
|
4752
|
+
// (because this event may trigger a new history state)
|
|
4753
|
+
gui.dispatchEvent('undo_redo_pre');
|
|
4704
4754
|
var item = getHistoryItem();
|
|
4705
4755
|
if (item) {
|
|
4706
4756
|
offset++;
|
|
@@ -4710,6 +4760,7 @@
|
|
|
4710
4760
|
};
|
|
4711
4761
|
|
|
4712
4762
|
this.redo = function() {
|
|
4763
|
+
gui.dispatchEvent('undo_redo_pre');
|
|
4713
4764
|
if (offset <= 0) return;
|
|
4714
4765
|
offset--;
|
|
4715
4766
|
var item = getHistoryItem();
|
|
@@ -4783,6 +4834,30 @@
|
|
|
4783
4834
|
});
|
|
4784
4835
|
}
|
|
4785
4836
|
|
|
4837
|
+
function ToggleButton(el) {
|
|
4838
|
+
var btn = El(el),
|
|
4839
|
+
self = new EventDispatcher(),
|
|
4840
|
+
on = false;
|
|
4841
|
+
|
|
4842
|
+
btn.on('click', function(e) {
|
|
4843
|
+
on = !on;
|
|
4844
|
+
btn.classed('active', on);
|
|
4845
|
+
self.dispatchEvent('click', {on: on, active: on});
|
|
4846
|
+
});
|
|
4847
|
+
|
|
4848
|
+
self.turnOff = function() {
|
|
4849
|
+
on = false;
|
|
4850
|
+
btn.removeClass('active');
|
|
4851
|
+
};
|
|
4852
|
+
|
|
4853
|
+
self.turnOn = function() {
|
|
4854
|
+
on = true;
|
|
4855
|
+
btn.addClass('active');
|
|
4856
|
+
};
|
|
4857
|
+
|
|
4858
|
+
return self;
|
|
4859
|
+
}
|
|
4860
|
+
|
|
4786
4861
|
function ModeSwitcher() {
|
|
4787
4862
|
var self = this;
|
|
4788
4863
|
var mode = null;
|
|
@@ -4872,11 +4947,10 @@
|
|
|
4872
4947
|
standard: ['info', 'selection', 'data', 'box'],
|
|
4873
4948
|
polygons: ['info', 'selection', 'data', 'box', 'vertices'],
|
|
4874
4949
|
rectangles: ['info', 'selection', 'data', 'box', 'rectangles', 'vertices'],
|
|
4875
|
-
lines: ['info', 'selection', 'data', 'box', 'vertices'],
|
|
4950
|
+
lines: ['info', 'selection', 'data', 'box', 'vertices' /*, 'draw-lines'*/],
|
|
4876
4951
|
table: ['info', 'selection', 'data'],
|
|
4877
|
-
labels: ['info', 'selection', 'data', 'box', 'labels', 'location'],
|
|
4878
|
-
|
|
4879
|
-
points: ['info', 'selection', 'data', 'box', 'location']
|
|
4952
|
+
labels: ['info', 'selection', 'data', 'box', 'labels', 'location', 'add-points'],
|
|
4953
|
+
points: ['info', 'selection', 'data', 'box', 'location', 'add-points']
|
|
4880
4954
|
};
|
|
4881
4955
|
|
|
4882
4956
|
var prompts = {
|
|
@@ -4895,6 +4969,7 @@
|
|
|
4895
4969
|
vertices: 'edit vertices',
|
|
4896
4970
|
selection: 'select features',
|
|
4897
4971
|
'add-points': 'add points',
|
|
4972
|
+
'draw-lines': 'draw lines',
|
|
4898
4973
|
rectangles: 'drag-to-resize',
|
|
4899
4974
|
off: 'turn off'
|
|
4900
4975
|
};
|
|
@@ -5138,7 +5213,9 @@
|
|
|
5138
5213
|
};
|
|
5139
5214
|
|
|
5140
5215
|
self.selectLayer = function(lyr, dataset) {
|
|
5141
|
-
if (self.getActiveLayer().layer == lyr)
|
|
5216
|
+
if (self.getActiveLayer().layer == lyr) {
|
|
5217
|
+
return;
|
|
5218
|
+
}
|
|
5142
5219
|
self.setDefaultTarget([lyr], dataset);
|
|
5143
5220
|
self.updated({select: true});
|
|
5144
5221
|
gui.session.setTargetLayer(lyr);
|
|
@@ -6844,7 +6921,6 @@
|
|
|
6844
6921
|
return internal.svg.getTransform(p, scale);
|
|
6845
6922
|
}
|
|
6846
6923
|
|
|
6847
|
-
|
|
6848
6924
|
function repositionSymbols(elements, layer, ext) {
|
|
6849
6925
|
var el, idx, shp, p, displayOn, inView, displayBounds;
|
|
6850
6926
|
for (var i=0, n=elements.length; i<n; i++) {
|
|
@@ -6868,7 +6944,7 @@
|
|
|
6868
6944
|
}
|
|
6869
6945
|
}
|
|
6870
6946
|
|
|
6871
|
-
function renderSymbols(lyr, ext
|
|
6947
|
+
function renderSymbols(lyr, ext) {
|
|
6872
6948
|
var records = lyr.data.getRecords();
|
|
6873
6949
|
var symbols = lyr.shapes.map(function(shp, i) {
|
|
6874
6950
|
var d = records[i];
|
|
@@ -6976,6 +7052,8 @@
|
|
|
6976
7052
|
var interactionMode;
|
|
6977
7053
|
var targetLayer;
|
|
6978
7054
|
var hitTest;
|
|
7055
|
+
var pinnedOn; // used in multi-edit mode (selection) for toggling pinning behavior
|
|
7056
|
+
|
|
6979
7057
|
// event priority is higher than navigation, so stopping propagation disables
|
|
6980
7058
|
// pan navigation
|
|
6981
7059
|
var priority = 2;
|
|
@@ -7034,6 +7112,7 @@
|
|
|
7034
7112
|
updateSelectionState(null); // no hit data, no event
|
|
7035
7113
|
active = false;
|
|
7036
7114
|
hitTest = null;
|
|
7115
|
+
pinnedOn = false;
|
|
7037
7116
|
}
|
|
7038
7117
|
}
|
|
7039
7118
|
|
|
@@ -7070,6 +7149,13 @@
|
|
|
7070
7149
|
updateSelectionState({ids: ids});
|
|
7071
7150
|
};
|
|
7072
7151
|
|
|
7152
|
+
self.setPinning = function(val) {
|
|
7153
|
+
if (pinnedOn != val) {
|
|
7154
|
+
pinnedOn = val;
|
|
7155
|
+
triggerHitEvent('change');
|
|
7156
|
+
}
|
|
7157
|
+
};
|
|
7158
|
+
|
|
7073
7159
|
self.setTransientIds = function(ids) {
|
|
7074
7160
|
// turnOn('selection');
|
|
7075
7161
|
transientIds = ids || [];
|
|
@@ -7139,7 +7225,7 @@
|
|
|
7139
7225
|
// make sure popup is unpinned and turned off when switching editing modes
|
|
7140
7226
|
// (some modes do not support pinning)
|
|
7141
7227
|
gui.on('interaction_mode_change', function(e) {
|
|
7142
|
-
|
|
7228
|
+
self.clearSelection();
|
|
7143
7229
|
// if (e.mode == 'off' || e.mode == 'box') {
|
|
7144
7230
|
if (gui.interaction.modeUsesSelection(e.mode)) {
|
|
7145
7231
|
turnOn(e.mode);
|
|
@@ -7148,6 +7234,10 @@
|
|
|
7148
7234
|
}
|
|
7149
7235
|
});
|
|
7150
7236
|
|
|
7237
|
+
gui.on('undo_redo_pre', function() {
|
|
7238
|
+
self.clearSelection();
|
|
7239
|
+
});
|
|
7240
|
+
|
|
7151
7241
|
gui.on('box_drag_start', function() {
|
|
7152
7242
|
self.clearHover();
|
|
7153
7243
|
});
|
|
@@ -7300,6 +7390,9 @@
|
|
|
7300
7390
|
if (transientIds.length) {
|
|
7301
7391
|
eventData.ids = utils$1.uniq(transientIds.concat(eventData.ids || []));
|
|
7302
7392
|
}
|
|
7393
|
+
if (pinnedOn) {
|
|
7394
|
+
eventData.pinned = true;
|
|
7395
|
+
}
|
|
7303
7396
|
self.dispatchEvent(type, eventData);
|
|
7304
7397
|
}
|
|
7305
7398
|
|
|
@@ -7856,14 +7949,17 @@
|
|
|
7856
7949
|
var scale = gui.map.getExtent().getPixelSize();
|
|
7857
7950
|
var dx = (xy.x - prevXY.x) * scale;
|
|
7858
7951
|
var dy = -(xy.y - prevXY.y) * scale;
|
|
7859
|
-
|
|
7952
|
+
var center = activeHandle.col == 'center' && activeHandle.row == 'center';
|
|
7953
|
+
if (activeHandle.col == 'left' || center) {
|
|
7860
7954
|
boxCoords[0] += dx;
|
|
7861
|
-
}
|
|
7955
|
+
}
|
|
7956
|
+
if (activeHandle.col == 'right' || center) {
|
|
7862
7957
|
boxCoords[2] += dx;
|
|
7863
7958
|
}
|
|
7864
|
-
if (activeHandle.row == 'top') {
|
|
7959
|
+
if (activeHandle.row == 'top' || center) {
|
|
7865
7960
|
boxCoords[3] += dy;
|
|
7866
|
-
}
|
|
7961
|
+
}
|
|
7962
|
+
if (activeHandle.row == 'bottom' || center) {
|
|
7867
7963
|
boxCoords[1] += dy;
|
|
7868
7964
|
}
|
|
7869
7965
|
prevXY = xy;
|
|
@@ -7974,7 +8070,7 @@
|
|
|
7974
8070
|
function initHandles(el) {
|
|
7975
8071
|
var handles = [];
|
|
7976
8072
|
for (var i=0; i<9; i++) {
|
|
7977
|
-
if (i == 4) continue;
|
|
8073
|
+
// if (i == 4) continue; // skip middle handle
|
|
7978
8074
|
var c = Math.floor(i / 3);
|
|
7979
8075
|
var r = i % 3;
|
|
7980
8076
|
handles.push({
|
|
@@ -8211,6 +8307,7 @@
|
|
|
8211
8307
|
}
|
|
8212
8308
|
|
|
8213
8309
|
function turnOff() {
|
|
8310
|
+
dataBtn.turnOff();
|
|
8214
8311
|
box.turnOff();
|
|
8215
8312
|
reset();
|
|
8216
8313
|
_on = false;
|
|
@@ -8221,10 +8318,17 @@
|
|
|
8221
8318
|
}
|
|
8222
8319
|
|
|
8223
8320
|
function reset() {
|
|
8224
|
-
|
|
8321
|
+
hidePopup();
|
|
8322
|
+
setPinning(false);
|
|
8225
8323
|
hit.clearSelection();
|
|
8226
8324
|
}
|
|
8227
8325
|
|
|
8326
|
+
function setPinning(on) {
|
|
8327
|
+
hit.setPinning(on);
|
|
8328
|
+
if (on) dataBtn.turnOn();
|
|
8329
|
+
else dataBtn.turnOff();
|
|
8330
|
+
}
|
|
8331
|
+
|
|
8228
8332
|
function getIdsOpt() {
|
|
8229
8333
|
return hit.getSelectionIds().join(',');
|
|
8230
8334
|
}
|
|
@@ -8239,11 +8343,15 @@
|
|
|
8239
8343
|
popup.show();
|
|
8240
8344
|
updateCoords();
|
|
8241
8345
|
} else {
|
|
8242
|
-
|
|
8243
|
-
hideCoords();
|
|
8346
|
+
hidePopup();
|
|
8244
8347
|
}
|
|
8245
8348
|
});
|
|
8246
8349
|
|
|
8350
|
+
function hidePopup() {
|
|
8351
|
+
popup.hide();
|
|
8352
|
+
hideCoords();
|
|
8353
|
+
}
|
|
8354
|
+
|
|
8247
8355
|
new SimpleButton(popup.findChild('.delete-btn')).on('click', function() {
|
|
8248
8356
|
var cmd = '-filter invert ids=' + getIdsOpt();
|
|
8249
8357
|
runCommand(cmd);
|
|
@@ -8259,6 +8367,10 @@
|
|
|
8259
8367
|
runCommand(cmd);
|
|
8260
8368
|
});
|
|
8261
8369
|
|
|
8370
|
+
var dataBtn = new ToggleButton(popup.findChild('.data-btn')).on('click', function(e) {
|
|
8371
|
+
setPinning(e.on);
|
|
8372
|
+
});
|
|
8373
|
+
|
|
8262
8374
|
new SimpleButton(popup.findChild('.duplicate-btn')).on('click', function() {
|
|
8263
8375
|
var cmd = '-filter + name=selection ids=' + getIdsOpt();
|
|
8264
8376
|
runCommand(cmd);
|
|
@@ -8296,19 +8408,19 @@
|
|
|
8296
8408
|
hideCoords();
|
|
8297
8409
|
return;
|
|
8298
8410
|
}
|
|
8299
|
-
El(coordsBtn.node()).addClass('
|
|
8411
|
+
El(coordsBtn.node()).addClass('active');
|
|
8300
8412
|
coords.text(bbox.join(','));
|
|
8301
8413
|
coords.show();
|
|
8302
8414
|
GUI.selectElement(coords.node());
|
|
8303
8415
|
}
|
|
8304
8416
|
|
|
8305
8417
|
function hideCoords() {
|
|
8306
|
-
El(coordsBtn.node()).removeClass('
|
|
8418
|
+
El(coordsBtn.node()).removeClass('active');
|
|
8307
8419
|
coords.hide();
|
|
8308
8420
|
}
|
|
8309
8421
|
|
|
8310
8422
|
function runCommand(cmd, turnOff) {
|
|
8311
|
-
|
|
8423
|
+
hidePopup();
|
|
8312
8424
|
gui.quiet(true);
|
|
8313
8425
|
if (gui.console) gui.console.runMapshaperCommands(cmd, function(err) {
|
|
8314
8426
|
gui.quiet(false);
|
|
@@ -8318,6 +8430,55 @@
|
|
|
8318
8430
|
}
|
|
8319
8431
|
}
|
|
8320
8432
|
|
|
8433
|
+
function openAddFieldPopup(gui, ids, lyr) {
|
|
8434
|
+
var popup = showPopupAlert('', 'Add field');
|
|
8435
|
+
var el = popup.container();
|
|
8436
|
+
el.addClass('option-menu');
|
|
8437
|
+
var html = `<div><input type="text" class="field-name text-input" placeholder="field name"></div>
|
|
8438
|
+
<div><input type="text" class="field-value text-input" placeholder="value"><div>
|
|
8439
|
+
<div tabindex="0" class="btn dialog-btn">Apply</div> <span class="inline-checkbox"><input type="checkbox" class="all" />assign value to all records</span>`;
|
|
8440
|
+
el.html(html);
|
|
8441
|
+
|
|
8442
|
+
var name = el.findChild('.field-name');
|
|
8443
|
+
name.node().focus();
|
|
8444
|
+
var val = el.findChild('.field-value');
|
|
8445
|
+
var box = el.findChild('.all');
|
|
8446
|
+
var btn = el.findChild('.btn').on('click', function() {
|
|
8447
|
+
var table = internal.getLayerDataTable(lyr); // creates new table if missing
|
|
8448
|
+
var all = box.node().checked;
|
|
8449
|
+
var nameStr = name.node().value.trim();
|
|
8450
|
+
if (!nameStr) return;
|
|
8451
|
+
if (table.fieldExists(nameStr)) {
|
|
8452
|
+
name.node().value = '';
|
|
8453
|
+
return;
|
|
8454
|
+
}
|
|
8455
|
+
var valStr = val.node().value.trim();
|
|
8456
|
+
var value = internal.parseUnknownType(valStr);
|
|
8457
|
+
// table.addField(nameStr, function(d) {
|
|
8458
|
+
// // parse each time to avoid multiple references to objects
|
|
8459
|
+
// return (all || d == rec) ? parseUnknownType(valStr) : null;
|
|
8460
|
+
// });
|
|
8461
|
+
|
|
8462
|
+
var cmdStr = `-each "d['${nameStr}'] = `;
|
|
8463
|
+
if (!all) {
|
|
8464
|
+
cmdStr += ids.length == 1 ?
|
|
8465
|
+
`this.id != ${ids[0]}` :
|
|
8466
|
+
`!${JSON.stringify(ids)}.includes(this.id)`;
|
|
8467
|
+
cmdStr += ' ? null : ';
|
|
8468
|
+
}
|
|
8469
|
+
valStr = JSON.stringify(JSON.stringify(value)); // add escapes to strings
|
|
8470
|
+
cmdStr = valStr.replace('"', cmdStr);
|
|
8471
|
+
|
|
8472
|
+
gui.console.runMapshaperCommands(cmdStr, function(err) {
|
|
8473
|
+
if (!err) {
|
|
8474
|
+
popup.close();
|
|
8475
|
+
} else {
|
|
8476
|
+
console.error(err);
|
|
8477
|
+
}
|
|
8478
|
+
});
|
|
8479
|
+
});
|
|
8480
|
+
}
|
|
8481
|
+
|
|
8321
8482
|
// toNext, toPrev: trigger functions for switching between multiple records
|
|
8322
8483
|
function Popup(gui, toNext, toPrev) {
|
|
8323
8484
|
var self = new EventDispatcher();
|
|
@@ -8331,7 +8492,6 @@
|
|
|
8331
8492
|
var navInfo = El('span').addClass('popup-nav-info').appendTo(nav);
|
|
8332
8493
|
var nextLink = El('span').addClass('popup-nav-arrow colored-text').appendTo(nav).text('▶');
|
|
8333
8494
|
var refresh = null;
|
|
8334
|
-
var currIds = [];
|
|
8335
8495
|
|
|
8336
8496
|
el.addClass('rollover'); // used as a sentinel for the hover function
|
|
8337
8497
|
|
|
@@ -8342,16 +8502,20 @@
|
|
|
8342
8502
|
});
|
|
8343
8503
|
|
|
8344
8504
|
self.show = function(id, ids, lyr, pinned) {
|
|
8345
|
-
var
|
|
8505
|
+
var singleEdit = pinned && gui.interaction.getMode() == 'data';
|
|
8506
|
+
var multiEdit = pinned && gui.interaction.getMode() == 'selection';
|
|
8346
8507
|
var maxHeight = parent.node().clientHeight - 36;
|
|
8347
|
-
|
|
8508
|
+
var recIds = multiEdit ? ids : [id];
|
|
8509
|
+
|
|
8348
8510
|
// stash a function for refreshing the current popup when data changes
|
|
8349
8511
|
// while the popup is being displayed (e.g. while dragging a label)
|
|
8350
8512
|
refresh = function() {
|
|
8351
|
-
render(content,
|
|
8513
|
+
render(content, recIds, lyr, singleEdit || multiEdit);
|
|
8352
8514
|
};
|
|
8353
8515
|
refresh();
|
|
8354
|
-
if (
|
|
8516
|
+
if (multiEdit) {
|
|
8517
|
+
showRecords(ids.length);
|
|
8518
|
+
} else if (ids && ids.length > 1 && !multiEdit) {
|
|
8355
8519
|
showNav(id, ids, pinned);
|
|
8356
8520
|
} else {
|
|
8357
8521
|
tab.hide();
|
|
@@ -8365,7 +8529,6 @@
|
|
|
8365
8529
|
self.hide = function() {
|
|
8366
8530
|
if (!isOpen()) return;
|
|
8367
8531
|
refresh = null;
|
|
8368
|
-
currIds = [];
|
|
8369
8532
|
// make sure any pending edits are made before re-rendering popup
|
|
8370
8533
|
GUI.blurActiveElement(); // this should be more selective -- could cause a glitch if typing in console
|
|
8371
8534
|
content.empty();
|
|
@@ -8379,6 +8542,13 @@
|
|
|
8379
8542
|
return el.visible();
|
|
8380
8543
|
}
|
|
8381
8544
|
|
|
8545
|
+
function showRecords(n) {
|
|
8546
|
+
navInfo.text(n);
|
|
8547
|
+
nextLink.css('display','none');
|
|
8548
|
+
prevLink.css('display','none');
|
|
8549
|
+
tab.show();
|
|
8550
|
+
}
|
|
8551
|
+
|
|
8382
8552
|
function showNav(id, ids, pinned) {
|
|
8383
8553
|
var num = ids.indexOf(id) + 1;
|
|
8384
8554
|
navInfo.text(' ' + num + ' / ' + ids.length + ' ');
|
|
@@ -8387,28 +8557,12 @@
|
|
|
8387
8557
|
tab.show();
|
|
8388
8558
|
}
|
|
8389
8559
|
|
|
8390
|
-
function render(el,
|
|
8391
|
-
var recIds = [recId]; // TODO: support multiple ids
|
|
8560
|
+
function render(el, recIds, lyr, editable) {
|
|
8392
8561
|
var table = lyr.data; // table can be null (e.g. if layer has no attribute data)
|
|
8393
|
-
var
|
|
8394
|
-
var tableEl = El('table').addClass('selectable'),
|
|
8395
|
-
rows = 0;
|
|
8396
|
-
// self.hide(); // clean up if panel is already open
|
|
8562
|
+
var tableEl = table ? renderTable(recIds, table, editable) : null;
|
|
8397
8563
|
el.empty(); // clean up if panel is already open
|
|
8398
|
-
|
|
8399
|
-
|
|
8400
|
-
// missing GeoJSON fields are set to undefined on import; skip these
|
|
8401
|
-
if (v !== undefined) {
|
|
8402
|
-
type = getFieldType(v, k, table);
|
|
8403
|
-
renderRow(tableEl, rec, k, type, editable);
|
|
8404
|
-
rows++;
|
|
8405
|
-
}
|
|
8406
|
-
});
|
|
8407
|
-
|
|
8408
|
-
tableEl.appendTo(el);
|
|
8409
|
-
if (rows > 0) {
|
|
8410
|
-
// tableEl.appendTo(el);
|
|
8411
|
-
|
|
8564
|
+
if (tableEl) {
|
|
8565
|
+
tableEl.appendTo(el);
|
|
8412
8566
|
tableEl.on('copy', function(e) {
|
|
8413
8567
|
// remove leading or trailing tabs that sometimes get copied when
|
|
8414
8568
|
// selecting from a table
|
|
@@ -8419,7 +8573,6 @@
|
|
|
8419
8573
|
e.preventDefault(); // don't copy original string with tabs
|
|
8420
8574
|
}
|
|
8421
8575
|
});
|
|
8422
|
-
|
|
8423
8576
|
} else {
|
|
8424
8577
|
// Some individual features can have undefined values for some or all of
|
|
8425
8578
|
// their data properties (properties are set to undefined when an input JSON file
|
|
@@ -8433,72 +8586,65 @@
|
|
|
8433
8586
|
var line = El('div').appendTo(el);
|
|
8434
8587
|
El('span').addClass('add-field-btn').appendTo(line).on('click', async function(e) {
|
|
8435
8588
|
// show "add field" dialog
|
|
8436
|
-
|
|
8589
|
+
openAddFieldPopup(gui, recIds, lyr);
|
|
8437
8590
|
}).text('+ add field');
|
|
8438
8591
|
}
|
|
8439
8592
|
}
|
|
8440
8593
|
|
|
8441
|
-
function
|
|
8442
|
-
var
|
|
8443
|
-
var
|
|
8444
|
-
|
|
8445
|
-
|
|
8446
|
-
|
|
8447
|
-
|
|
8448
|
-
|
|
8449
|
-
|
|
8450
|
-
|
|
8451
|
-
|
|
8452
|
-
|
|
8453
|
-
|
|
8454
|
-
|
|
8455
|
-
var
|
|
8456
|
-
|
|
8457
|
-
|
|
8458
|
-
|
|
8459
|
-
if (table.fieldExists(nameStr)) {
|
|
8460
|
-
name.node().value = '';
|
|
8461
|
-
return;
|
|
8594
|
+
function renderTable(recIds, table, editable) {
|
|
8595
|
+
var tableEl = El('table').addClass('selectable');
|
|
8596
|
+
var rows = 0;
|
|
8597
|
+
var rec;
|
|
8598
|
+
if (recIds.length == 1) {
|
|
8599
|
+
rec = editable ?
|
|
8600
|
+
table.getReadOnlyRecordAt(recIds[0]) :
|
|
8601
|
+
table.getRecordAt(recIds[0]);
|
|
8602
|
+
} else {
|
|
8603
|
+
rec = getMultiRecord(recIds, table);
|
|
8604
|
+
}
|
|
8605
|
+
utils$1.forEachProperty(rec, function(v, k) {
|
|
8606
|
+
// missing GeoJSON fields are set to undefined on import; skip these
|
|
8607
|
+
if (v === undefined) return;
|
|
8608
|
+
var rowEl = renderRow(k, v, recIds, table, editable);
|
|
8609
|
+
if (rowEl) {
|
|
8610
|
+
rowEl.appendTo(tableEl);
|
|
8611
|
+
rows++;
|
|
8462
8612
|
}
|
|
8463
|
-
|
|
8464
|
-
|
|
8465
|
-
|
|
8466
|
-
|
|
8467
|
-
|
|
8468
|
-
|
|
8469
|
-
|
|
8470
|
-
|
|
8471
|
-
|
|
8472
|
-
|
|
8473
|
-
|
|
8474
|
-
|
|
8475
|
-
|
|
8476
|
-
|
|
8477
|
-
|
|
8478
|
-
|
|
8479
|
-
|
|
8480
|
-
gui.console.runMapshaperCommands(cmdStr, function(err) {
|
|
8481
|
-
if (!err) {
|
|
8482
|
-
popup.close();
|
|
8483
|
-
} else {
|
|
8484
|
-
console.error(err);
|
|
8613
|
+
});
|
|
8614
|
+
return rows > 0 ? tableEl : null;
|
|
8615
|
+
}
|
|
8616
|
+
|
|
8617
|
+
function getMultiRecord(recIds, table) {
|
|
8618
|
+
var fields = table.getFields();
|
|
8619
|
+
var rec = {};
|
|
8620
|
+
recIds.forEach(function(id) {
|
|
8621
|
+
var d = table.getRecordAt(id) || {};
|
|
8622
|
+
var k, v;
|
|
8623
|
+
for (var i=0; i<fields.length; i++) {
|
|
8624
|
+
k = fields[i];
|
|
8625
|
+
v = d[k];
|
|
8626
|
+
if (k in rec === false) {
|
|
8627
|
+
rec[k] = v;
|
|
8628
|
+
} else if (rec[k] !== v) {
|
|
8629
|
+
rec[k] = null;
|
|
8485
8630
|
}
|
|
8486
|
-
}
|
|
8631
|
+
}
|
|
8487
8632
|
});
|
|
8633
|
+
return rec;
|
|
8488
8634
|
}
|
|
8489
8635
|
|
|
8490
|
-
|
|
8491
|
-
|
|
8636
|
+
|
|
8637
|
+
function renderRow(key, val, recIds, table, editable) {
|
|
8638
|
+
var type = getFieldType(val, key, table);
|
|
8492
8639
|
var str = formatInspectorValue(val, type);
|
|
8493
8640
|
var rowHtml = `<td class="field-name">${key}</td><td><span class="value">${utils$1.htmlEscape(str)}</span> </td>`;
|
|
8494
|
-
var
|
|
8495
|
-
|
|
8496
|
-
|
|
8497
|
-
.findChild('.value');
|
|
8498
|
-
setFieldClass(cell, val, type);
|
|
8641
|
+
var rowEl = El('tr').html(rowHtml);
|
|
8642
|
+
var cellEl = rowEl.findChild('.value');
|
|
8643
|
+
setFieldClass(cellEl, val, type);
|
|
8499
8644
|
if (editable) {
|
|
8500
|
-
editItem(
|
|
8645
|
+
editItem(cellEl, key, val, recIds, table, type);
|
|
8501
8646
|
}
|
|
8647
|
+
return rowEl;
|
|
8502
8648
|
}
|
|
8503
8649
|
|
|
8504
8650
|
function setFieldClass(el, val, type) {
|
|
@@ -8511,10 +8657,10 @@
|
|
|
8511
8657
|
el.classed('empty', isEmpty);
|
|
8512
8658
|
}
|
|
8513
8659
|
|
|
8514
|
-
function editItem(el,
|
|
8660
|
+
function editItem(el, key, val, recIds, table, type) {
|
|
8515
8661
|
var input = new ClickText2(el),
|
|
8516
|
-
strval = formatInspectorValue(
|
|
8517
|
-
parser = getInputParser(type);
|
|
8662
|
+
strval = formatInspectorValue(val, type),
|
|
8663
|
+
parser = internal.getInputParser(type);
|
|
8518
8664
|
el.parent().addClass('editable-cell');
|
|
8519
8665
|
el.addClass('colored-text dot-underline');
|
|
8520
8666
|
input.on('change', function(e) {
|
|
@@ -8526,17 +8672,27 @@
|
|
|
8526
8672
|
} else if (strval != strval2) {
|
|
8527
8673
|
// field content has changed
|
|
8528
8674
|
strval = strval2;
|
|
8529
|
-
gui.dispatchEvent('data_preupdate', {ids:
|
|
8530
|
-
rec[key] = val2;
|
|
8531
|
-
|
|
8675
|
+
gui.dispatchEvent('data_preupdate', {ids: recIds}); // for undo/redo
|
|
8676
|
+
// rec[key] = val2;
|
|
8677
|
+
updateRecords(recIds, key, val2, table);
|
|
8678
|
+
gui.dispatchEvent('data_postupdate', {ids: recIds});
|
|
8532
8679
|
input.value(strval);
|
|
8533
8680
|
setFieldClass(el, val2, type);
|
|
8534
|
-
self.dispatchEvent('data_updated', {field: key, value: val2, ids:
|
|
8681
|
+
self.dispatchEvent('data_updated', {field: key, value: val2, ids: recIds});
|
|
8535
8682
|
}
|
|
8536
8683
|
});
|
|
8537
8684
|
}
|
|
8538
8685
|
}
|
|
8539
8686
|
|
|
8687
|
+
function updateRecords(ids, f, v, table) {
|
|
8688
|
+
var records = table.getRecords();
|
|
8689
|
+
ids.forEach(function(id) {
|
|
8690
|
+
var d = records[id] || {};
|
|
8691
|
+
d[f] = v;
|
|
8692
|
+
records[id] = d;
|
|
8693
|
+
});
|
|
8694
|
+
}
|
|
8695
|
+
|
|
8540
8696
|
function formatInspectorValue(val, type) {
|
|
8541
8697
|
var str;
|
|
8542
8698
|
if (type == 'date') {
|
|
@@ -8549,60 +8705,10 @@
|
|
|
8549
8705
|
return str;
|
|
8550
8706
|
}
|
|
8551
8707
|
|
|
8552
|
-
var inputParsers = {
|
|
8553
|
-
date: function(raw) {
|
|
8554
|
-
var d = new Date(raw);
|
|
8555
|
-
return isNaN(+d) ? null : d;
|
|
8556
|
-
},
|
|
8557
|
-
string: function(raw) {
|
|
8558
|
-
return raw;
|
|
8559
|
-
},
|
|
8560
|
-
number: function(raw) {
|
|
8561
|
-
var val = Number(raw);
|
|
8562
|
-
if (raw == 'NaN') {
|
|
8563
|
-
val = NaN;
|
|
8564
|
-
} else if (isNaN(val)) {
|
|
8565
|
-
val = null;
|
|
8566
|
-
}
|
|
8567
|
-
return val;
|
|
8568
|
-
},
|
|
8569
|
-
object: function(raw) {
|
|
8570
|
-
var val = null;
|
|
8571
|
-
try {
|
|
8572
|
-
val = JSON.parse(raw);
|
|
8573
|
-
} catch(e) {}
|
|
8574
|
-
return val;
|
|
8575
|
-
},
|
|
8576
|
-
boolean: function(raw) {
|
|
8577
|
-
var val = null;
|
|
8578
|
-
if (raw == 'true') {
|
|
8579
|
-
val = true;
|
|
8580
|
-
} else if (raw == 'false') {
|
|
8581
|
-
val = false;
|
|
8582
|
-
}
|
|
8583
|
-
return val;
|
|
8584
|
-
},
|
|
8585
|
-
multiple: function(raw) {
|
|
8586
|
-
var val = Number(raw);
|
|
8587
|
-
return isNaN(val) ? raw : val;
|
|
8588
|
-
}
|
|
8589
|
-
};
|
|
8590
|
-
|
|
8591
|
-
function parseUnknownType(str) {
|
|
8592
|
-
var val = inputParsers.number(str);
|
|
8593
|
-
if (val !== null) return val;
|
|
8594
|
-
val = inputParsers.object(str);
|
|
8595
|
-
if (val !== null) return val;
|
|
8596
|
-
return str;
|
|
8597
|
-
}
|
|
8598
|
-
|
|
8599
|
-
function getInputParser(type) {
|
|
8600
|
-
return inputParsers[type || 'multiple'];
|
|
8601
|
-
}
|
|
8602
8708
|
|
|
8603
8709
|
function getFieldType(val, key, table) {
|
|
8604
8710
|
// if a field has a null value, look at entire column to identify type
|
|
8605
|
-
return internal.getValueType(val) || internal.getColumnType(key, table.getRecords());
|
|
8711
|
+
return internal.getValueType(val) || internal.getColumnType(key, table.getRecords()) ;
|
|
8606
8712
|
}
|
|
8607
8713
|
|
|
8608
8714
|
function InspectionControl2(gui, hit) {
|
|
@@ -8627,16 +8733,20 @@
|
|
|
8627
8733
|
});
|
|
8628
8734
|
|
|
8629
8735
|
hit.on('change', function(e) {
|
|
8630
|
-
var ids;
|
|
8631
8736
|
if (!inspecting()) return;
|
|
8632
|
-
|
|
8633
|
-
|
|
8737
|
+
var ids;
|
|
8738
|
+
if (e.mode == 'selection') {
|
|
8739
|
+
ids = e.pinned && e.ids || [];
|
|
8740
|
+
} else {
|
|
8741
|
+
ids = e.ids || [];
|
|
8742
|
+
}
|
|
8743
|
+
inspect(e.id, ids, e.pinned);
|
|
8634
8744
|
});
|
|
8635
8745
|
|
|
8636
8746
|
// id: Id of a feature in the active layer, or -1
|
|
8637
|
-
function inspect(id,
|
|
8747
|
+
function inspect(id, ids, pin) {
|
|
8638
8748
|
var target = hit.getHitTarget();
|
|
8639
|
-
if (id > -1 && inspecting() && target && target.layer) {
|
|
8749
|
+
if ((id > -1 || ids && ids.length > 0) && inspecting() && target && target.layer) {
|
|
8640
8750
|
_popup.show(id, ids, target.layer, pin);
|
|
8641
8751
|
} else {
|
|
8642
8752
|
_popup.hide();
|
|
@@ -8935,6 +9045,9 @@
|
|
|
8935
9045
|
hit.clearVertexOverlay();
|
|
8936
9046
|
}
|
|
8937
9047
|
|
|
9048
|
+
// return data on the nearest vertex (or identical vertices) to the pointer
|
|
9049
|
+
// (if within a distance threshold)
|
|
9050
|
+
//
|
|
8938
9051
|
function findDraggableVertices(e) {
|
|
8939
9052
|
var target = hit.getHitTarget();
|
|
8940
9053
|
var shp = target.layer.shapes[e.id];
|
|
@@ -9097,35 +9210,6 @@
|
|
|
9097
9210
|
// }
|
|
9098
9211
|
}
|
|
9099
9212
|
|
|
9100
|
-
function initPointDrawing(gui, ext, hit) {
|
|
9101
|
-
function active(e) {
|
|
9102
|
-
return e.id > -1 && gui.interaction.getMode() == 'add-points';
|
|
9103
|
-
}
|
|
9104
|
-
}
|
|
9105
|
-
|
|
9106
|
-
function Pencil(gui, mouse, hit) {
|
|
9107
|
-
var self = this;
|
|
9108
|
-
var _on = false;
|
|
9109
|
-
|
|
9110
|
-
self.turnOn = function() {
|
|
9111
|
-
_on = true;
|
|
9112
|
-
};
|
|
9113
|
-
|
|
9114
|
-
self.turnOff = function() {
|
|
9115
|
-
_on = false;
|
|
9116
|
-
};
|
|
9117
|
-
|
|
9118
|
-
|
|
9119
|
-
|
|
9120
|
-
|
|
9121
|
-
|
|
9122
|
-
|
|
9123
|
-
}
|
|
9124
|
-
|
|
9125
|
-
function initDrawing(gui, ext, mouse, hit) {
|
|
9126
|
-
initPointDrawing(gui, new Pencil(gui, mouse, hit));
|
|
9127
|
-
}
|
|
9128
|
-
|
|
9129
9213
|
var darkStroke = "#334",
|
|
9130
9214
|
lightStroke = "#b7d9ea",
|
|
9131
9215
|
violet = "#cc6acc",
|
|
@@ -9452,6 +9536,59 @@
|
|
|
9452
9536
|
return internal.findPropertiesBySymbolGeom(fields, lyr.geometry_type);
|
|
9453
9537
|
}
|
|
9454
9538
|
|
|
9539
|
+
function initPointDrawing(gui, ext, mouse, hit) {
|
|
9540
|
+
|
|
9541
|
+
gui.on('interaction_mode_change', function(e) {
|
|
9542
|
+
gui.container.findChild('.map-layers').classed('add-points', e.mode === 'add-points');
|
|
9543
|
+
});
|
|
9544
|
+
|
|
9545
|
+
function active() {
|
|
9546
|
+
return gui.interaction.getMode() == 'add-points';
|
|
9547
|
+
}
|
|
9548
|
+
|
|
9549
|
+
mouse.on('click', function(e) {
|
|
9550
|
+
if (!active()) return;
|
|
9551
|
+
addPoint(e.x, e.y);
|
|
9552
|
+
gui.dispatchEvent('map-needs-refresh');
|
|
9553
|
+
});
|
|
9554
|
+
|
|
9555
|
+
// x, y: pixel coordinates
|
|
9556
|
+
function addPoint(x, y) {
|
|
9557
|
+
var p = ext.translatePixelCoords(x, y);
|
|
9558
|
+
var target = hit.getHitTarget();
|
|
9559
|
+
var lyr = target.layer;
|
|
9560
|
+
var fid = lyr.shapes.length;
|
|
9561
|
+
var d = lyr.data ? getEmptyDataRecord(lyr.data) : null;
|
|
9562
|
+
if (d) {
|
|
9563
|
+
// this seems to work even for projected layers -- the data tables
|
|
9564
|
+
// of projected and original data seem to be shared.
|
|
9565
|
+
lyr.data.getRecords()[fid] = d;
|
|
9566
|
+
// TODO: handle SVG symbol layer
|
|
9567
|
+
if (internal.layerHasLabels(lyr)) {
|
|
9568
|
+
d['label-text'] = 'TBD'; // without text, new labels will be invisible
|
|
9569
|
+
} else if (layerHasCanvasDisplayStyle(lyr)) {
|
|
9570
|
+
d.r = 3; // show a black circle if layer is styled
|
|
9571
|
+
}
|
|
9572
|
+
}
|
|
9573
|
+
lyr.shapes[fid] = [p];
|
|
9574
|
+
updatePointCoords(target, fid);
|
|
9575
|
+
}
|
|
9576
|
+
|
|
9577
|
+
function getEmptyDataRecord(table) {
|
|
9578
|
+
return table.getFields().reduce(function(memo, name) {
|
|
9579
|
+
memo[name] = null;
|
|
9580
|
+
return memo;
|
|
9581
|
+
}, {});
|
|
9582
|
+
}
|
|
9583
|
+
}
|
|
9584
|
+
|
|
9585
|
+
// import { initLineDrawing } from './gui-draw-lines';
|
|
9586
|
+
|
|
9587
|
+
function initDrawing(gui, ext, mouse, hit) {
|
|
9588
|
+
initPointDrawing(gui, ext, mouse, hit);
|
|
9589
|
+
// initLineDrawing(gui, ext, mouse, hit);
|
|
9590
|
+
}
|
|
9591
|
+
|
|
9455
9592
|
function MapExtent(_position) {
|
|
9456
9593
|
var _scale = 1,
|
|
9457
9594
|
_cx, _cy, // center in geographic units
|
|
@@ -10479,7 +10616,7 @@
|
|
|
10479
10616
|
target.svg_id = id;
|
|
10480
10617
|
resize(ext);
|
|
10481
10618
|
if (type == 'label' || type == 'symbol') {
|
|
10482
|
-
html = renderSymbols(target.layer, ext
|
|
10619
|
+
html = renderSymbols(target.layer, ext);
|
|
10483
10620
|
} else if (type == 'furniture') {
|
|
10484
10621
|
html = renderFurniture(target.layer, ext);
|
|
10485
10622
|
}
|
|
@@ -10493,13 +10630,17 @@
|
|
|
10493
10630
|
};
|
|
10494
10631
|
|
|
10495
10632
|
function reposition(target, type, ext) {
|
|
10496
|
-
var container = el.findChild('.' + target.svg_id)
|
|
10633
|
+
var container = el.findChild('.' + target.svg_id);
|
|
10634
|
+
if (!container || !container.node()) {
|
|
10635
|
+
console.error('[reposition] missing SVG container');
|
|
10636
|
+
return;
|
|
10637
|
+
}
|
|
10497
10638
|
var elements;
|
|
10498
10639
|
if (type == 'symbol') {
|
|
10499
|
-
elements = El.findAll('.mapshaper-svg-symbol', container);
|
|
10640
|
+
elements = El.findAll('.mapshaper-svg-symbol', container.node());
|
|
10500
10641
|
repositionSymbols(elements, target.layer, ext);
|
|
10501
10642
|
} else if (type == 'furniture') {
|
|
10502
|
-
repositionFurniture(container, target.layer, ext);
|
|
10643
|
+
repositionFurniture(container.node(), target.layer, ext);
|
|
10503
10644
|
} else {
|
|
10504
10645
|
// container.getElementsByTagName('text')
|
|
10505
10646
|
error('Unsupported symbol type:', type);
|
|
@@ -10514,7 +10655,7 @@
|
|
|
10514
10655
|
return el;
|
|
10515
10656
|
}
|
|
10516
10657
|
|
|
10517
|
-
function
|
|
10658
|
+
function LayerRenderer(gui, container, ext, mouse) {
|
|
10518
10659
|
var el = El(container),
|
|
10519
10660
|
_mainCanv = new DisplayCanvas().appendTo(el),
|
|
10520
10661
|
_overlayCanv = new DisplayCanvas().appendTo(el),
|
|
@@ -10534,14 +10675,12 @@
|
|
|
10534
10675
|
}
|
|
10535
10676
|
layers.forEach(function(lyr) {
|
|
10536
10677
|
var isSvgLayer = internal.layerHasSvgSymbols(lyr.layer) || internal.layerHasLabels(lyr.layer);
|
|
10537
|
-
//if (!svgType || svgType == 'label') { // svg labels may have canvas dots
|
|
10538
|
-
if (!isSvgLayer) { // svg labels may have canvas dots
|
|
10539
|
-
drawCanvasLayer(lyr, _mainCanv);
|
|
10540
|
-
}
|
|
10541
10678
|
if (isSvgLayer && !needSvgRedraw) {
|
|
10542
10679
|
_svg.reposition(lyr, 'symbol');
|
|
10543
10680
|
} else if (isSvgLayer) {
|
|
10544
10681
|
_svg.drawLayer(lyr, 'symbol');
|
|
10682
|
+
} else {
|
|
10683
|
+
drawCanvasLayer(lyr, _mainCanv);
|
|
10545
10684
|
}
|
|
10546
10685
|
});
|
|
10547
10686
|
};
|
|
@@ -10639,7 +10778,8 @@
|
|
|
10639
10778
|
});
|
|
10640
10779
|
|
|
10641
10780
|
new SimpleButton(popup.findChild('.rect-btn')).on('click', function() {
|
|
10642
|
-
|
|
10781
|
+
var cmd = '-rectangle + bbox=' + box.getDataCoords().join(',');
|
|
10782
|
+
runCommand(cmd);
|
|
10643
10783
|
});
|
|
10644
10784
|
|
|
10645
10785
|
gui.addMode('box_tool', turnOn, turnOff);
|
|
@@ -10734,7 +10874,7 @@
|
|
|
10734
10874
|
|
|
10735
10875
|
hit.on('change', function(e) {
|
|
10736
10876
|
if (!_on) return;
|
|
10737
|
-
// TODO: handle multiple hits (see gui-inspection-
|
|
10877
|
+
// TODO: handle multiple hits (see gui-inspection-control)
|
|
10738
10878
|
var id = e.id;
|
|
10739
10879
|
if (e.id > -1 && e.pinned) {
|
|
10740
10880
|
var target = hit.getHitTarget();
|
|
@@ -10755,8 +10895,7 @@
|
|
|
10755
10895
|
gui.container.findChild('.map-layers').classed('dragging', true);
|
|
10756
10896
|
|
|
10757
10897
|
} else if (dragInfo) {
|
|
10758
|
-
|
|
10759
|
-
gui.dispatchEvent('rectangle_dragend', dragInfo);
|
|
10898
|
+
gui.dispatchEvent('rectangle_dragend', dragInfo); // save undo state
|
|
10760
10899
|
gui.container.findChild('.map-layers').classed('dragging', false);
|
|
10761
10900
|
reset();
|
|
10762
10901
|
} else {
|
|
@@ -11296,7 +11435,7 @@
|
|
|
11296
11435
|
_hit,
|
|
11297
11436
|
_basemap,
|
|
11298
11437
|
_intersectionLyr, _activeLyr, _overlayLyr,
|
|
11299
|
-
|
|
11438
|
+
_renderer, _dynamicCRS;
|
|
11300
11439
|
|
|
11301
11440
|
_basemap = new Basemap(gui, _ext);
|
|
11302
11441
|
|
|
@@ -11391,13 +11530,12 @@
|
|
|
11391
11530
|
clearAllDisplayArcs();
|
|
11392
11531
|
|
|
11393
11532
|
// Reproject all visible map layers
|
|
11394
|
-
|
|
11395
|
-
|
|
11396
|
-
|
|
11397
|
-
|
|
11398
|
-
|
|
11399
|
-
|
|
11400
|
-
updateLayerStyles(getDrawableContentLayers()); // kludge to make sure all layers have styles
|
|
11533
|
+
getDrawableContentLayers().forEach(function(lyr) {
|
|
11534
|
+
projectDisplayLayer(lyr, newCRS);
|
|
11535
|
+
});
|
|
11536
|
+
|
|
11537
|
+
// kludge to make sure all layers have styles
|
|
11538
|
+
updateLayerStyles(getDrawableContentLayers());
|
|
11401
11539
|
|
|
11402
11540
|
// Update map extent (also triggers redraw)
|
|
11403
11541
|
projectMapExtent(_ext, oldCRS, this.getDisplayCRS(), calcFullBounds());
|
|
@@ -11475,7 +11613,7 @@
|
|
|
11475
11613
|
// Initialization just before displaying the map for the first time
|
|
11476
11614
|
function initMap() {
|
|
11477
11615
|
_ext.resize();
|
|
11478
|
-
|
|
11616
|
+
_renderer = new LayerRenderer(gui, el, _ext, _mouse);
|
|
11479
11617
|
gui.buttons.show();
|
|
11480
11618
|
|
|
11481
11619
|
if (opts.inspectorControl) {
|
|
@@ -11485,7 +11623,7 @@
|
|
|
11485
11623
|
new BoxTool(gui, _ext, _nav),
|
|
11486
11624
|
new RectangleControl(gui, _hit),
|
|
11487
11625
|
initInteractiveEditing(gui, _ext, _hit);
|
|
11488
|
-
|
|
11626
|
+
initDrawing(gui, _ext, _mouse, _hit);
|
|
11489
11627
|
_hit.on('change', updateOverlayLayer);
|
|
11490
11628
|
}
|
|
11491
11629
|
|
|
@@ -11516,7 +11654,6 @@
|
|
|
11516
11654
|
|
|
11517
11655
|
// 'hover' avoids redrawing all svg symbols when only highlight needs to refresh
|
|
11518
11656
|
drawLayers('hover');
|
|
11519
|
-
// drawLayers();
|
|
11520
11657
|
}
|
|
11521
11658
|
|
|
11522
11659
|
function getDisplayOptions() {
|
|
@@ -11551,10 +11688,7 @@
|
|
|
11551
11688
|
_ext.setFullBounds(calcFullBounds(), getStrictBounds());
|
|
11552
11689
|
}
|
|
11553
11690
|
|
|
11554
|
-
function
|
|
11555
|
-
if (isPreviewView()) {
|
|
11556
|
-
return internal.getFrameLayerBounds(internal.findFrameLayer(model));
|
|
11557
|
-
}
|
|
11691
|
+
function getVisibleContentBounds() {
|
|
11558
11692
|
var b = new Bounds();
|
|
11559
11693
|
var layers = getDrawableContentLayers();
|
|
11560
11694
|
layers.forEach(function(lyr) {
|
|
@@ -11565,6 +11699,14 @@
|
|
|
11565
11699
|
// assign bounds to empty layers, to prevent rendering errors downstream
|
|
11566
11700
|
b.setBounds(0,0,0,0);
|
|
11567
11701
|
}
|
|
11702
|
+
return b;
|
|
11703
|
+
}
|
|
11704
|
+
|
|
11705
|
+
function calcFullBounds() {
|
|
11706
|
+
if (isPreviewView()) {
|
|
11707
|
+
return internal.getFrameLayerBounds(internal.findFrameLayer(model));
|
|
11708
|
+
}
|
|
11709
|
+
var b = getVisibleContentBounds();
|
|
11568
11710
|
|
|
11569
11711
|
// add margin
|
|
11570
11712
|
// use larger margin for small sizes
|
|
@@ -11590,10 +11732,6 @@
|
|
|
11590
11732
|
return isActiveLayer(lyr) || lyr.pinned;
|
|
11591
11733
|
}
|
|
11592
11734
|
|
|
11593
|
-
function isFrameLayer(lyr) {
|
|
11594
|
-
return !!(lyr && lyr == internal.findFrameLayer(model));
|
|
11595
|
-
}
|
|
11596
|
-
|
|
11597
11735
|
function isTableView() {
|
|
11598
11736
|
return !isPreviewView() && !!_activeLyr.tabular;
|
|
11599
11737
|
}
|
|
@@ -11725,11 +11863,11 @@
|
|
|
11725
11863
|
}
|
|
11726
11864
|
// RENDERING
|
|
11727
11865
|
// draw main content layers
|
|
11728
|
-
|
|
11866
|
+
_renderer.drawMainLayers(contentLayers, action);
|
|
11729
11867
|
// draw hover & selection overlay
|
|
11730
|
-
|
|
11868
|
+
_renderer.drawOverlayLayer(_overlayLyr, action);
|
|
11731
11869
|
// draw furniture
|
|
11732
|
-
|
|
11870
|
+
// _renderer.drawFurnitureLayers(furnitureLayers, action);
|
|
11733
11871
|
gui.dispatchEvent('map_rendered');
|
|
11734
11872
|
}
|
|
11735
11873
|
}
|