mapshaper 0.6.40 → 0.6.42

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.
@@ -1125,21 +1125,26 @@
1125
1125
  var self = {}, html = '';
1126
1126
  var _cancel, _close;
1127
1127
  var warningRxp = /^Warning: /;
1128
- var el = El('div').appendTo('body').addClass('error-wrapper');
1129
- var infoBox = El('div').appendTo(el).addClass('error-box info-box selectable');
1128
+ var el = El('div').appendTo('body').addClass('alert-wrapper');
1129
+ var infoBox = El('div').appendTo(el).addClass('alert-box info-box selectable');
1130
+ El('div').appendTo(infoBox).addClass('close2-btn').on('click', function() {
1131
+ if (_cancel) _cancel();
1132
+ self.close();
1133
+ });
1134
+ var container = El('div').appendTo(infoBox);
1130
1135
  if (!title && warningRxp.test(msg)) {
1131
1136
  title = 'Warning';
1132
1137
  msg = msg.replace(warningRxp, '');
1133
1138
  }
1134
1139
  if (title) {
1135
- html += `<div class="error-title">${title}</div>`;
1140
+ El('div').addClass('alert-title').text(title).appendTo(container);
1141
+ }
1142
+ var content = El('div').appendTo(infoBox);
1143
+ if (msg) {
1144
+ content.html(`<p class="error-message">${msg}</p>`);
1136
1145
  }
1137
- html += `<p class="error-message">${msg}</p>`;
1138
- El('div').appendTo(infoBox).addClass('close2-btn').on('click', function() {
1139
- if (_cancel) _cancel();
1140
- self.close();
1141
- });
1142
- El('div').appendTo(infoBox).addClass('error-content').html(html);
1146
+
1147
+ self.container = function() { return content; };
1143
1148
 
1144
1149
  self.onCancel = function(cb) {
1145
1150
  _cancel = cb;
@@ -1979,7 +1984,7 @@
1979
1984
  var names = getFileNames(files);
1980
1985
  var expanded = [];
1981
1986
  if (files.length === 0) return;
1982
- useQuickView = importCount === 0 && (opts.quick_view || overQuickView);
1987
+ useQuickView = importTotal === 0 && (opts.quick_view || overQuickView);
1983
1988
  try {
1984
1989
  expanded = await expandFiles(files);
1985
1990
  } catch(e) {
@@ -4023,10 +4028,10 @@
4023
4028
 
4024
4029
  function render() {
4025
4030
  renderLayerList();
4026
- renderFileList();
4031
+ renderSourceFileList();
4027
4032
  }
4028
4033
 
4029
- function renderFileList() {
4034
+ function renderSourceFileList() {
4030
4035
  var list = el.findChild('.file-list');
4031
4036
  var files = [];
4032
4037
  list.empty();
@@ -5064,6 +5069,26 @@
5064
5069
  _stop = stop;
5065
5070
  }
5066
5071
 
5072
+ // get detailed error information from error stack (if available)
5073
+ // Example stack string (Node.js):
5074
+ /*
5075
+ /Users/someuser/somescript.js:226
5076
+ opacity: Math.round(weight * 5 / 5 // 0.2 0.4 0.6 etc
5077
+ ^
5078
+
5079
+ SyntaxError: missing ) after argument list
5080
+ at internalCompileFunction (node:internal/vm:73:18)
5081
+ at wrapSafe (node:internal/modules/cjs/loader:1149:20)
5082
+ at Module._compile (node:internal/modules/cjs/loader:1190:27)
5083
+ ...
5084
+ */
5085
+ function getErrorDetail(e) {
5086
+ var parts = (typeof e.stack == 'string') ? e.stack.split(/\n\s*\n/) : [];
5087
+ if (parts.length > 1 || true) {
5088
+ return '\nError details:\n' + parts[0];
5089
+ }
5090
+ return '';
5091
+ }
5067
5092
 
5068
5093
  // print a message to stdout
5069
5094
  function print() {
@@ -7993,8 +8018,7 @@
7993
8018
  // stash a function for refreshing the current popup when data changes
7994
8019
  // while the popup is being displayed (e.g. while dragging a label)
7995
8020
  refresh = function() {
7996
- var rec = table && (editable ? table.getRecordAt(id) : table.getReadOnlyRecordAt(id)) || {};
7997
- render(content, rec, table, editable);
8021
+ render(content, id, table, editable);
7998
8022
  };
7999
8023
  refresh();
8000
8024
  if (ids && ids.length > 1) {
@@ -8033,7 +8057,8 @@
8033
8057
  tab.show();
8034
8058
  }
8035
8059
 
8036
- function render(el, rec, table, editable) {
8060
+ function render(el, recId, table, editable) {
8061
+ var rec = table && (editable ? table.getRecordAt(recId) : table.getReadOnlyRecordAt(recId)) || {};
8037
8062
  var tableEl = El('table').addClass('selectable'),
8038
8063
  rows = 0;
8039
8064
  // self.hide(); // clean up if panel is already open
@@ -8048,11 +8073,6 @@
8048
8073
  }
8049
8074
  });
8050
8075
 
8051
- // add new field form
8052
- if (editable) {
8053
- renderNewRow(tableEl, rec, table);
8054
- }
8055
-
8056
8076
  tableEl.appendTo(el);
8057
8077
  if (rows > 0) {
8058
8078
  // tableEl.appendTo(el);
@@ -8077,15 +8097,58 @@
8077
8097
  }
8078
8098
 
8079
8099
  if (editable) {
8100
+ // render "add field" button
8080
8101
  var line = El('div').appendTo(el);
8081
8102
  El('span').addClass('save-menu-btn').appendTo(line).on('click', async function(e) {
8103
+ // show "add field" dialog
8104
+ renderAddFieldPopup(recId, table);
8105
+ }).text('+ add field');
8106
+ }
8107
+ }
8108
+
8109
+ function renderAddFieldPopup(recId, table) {
8110
+ var popup = showPopupAlert('', 'Add field');
8111
+ var el = popup.container();
8112
+ el.addClass('option-menu');
8113
+ var html = `<input type="text" class="field-name text-input" placeholder="field name"><br>
8114
+ <input type="text" class="field-value text-input" placeholder="value"><br>
8115
+ <div class="btn dialog-btn">Apply</div> <span class="inline-checkbox"><input type="checkbox" class="all" />assign value to all records</span>`;
8116
+ el.html(html);
8117
+
8118
+ var name = el.findChild('.field-name');
8119
+ name.node().focus();
8120
+ var val = el.findChild('.field-value');
8121
+ var box = el.findChild('.all');
8122
+ var btn = el.findChild('.btn').on('click', function() {
8123
+ var all = box.node().checked;
8124
+ var nameStr = name.node().value.trim();
8125
+ if (!nameStr) return;
8126
+ if (table.fieldExists(nameStr)) {
8127
+ name.node().value = '';
8128
+ return;
8129
+ }
8130
+ var valStr = val.node().value.trim();
8131
+ var value = parseUnknownType(valStr);
8132
+ // table.addField(nameStr, function(d) {
8133
+ // // parse each time to avoid multiple references to objects
8134
+ // return (all || d == rec) ? parseUnknownType(valStr) : null;
8135
+ // });
8082
8136
 
8083
- }).text('add field');
8084
- }
8085
- }
8086
-
8087
- function renderNewRow(el, rec, table) {
8137
+ var cmdStr = `-each "d['${nameStr}'] = `;
8138
+ if (!all) {
8139
+ cmdStr += `this.id != ${recId} ? null : `;
8140
+ }
8141
+ valStr = JSON.stringify(JSON.stringify(value));
8142
+ cmdStr = valStr.replace('"', cmdStr);
8088
8143
 
8144
+ gui.console.runMapshaperCommands(cmdStr, function(err) {
8145
+ if (!err) {
8146
+ popup.close();
8147
+ } else {
8148
+ console.error(err);
8149
+ }
8150
+ });
8151
+ });
8089
8152
  }
8090
8153
 
8091
8154
  function renderRow(table, rec, key, type, editable) {
@@ -8121,12 +8184,10 @@
8121
8184
  input.on('change', function(e) {
8122
8185
  var val2 = parser(input.value()),
8123
8186
  strval2 = formatInspectorValue(val2, type);
8124
- if (strval == strval2) {
8125
- // contents unchanged
8126
- } else if (val2 === null && type != 'object') { // allow null objects
8187
+ if (val2 === null && type != 'object') { // allow null objects
8127
8188
  // invalid value; revert to previous value
8128
8189
  input.value(strval);
8129
- } else {
8190
+ } else if (strval != strval2) {
8130
8191
  // field content has changed
8131
8192
  strval = strval2;
8132
8193
  gui.dispatchEvent('data_preupdate', {FID: currId}); // for undo/redo
@@ -8191,6 +8252,14 @@
8191
8252
  }
8192
8253
  };
8193
8254
 
8255
+ function parseUnknownType(str) {
8256
+ var val = inputParsers.number(str);
8257
+ if (val !== null) return val;
8258
+ val = inputParsers.object(str);
8259
+ if (val !== null) return val;
8260
+ return str;
8261
+ }
8262
+
8194
8263
  function getInputParser(type) {
8195
8264
  return inputParsers[type || 'multiple'];
8196
8265
  }
@@ -9171,6 +9240,10 @@
9171
9240
  return calcBounds(_cx, _cy, _scale / (k || 1));
9172
9241
  };
9173
9242
 
9243
+ this.getFullBounds = function() {
9244
+ return _fullBounds;
9245
+ };
9246
+
9174
9247
  // Update the extent of 'full' zoom without navigating the current view
9175
9248
  //
9176
9249
  this.setFullBounds = function(fullBounds, strictBounds) {
@@ -9506,6 +9579,7 @@
9506
9579
  canv.drawVertices(layer.shapes, arcs, style, filter);
9507
9580
  }
9508
9581
  }
9582
+ canv.clearStyles();
9509
9583
  }
9510
9584
 
9511
9585
 
@@ -9566,6 +9640,11 @@
9566
9640
  _pixelColor = getPixelColorFunction(),
9567
9641
  _ext;
9568
9642
 
9643
+ _self.clearStyles = function() {
9644
+ _ctx.fillStyle = null;
9645
+ _ctx.strokeStyle = null;
9646
+ };
9647
+
9569
9648
  _self.prep = function(extent) {
9570
9649
  var w = extent.width(),
9571
9650
  h = extent.height(),
@@ -10551,25 +10630,11 @@
10551
10630
 
10552
10631
 
10553
10632
  function getDisplayBounds(lyr, arcs) {
10554
- var arcBounds = arcs ? arcs.getBounds() : new Bounds(),
10555
- bounds = arcBounds, // default display extent: all arcs in the dataset
10556
- lyrBounds;
10557
-
10558
- if (lyr.geometry_type == 'point') {
10559
- lyrBounds = internal.getLayerBounds(lyr);
10560
- if (lyrBounds && lyrBounds.hasBounds()) {
10561
- if (lyrBounds.area() > 0 || !arcBounds.hasBounds()) {
10562
- bounds = lyrBounds;
10563
- } else {
10564
- // if a point layer has no extent (e.g. contains only a single point),
10565
- // then merge with arc bounds, to place the point in context.
10566
- bounds = arcBounds.mergeBounds(lyrBounds);
10567
- }
10568
- }
10569
- }
10570
-
10571
- if (!bounds || !bounds.hasBounds()) { // empty layer
10572
- bounds = new Bounds();
10633
+ var bounds = internal.getLayerBounds(lyr, arcs) || new Bounds();
10634
+ if (lyr.geometry_type == 'point' && arcs && bounds.hasBounds() && bounds.area() > 0 === false) {
10635
+ // if a point layer has no extent (e.g. contains only a single point),
10636
+ // then merge with arc bounds, to place the point in context.
10637
+ bounds = bounds.mergeBounds(arcs.getBounds());
10573
10638
  }
10574
10639
  return bounds;
10575
10640
  }
@@ -10843,7 +10908,6 @@
10843
10908
  _ext = new MapExtent(position),
10844
10909
  _nav = new MapNav(gui, _ext, _mouse),
10845
10910
  _visibleLayers = [], // cached visible map layers
10846
- _fullBounds = null,
10847
10911
  _hit,
10848
10912
  _basemap,
10849
10913
  _intersectionLyr, _activeLyr, _overlayLyr,
@@ -10951,8 +11015,8 @@
10951
11015
  updateLayerStyles(getDrawableContentLayers()); // kludge to make sure all layers have styles
10952
11016
 
10953
11017
  // Update map extent (also triggers redraw)
10954
- projectMapExtent(_ext, oldCRS, this.getDisplayCRS(), getFullBounds());
10955
- _fullBounds = getFullBounds(); // update this so map extent doesn't get reset after next update
11018
+ projectMapExtent(_ext, oldCRS, this.getDisplayCRS(), calcFullBounds());
11019
+ updateFullBounds();
10956
11020
  };
10957
11021
 
10958
11022
  // Refresh map display in response to data changes, layer selection, etc.
@@ -10995,28 +11059,27 @@
10995
11059
  gui.dispatchEvent('popup-needs-refresh');
10996
11060
  } else if (_hit) {
10997
11061
  _hit.clearSelection();
10998
- _hit.setLayer(_activeLyr);
10999
11062
  }
11063
+ _hit.setLayer(_activeLyr); // need this every time, to support dynamic reprojection
11000
11064
 
11001
11065
  updateVisibleMapLayers();
11002
- fullBounds = getFullBounds();
11066
+ fullBounds = calcFullBounds();
11003
11067
 
11004
- if (!prevLyr || !_fullBounds || prevLyr.tabular || _activeLyr.tabular || isFrameView()) {
11068
+ if (!prevLyr || prevLyr.tabular || _activeLyr.tabular || isFrameView()) {
11005
11069
  needReset = true;
11006
11070
  } else {
11007
- needReset = mapNeedsReset(fullBounds, _fullBounds, _ext.getBounds(), e.flags);
11071
+ needReset = mapNeedsReset(fullBounds, _ext.getFullBounds(), _ext.getBounds(), e.flags);
11008
11072
  }
11009
11073
 
11010
11074
  if (isFrameView()) {
11011
11075
  _nav.setZoomFactor(0.05); // slow zooming way down to allow fine-tuning frame placement // 0.03
11012
- _ext.setFrame(getFullBounds()); // TODO: remove redundancy with drawLayers()
11076
+ _ext.setFrame(calcFullBounds()); // TODO: remove redundancy with drawLayers()
11013
11077
  needReset = true; // snap to frame extent
11014
11078
  } else {
11015
11079
  _nav.setZoomFactor(1);
11016
11080
  }
11017
11081
  _ext.setFullBounds(fullBounds, getStrictBounds()); // update 'home' button extent
11018
11082
 
11019
- _fullBounds = fullBounds;
11020
11083
  if (needReset) {
11021
11084
  _ext.reset();
11022
11085
  }
@@ -11117,12 +11180,17 @@
11117
11180
  return null;
11118
11181
  }
11119
11182
 
11120
- function getFullBounds() {
11183
+ function updateFullBounds() {
11184
+ _ext.setFullBounds(calcFullBounds(), getStrictBounds());
11185
+ }
11186
+
11187
+ function calcFullBounds() {
11121
11188
  if (isPreviewView()) {
11122
11189
  return internal.getFrameLayerBounds(internal.findFrameLayer(model));
11123
11190
  }
11124
11191
  var b = new Bounds();
11125
- getDrawableContentLayers().forEach(function(lyr) {
11192
+ var layers = getDrawableContentLayers();
11193
+ layers.forEach(function(lyr) {
11126
11194
  b.mergeBounds(lyr.bounds);
11127
11195
  });
11128
11196
 
@@ -11267,6 +11335,7 @@
11267
11335
  // (default) anything could have changed
11268
11336
  function drawLayers2(action) {
11269
11337
  var layersMayHaveChanged = !action;
11338
+ var fullBounds;
11270
11339
  var contentLayers = getDrawableContentLayers();
11271
11340
  var furnitureLayers = getDrawableFurnitureLayers();
11272
11341
  if (!(_ext.width() > 0 && _ext.height() > 0)) {
@@ -11277,7 +11346,7 @@
11277
11346
  if (layersMayHaveChanged) {
11278
11347
  // kludge to handle layer visibility toggling
11279
11348
  _ext.setFrame(isPreviewView() ? getFrameData() : null);
11280
- _ext.setFullBounds(getFullBounds(), getStrictBounds());
11349
+ updateFullBounds();
11281
11350
  updateLayerStyles(contentLayers);
11282
11351
  updateLayerStackOrder(model.getLayers());// update menu_order property of all layers
11283
11352
  }