mapshaper 0.6.7 → 0.6.10

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  (function () {
2
2
 
3
- var VERSION = "0.6.7";
3
+ var VERSION = "0.6.10";
4
4
 
5
5
 
6
6
  var utils = /*#__PURE__*/Object.freeze({
@@ -8470,7 +8470,9 @@
8470
8470
  function getBoundsPrecisionForDisplay(bbox) {
8471
8471
  var w = Math.abs(bbox[2] - bbox[0]),
8472
8472
  h = Math.abs(bbox[3] - bbox[1]),
8473
- range = Math.min(w, h) + 1e-8,
8473
+ // switched to max bound, based on experience with shift-drag box info
8474
+ // range = Math.min(w, h) + 1e-8,
8475
+ range = Math.max(w, h) + 1e-8,
8474
8476
  digits = 0;
8475
8477
  while (range < 2000) {
8476
8478
  range *= 10;
@@ -9809,6 +9811,30 @@
9809
9811
  }
9810
9812
 
9811
9813
  if (hasPaths) {
9814
+
9815
+ ctx.bboxContainsPoint = function(x, y) {
9816
+ var bounds = arcs.getMultiShapeBounds(_ids);
9817
+ return bounds.containsPoint(x, y);
9818
+ };
9819
+
9820
+ ctx.bboxIntersectsRectangle = function(a, b, c, d) {
9821
+ var bbox = arcs.getMultiShapeBounds(_ids);
9822
+ var rect = Bounds.from(a, b, c, d);
9823
+ return rect.intersects(bbox);
9824
+ };
9825
+
9826
+ ctx.bboxContainsRectangle = function(a, b, c, d) {
9827
+ var bbox = arcs.getMultiShapeBounds(_ids);
9828
+ var rect = Bounds.from(a, b, c, d);
9829
+ return bbox.contains(rect);
9830
+ };
9831
+
9832
+ ctx.bboxContainedByRectangle = function(a, b, c, d) {
9833
+ var bbox = arcs.getMultiShapeBounds(_ids);
9834
+ var rect = Bounds.from(a, b, c, d);
9835
+ return rect.contains(bbox);
9836
+ };
9837
+
9812
9838
  addGetters(ctx, {
9813
9839
  // TODO: count hole/s + containing ring as one part
9814
9840
  partCount: function() {
@@ -14850,6 +14876,7 @@
14850
14876
  href: d.href || ''
14851
14877
  }
14852
14878
  };
14879
+ if (d.fill) o.properties.fill = d.fill;
14853
14880
  return o;
14854
14881
  }
14855
14882
 
@@ -19564,6 +19591,10 @@ ${svg}
19564
19591
  describe: 'a pair of values (0-100) for limiting a color ramp',
19565
19592
  type: 'numbers'
19566
19593
  })
19594
+ .option('range', {
19595
+ // describe: 'a pair of numbers defining the effective data range',
19596
+ type: 'numbers'
19597
+ })
19567
19598
  .option('null-value', {
19568
19599
  describe: 'value (or color) to use for invalid or missing data'
19569
19600
  })
@@ -29917,10 +29948,25 @@ ${svg}
29917
29948
  }
29918
29949
 
29919
29950
  var ascending = getAscendingNumbers(dataValues);
29951
+ if (opts.range) {
29952
+ ascending = applyDataRange(ascending, opts.range);
29953
+ }
29920
29954
  var nullCount = dataValues.length - ascending.length;
29921
29955
  var minVal = ascending[0];
29922
29956
  var maxVal = ascending[ascending.length - 1];
29923
29957
 
29958
+ // kludge
29959
+ var clamp = opts.range ? function(val) {
29960
+ if (val < opts.range[0]) val = opts.range[0];
29961
+ if (val > opts.range[1]) val = opts.range[1];
29962
+ return val;
29963
+ } : null;
29964
+
29965
+ if (opts.range) {
29966
+ minVal = opts.range[0];
29967
+ maxVal = opts.range[1];
29968
+ }
29969
+
29924
29970
  if (numBreaks === 0) {
29925
29971
  breaks = [];
29926
29972
  } else if (opts.breaks) {
@@ -29948,6 +29994,7 @@ ${svg}
29948
29994
  }
29949
29995
  classToValue = getOutputFunction(classValues, nullValue, opts);
29950
29996
  classifier = function(val) {
29997
+ if (clamp) val = clamp(val);
29951
29998
  return classToValue(dataToClass(val));
29952
29999
  };
29953
30000
 
@@ -30132,6 +30179,26 @@ ${svg}
30132
30179
  return arr;
30133
30180
  }
30134
30181
 
30182
+ function applyDataRange(values, range) {
30183
+ var minval = range[0];
30184
+ var maxval = range[1];
30185
+ if (maxval > minval === false) {
30186
+ stop('Invalid data range:', range);
30187
+ }
30188
+ var values2 = values.map(function(val) {
30189
+ if (val < minval) val = minval;
30190
+ if (val > maxval) val = maxval;
30191
+ return val;
30192
+ });
30193
+ if (values2[0] < minval) {
30194
+ values2.unshift(minval);
30195
+ }
30196
+ if (values2[values2.length - 1] < maxval) {
30197
+ values2.push(maxval);
30198
+ }
30199
+ return values2;
30200
+ }
30201
+
30135
30202
  function getAscendingNumbers(values) {
30136
30203
  var numbers = values.filter(utils.isFiniteNumber);
30137
30204
  utils.genericSort(numbers, true);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mapshaper",
3
- "version": "0.6.7",
3
+ "version": "0.6.10",
4
4
  "description": "A tool for editing vector datasets for mapping and GIS.",
5
5
  "keywords": [
6
6
  "shapefile",
@@ -1187,7 +1187,13 @@
1187
1187
  // FF: supports pasting JSON and CSV from the clipboard but not files.
1188
1188
  // Single files of all types are pasted as a string and an image/png
1189
1189
  // Multiple files are pasted as a string containing a list of file names
1190
- if (types == 'text/plain') {
1190
+
1191
+ // import text from the clipboard (could be csv, json, etc)
1192
+ // formatted text can be available as both text/plain and text/html (e.g.
1193
+ // a JSON data object copied from a GitHub issue).
1194
+ //
1195
+ if (types.includes('text/plain')) {
1196
+ // if (types == 'text/plain') {
1191
1197
  // text from clipboard (supported by Chrome, FF, Safari)
1192
1198
  // TODO: handle FF case of string containing multiple file names.
1193
1199
  files = [pastedTextToFile(e.clipboardData.getData('text/plain'))];
@@ -2040,7 +2046,7 @@
2040
2046
  // bbox: display coords
2041
2047
  // intended to work with rectangular projections like Mercator
2042
2048
  function getBBoxCoords(lyr, bbox) {
2043
- if (!isProjectedLayer(lyr)) return bbox;
2049
+ if (!isProjectedLayer(lyr)) return bbox.concat();
2044
2050
  var a = translateDisplayPoint(lyr, [bbox[0], bbox[1]]);
2045
2051
  var b = translateDisplayPoint(lyr, [bbox[2], bbox[3]]);
2046
2052
  var bounds = new internal.Bounds();
@@ -6917,9 +6923,208 @@
6917
6923
  });
6918
6924
  }
6919
6925
 
6926
+ function HighlightBox(gui, optsArg) {
6927
+ var el = El('div').addClass('zoom-box').appendTo('body'),
6928
+ opts = Object.assign({handles: false, persistent: false}, optsArg),
6929
+ box = new EventDispatcher(),
6930
+ stroke = 2,
6931
+ activeHandle = null,
6932
+ prevXY = null,
6933
+ boxCoords = null,
6934
+ _on = false,
6935
+ handles;
6936
+
6937
+ el.hide();
6938
+
6939
+ gui.on('map_navigation', function() {
6940
+ if (!_on) return;
6941
+ redraw();
6942
+ });
6943
+
6944
+ gui.on('box_drag', function(e) {
6945
+ if (!_on) return;
6946
+ boxCoords = getBoxCoords(e.data);
6947
+ redraw();
6948
+ box.dispatchEvent('drag');
6949
+ });
6950
+
6951
+ gui.on('box_drag_end', function(e) {
6952
+ if (!_on) return;
6953
+ boxCoords = getBoxCoords(e.data);
6954
+ var pix = coordsToPix(boxCoords, gui.map.getExtent());
6955
+ box.dispatchEvent('dragend', {map_bbox: pix});
6956
+ if (!opts.persistent) {
6957
+ box.hide();
6958
+ } else {
6959
+ redraw();
6960
+ }
6961
+ });
6962
+
6963
+ if (opts.handles) {
6964
+ handles = initHandles(el);
6965
+ handles.forEach(function(handle) {
6966
+ handle.el.on('mousedown', function(e) {
6967
+ activeHandle = handle;
6968
+ prevXY = {x: e.pageX, y: e.pageY};
6969
+ });
6970
+ });
6971
+
6972
+ document.addEventListener('mousemove', function(e) {
6973
+ if (!_on || !activeHandle || !prevXY || !boxCoords) return;
6974
+ var xy = {x: e.pageX, y: e.pageY};
6975
+ var scale = gui.map.getExtent().getPixelSize();
6976
+ var dx = (xy.x - prevXY.x) * scale;
6977
+ var dy = -(xy.y - prevXY.y) * scale;
6978
+ if (activeHandle.col == 'left') {
6979
+ boxCoords[0] += dx;
6980
+ } else if (activeHandle.col == 'right') {
6981
+ boxCoords[2] += dx;
6982
+ }
6983
+ if (activeHandle.row == 'top') {
6984
+ boxCoords[3] += dy;
6985
+ } else if (activeHandle.row == 'bottom') {
6986
+ boxCoords[1] += dy;
6987
+ }
6988
+ prevXY = xy;
6989
+ redraw();
6990
+ box.dispatchEvent('handle_drag');
6991
+ });
6992
+
6993
+ document.addEventListener('mouseup', function() {
6994
+ if (activeHandle && _on) {
6995
+ activeHandle = null;
6996
+ prevXY = null;
6997
+ box.dispatchEvent('handle_up');
6998
+ // reset box if it has been inverted (by dragging)
6999
+ fixBounds(boxCoords);
7000
+ redraw();
7001
+ }
7002
+ });
7003
+ }
7004
+
7005
+ box.getDataCoords = function() {
7006
+ if (!boxCoords) return null;
7007
+ var dataBox = getBBoxCoords(gui.map.getActiveLayer(), boxCoords);
7008
+ fixBounds(dataBox);
7009
+ return internal.getRoundedCoords(dataBox, internal.getBoundsPrecisionForDisplay(dataBox));
7010
+ };
7011
+
7012
+ box.turnOn = function() {
7013
+ _on = true;
7014
+ };
7015
+
7016
+ box.turnOff = function() {
7017
+ _on = false;
7018
+ };
7019
+
7020
+ box.hide = function() {
7021
+ el.hide();
7022
+ boxCoords = null;
7023
+ };
7024
+
7025
+ box.show = function(x1, y1, x2, y2) {
7026
+ var w = Math.abs(x1 - x2),
7027
+ h = Math.abs(y1 - y2),
7028
+ props = {
7029
+ top: Math.min(y1, y2),
7030
+ left: Math.min(x1, x2),
7031
+ width: Math.max(w - stroke * 2, 1),
7032
+ height: Math.max(h - stroke * 2, 1)
7033
+ };
7034
+ el.css(props);
7035
+ el.show();
7036
+ if (handles) {
7037
+ showHandles(handles, props);
7038
+ }
7039
+ };
7040
+
7041
+ function getBoxCoords(e) {
7042
+ var bbox = pixToCoords(e.a.concat(e.b), gui.map.getExtent());
7043
+ fixBounds(bbox);
7044
+ return bbox;
7045
+ }
7046
+
7047
+ function redraw() {
7048
+ if (!boxCoords) return;
7049
+ var ext = gui.map.getExtent();
7050
+ var b = coordsToPix(boxCoords, ext);
7051
+ var pos = ext.position();
7052
+ var dx = pos.pageX,
7053
+ dy = pos.pageY;
7054
+ box.show(b[0] + dx, b[1] + dy, b[2] + dx, b[3] + dy);
7055
+ }
7056
+
7057
+ return box;
7058
+ }
7059
+
7060
+ function coordsToPix(bbox, ext) {
7061
+ var a = ext.translateCoords(bbox[0], bbox[1]);
7062
+ var b = ext.translateCoords(bbox[2], bbox[3]);
7063
+ return [a[0], b[1], b[0], a[1]];
7064
+ }
7065
+
7066
+ function pixToCoords(bbox, ext) {
7067
+ var a = ext.translatePixelCoords(bbox[0], bbox[1]);
7068
+ var b = ext.translatePixelCoords(bbox[2], bbox[3]);
7069
+ return [a[0], b[1], b[0], a[1]];
7070
+ }
7071
+
7072
+
7073
+ function fixBounds(bbox) {
7074
+ var tmp;
7075
+ if (bbox[0] > bbox[2]) {
7076
+ tmp = bbox[0];
7077
+ bbox[0] = bbox[2];
7078
+ bbox[2] = tmp;
7079
+ }
7080
+ if (bbox[1] > bbox[3]) {
7081
+ tmp = bbox[1];
7082
+ bbox[1] = bbox[3];
7083
+ bbox[3] = tmp;
7084
+ }
7085
+ }
7086
+
7087
+ function initHandles(el) {
7088
+ var handles = [];
7089
+ for (var i=0; i<9; i++) {
7090
+ if (i == 4) continue;
7091
+ var c = Math.floor(i / 3);
7092
+ var r = i % 3;
7093
+ handles.push({
7094
+ el: El('div').addClass('handle').appendTo(el),
7095
+ col: c == 0 && 'left' || c == 1 && 'center' || 'right',
7096
+ row: r == 0 && 'top' || r == 1 && 'center' || 'bottom'
7097
+ });
7098
+ }
7099
+ return handles;
7100
+ }
7101
+
7102
+ function showHandles(handles, props) {
7103
+ var SIZE = 6; // should match .handle size in page.css
7104
+ handles.forEach(function(handle) {
7105
+ var top = 0,
7106
+ left = 0;
7107
+ if (handle.col == 'center') {
7108
+ left += props.width / 2 - SIZE / 2;
7109
+ } else if (handle.col == 'right') {
7110
+ left += props.width - SIZE;
7111
+ }
7112
+ if (handle.row == 'center') {
7113
+ top += props.height / 2 - SIZE / 2;
7114
+ } else if (handle.row == 'bottom') {
7115
+ top += props.height - SIZE;
7116
+ }
7117
+ handle.el.css({
7118
+ top: top,
7119
+ left: left
7120
+ });
7121
+ });
7122
+ }
7123
+
6920
7124
  function MapNav(gui, ext, mouse) {
6921
7125
  var wheel = new MouseWheel(mouse),
6922
7126
  zoomTween = new Tween(Tween.sineInOut),
7127
+ zoomBox = new HighlightBox(gui), // .addClass('zooming'),
6923
7128
  boxDrag = false,
6924
7129
  zoomScaleMultiplier = 1,
6925
7130
  inBtn, outBtn,
@@ -6953,6 +7158,11 @@
6953
7158
  ext.home();
6954
7159
  });
6955
7160
 
7161
+ ext.on('change', function() {
7162
+ // kludge so controls (e.g. HighlightBox) can initialize before map is ready
7163
+ gui.dispatchEvent('map_navigation');
7164
+ });
7165
+
6956
7166
  zoomTween.on('change', function(e) {
6957
7167
  ext.zoomToExtent(e.value, _fx, _fy);
6958
7168
  });
@@ -6972,6 +7182,7 @@
6972
7182
  // zoomDrag = !!e.metaKey || !!e.ctrlKey; // meta is command on mac, windows key on windows
6973
7183
  boxDrag = !!e.shiftKey;
6974
7184
  if (boxDrag) {
7185
+ if (useBoxZoom()) zoomBox.turnOn();
6975
7186
  dragStartEvt = e;
6976
7187
  gui.dispatchEvent('box_drag_start');
6977
7188
  }
@@ -6992,9 +7203,14 @@
6992
7203
  if (boxDrag) {
6993
7204
  boxDrag = false;
6994
7205
  gui.dispatchEvent('box_drag_end', getBoxData(e));
7206
+ zoomBox.turnOff();
6995
7207
  }
6996
7208
  });
6997
7209
 
7210
+ zoomBox.on('dragend', function(e) {
7211
+ zoomToBbox(e.map_bbox);
7212
+ });
7213
+
6998
7214
  wheel.on('mousewheel', function(e) {
6999
7215
  var tickFraction = 0.11; // 0.15; // fraction of zoom step per wheel event;
7000
7216
  var k = 1 + (tickFraction * e.multiplier * zoomScaleMultiplier),
@@ -7003,46 +7219,17 @@
7003
7219
  ext.zoomByPct(delta, e.x / ext.width(), e.y / ext.height());
7004
7220
  });
7005
7221
 
7006
- function fixBounds(bbox) {
7007
- if (bbox[0] > bbox[2]) {
7008
- swapElements(bbox, 0, 2);
7009
- }
7010
- if (bbox[1] > bbox[3]) {
7011
- swapElements(bbox, 1, 3);
7012
- }
7013
- }
7014
-
7015
- function swapElements(arr, i, j) {
7016
- var tmp = arr[i];
7017
- arr[i] = arr[j];
7018
- arr[j] = tmp;
7222
+ function useBoxZoom() {
7223
+ return gui.getMode() != 'selection_tool' && gui.getMode() != 'box_tool';
7019
7224
  }
7020
7225
 
7021
7226
  function getBoxData(e) {
7022
- var pageBox = [e.pageX, e.pageY, dragStartEvt.pageX, dragStartEvt.pageY];
7023
- var mapBox = [e.x, e.y, dragStartEvt.x, dragStartEvt.y];
7024
- var displayBox = pixToCoords(mapBox);
7025
- var dataBox = getBBoxCoords(gui.map.getActiveLayer(), displayBox);
7026
- fixBounds(pageBox);
7027
- fixBounds(mapBox);
7028
- fixBounds(displayBox);
7029
- fixBounds(dataBox);
7030
7227
  return {
7031
- map_bbox: mapBox,
7032
- page_bbox: pageBox,
7033
- // round coords, for nicer 'info' display
7034
- // (rounded precision should be sub-pixel)
7035
- map_display_bbox: internal.getRoundedCoords(displayBox, internal.getBoundsPrecisionForDisplay(displayBox)),
7036
- map_data_bbox: internal.getRoundedCoords(dataBox, internal.getBoundsPrecisionForDisplay(dataBox))
7228
+ a: [e.x, e.y],
7229
+ b: [dragStartEvt.x, dragStartEvt.y]
7037
7230
  };
7038
7231
  }
7039
7232
 
7040
- function pixToCoords(bbox) {
7041
- var a = ext.translatePixelCoords(bbox[0], bbox[1]);
7042
- var b = ext.translatePixelCoords(bbox[2], bbox[3]);
7043
- return [a[0], b[1], b[0], a[1]];
7044
- }
7045
-
7046
7233
  function disabled() {
7047
7234
  return !!gui.options.disableNavigation;
7048
7235
  }
@@ -7087,28 +7274,9 @@
7087
7274
  }
7088
7275
  }
7089
7276
 
7090
- function HighlightBox() {
7091
- var box = El('div').addClass('zoom-box').appendTo('body'),
7092
- show = box.show.bind(box), // original show() function
7093
- stroke = 2;
7094
- box.hide();
7095
- box.show = function(x1, y1, x2, y2) {
7096
- var w = Math.abs(x1 - x2),
7097
- h = Math.abs(y1 - y2);
7098
- box.css({
7099
- top: Math.min(y1, y2),
7100
- left: Math.min(x1, x2),
7101
- width: Math.max(w - stroke * 2, 1),
7102
- height: Math.max(h - stroke * 2, 1)
7103
- });
7104
- show();
7105
- };
7106
- return box;
7107
- }
7108
-
7109
7277
  function SelectionTool(gui, ext, hit) {
7110
7278
  var popup = gui.container.findChild('.selection-tool-options');
7111
- var box = new HighlightBox();
7279
+ var box = new HighlightBox(gui);
7112
7280
  var _on = false;
7113
7281
 
7114
7282
  gui.addMode('selection_tool', turnOn, turnOff);
@@ -7121,16 +7289,17 @@
7121
7289
  }
7122
7290
  });
7123
7291
 
7124
- gui.on('box_drag', function(e) {
7292
+ box.on('drag', function(e) {
7125
7293
  if (!_on) return;
7126
- var b = e.page_bbox;
7127
- box.show(b[0], b[1], b[2], b[3]);
7128
- updateSelection(e.map_data_bbox, true);
7294
+ updateSelection(box.getDataCoords(), true);
7129
7295
  });
7130
7296
 
7131
- gui.on('box_drag_end', function(e) {
7297
+ box.on('dragend', function(e) {
7132
7298
  if (!_on) return;
7133
- box.hide();
7299
+ updateSelection(box.getDataCoords());
7300
+ });
7301
+
7302
+ gui.on('selection_bridge', function(e) {
7134
7303
  updateSelection(e.map_data_bbox);
7135
7304
  });
7136
7305
 
@@ -7145,10 +7314,12 @@
7145
7314
  }
7146
7315
 
7147
7316
  function turnOn() {
7317
+ box.turnOn();
7148
7318
  _on = true;
7149
7319
  }
7150
7320
 
7151
7321
  function turnOff() {
7322
+ box.turnOff();
7152
7323
  reset();
7153
7324
  _on = false;
7154
7325
  if (gui.interaction.getMode() == 'selection') {
@@ -7698,6 +7869,7 @@
7698
7869
  var node2;
7699
7870
  o.properties.transform = getSvgSymbolTransform(xy, ext);
7700
7871
  o.properties['data-id'] = id;
7872
+ o.properties.class = 'mapshaper-svg-symbol';
7701
7873
  // o.properties['class'] = 'selected';
7702
7874
  g.innerHTML = internal.svg.stringify(o);
7703
7875
  node2 = g.firstChild;
@@ -9360,15 +9532,14 @@
9360
9532
  }
9361
9533
  }
9362
9534
 
9363
- // Controls both the shift-drag zoom-to-extent tool and the shift-drag editing tool
9364
-
9365
- function BoxTool(gui, ext, mouse, nav) {
9535
+ // Controls the shift-drag box editing tool
9536
+ //
9537
+ function BoxTool(gui, ext, nav) {
9366
9538
  var self = new EventDispatcher();
9367
- var box = new HighlightBox();
9539
+ var box = new HighlightBox(gui, {persistent: true, handles: true});
9368
9540
  var popup = gui.container.findChild('.box-tool-options');
9369
9541
  var coords = popup.findChild('.box-coords');
9370
9542
  var _on = false;
9371
- var bboxData;
9372
9543
 
9373
9544
  var infoBtn = new SimpleButton(popup.findChild('.info-btn')).on('click', function() {
9374
9545
  if (coords.visible()) hideCoords(); else showCoords();
@@ -9378,28 +9549,19 @@
9378
9549
  reset();
9379
9550
  });
9380
9551
 
9381
- // Removing zoom-in button -- cumbersome way to zoom
9382
- // new SimpleButton(popup.findChild('.zoom-btn')).on('click', function() {
9383
- // nav.zoomToBbox(bboxPixels);
9384
- // reset();
9385
- // });
9386
-
9387
- // Removing button for creating a layer containing a single rectangle.
9388
- // You can get the bbox with the Info button and create a rectangle in the console
9389
- // using -rectangle bbox=<coordinates>
9390
- // new SimpleButton(popup.findChild('.rectangle-btn')).on('click', function() {
9391
- // runCommand('-rectangle bbox=' + bbox.join(','));
9392
- // });
9393
-
9394
9552
  new SimpleButton(popup.findChild('.select-btn')).on('click', function() {
9553
+ var coords = box.getDataCoords();
9554
+ if (!coords) return;
9395
9555
  gui.enterMode('selection_tool');
9396
9556
  gui.interaction.setMode('selection');
9397
9557
  // kludge to pass bbox to the selection tool
9398
- gui.dispatchEvent('box_drag_end', bboxData);
9558
+ gui.dispatchEvent('selection_bridge', {
9559
+ map_data_bbox: coords
9560
+ });
9399
9561
  });
9400
9562
 
9401
9563
  new SimpleButton(popup.findChild('.clip-btn')).on('click', function() {
9402
- runCommand('-clip bbox=' + bboxData.map_data_bbox.join(','));
9564
+ runCommand('-clip bbox=' + box.getDataCoords().join(','));
9403
9565
  });
9404
9566
 
9405
9567
  gui.addMode('box_tool', turnOn, turnOff);
@@ -9412,37 +9574,18 @@
9412
9574
  }
9413
9575
  });
9414
9576
 
9415
- // Update the visible rectangle when the map view changes
9416
- // (e.g. during zooming or panning)
9417
- ext.on('change', function() {
9418
- if (!_on || !box.visible() || !bboxData) return;
9419
- var b = coordsToPix(bboxData.map_display_bbox);
9420
- var pos = ext.position();
9421
- var dx = pos.pageX,
9422
- dy = pos.pageY;
9423
- box.show(b[0] + dx, b[1] + dy, b[2] + dx, b[3] + dy);
9424
- });
9425
-
9426
9577
  gui.on('box_drag_start', function() {
9427
- box.classed('zooming', inZoomMode());
9578
+ // box.classed('zooming', inZoomMode());
9428
9579
  hideCoords();
9429
9580
  });
9430
9581
 
9431
- gui.on('box_drag', function(e) {
9432
- var b = e.page_bbox;
9433
- bboxData = e.data;
9434
- if (_on || inZoomMode()) {
9435
- box.show(b[0], b[1], b[2], b[3]);
9436
- }
9582
+ box.on('dragend', function(e) {
9583
+ if (_on) popup.show();
9437
9584
  });
9438
9585
 
9439
- gui.on('box_drag_end', function(e) {
9440
- bboxData = e.data;
9441
- if (inZoomMode()) {
9442
- box.hide();
9443
- nav.zoomToBbox(e.map_bbox);
9444
- } else if (_on) {
9445
- popup.show();
9586
+ box.on('handle_drag', function() {
9587
+ if (coords.visible()) {
9588
+ showCoords();
9446
9589
  }
9447
9590
  });
9448
9591
 
@@ -9461,7 +9604,7 @@
9461
9604
 
9462
9605
  function showCoords() {
9463
9606
  El(infoBtn.node()).addClass('selected-btn');
9464
- coords.text(bboxData.map_data_bbox.join(','));
9607
+ coords.text(box.getDataCoords().join(','));
9465
9608
  coords.show();
9466
9609
  GUI.selectElement(coords.node());
9467
9610
  }
@@ -9472,10 +9615,12 @@
9472
9615
  }
9473
9616
 
9474
9617
  function turnOn() {
9618
+ box.turnOn();
9475
9619
  _on = true;
9476
9620
  }
9477
9621
 
9478
9622
  function turnOff() {
9623
+ box.turnOff();
9479
9624
  if (gui.interaction.getMode() == 'box') {
9480
9625
  // mode change was not initiated by interactive menu -- turn off interactivity
9481
9626
  gui.interaction.turnOff();
@@ -9490,12 +9635,6 @@
9490
9635
  hideCoords();
9491
9636
  }
9492
9637
 
9493
- function coordsToPix(bbox) {
9494
- var a = ext.translateCoords(bbox[0], bbox[1]);
9495
- var b = ext.translateCoords(bbox[2], bbox[3]);
9496
- return [a[0], b[1], b[0], a[1]];
9497
- }
9498
-
9499
9638
  return self;
9500
9639
  }
9501
9640
 
@@ -10012,7 +10151,7 @@
10012
10151
  _ext = new MapExtent(position),
10013
10152
  _hit = new InteractiveSelection(gui, _ext, _mouse),
10014
10153
  _nav = new MapNav(gui, _ext, _mouse),
10015
- _boxTool = new BoxTool(gui, _ext, _mouse, _nav),
10154
+ _boxTool = new BoxTool(gui, _ext, _nav),
10016
10155
  _selectionTool = new SelectionTool(gui, _ext, _hit),
10017
10156
  _visibleLayers = [], // cached visible map layers
10018
10157
  _fullBounds = null,