mapshaper 0.6.59 → 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/www/index.html CHANGED
@@ -96,8 +96,8 @@
96
96
  <div class="layer-menu">
97
97
  <h3>Layers</h3>
98
98
  <div class="pin-all pinnable">
99
- <img class="pin-btn unpinned" src="images/eye.png">
100
- <img class="pin-btn pinned" src="images/eye2.png">
99
+ <img class="eye-btn black-eye" src="images/eye.png">
100
+ <img class="eye-btn green-eye" src="images/eye2.png">
101
101
  </div>
102
102
  <div class="layer-list"></div>
103
103
  <!-- <h4>Sources</h4> -->
@@ -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
 
@@ -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;});
@@ -4285,8 +4260,8 @@
4285
4260
  html += rowHTML('contents', describeLyr(lyr));
4286
4261
  html += '<img class="close-btn" draggable="false" src="images/close.png">';
4287
4262
  if (opts.pinnable) {
4288
- html += '<img class="pin-btn unpinned" draggable="false" src="images/eye.png">';
4289
- html += '<img class="pin-btn pinned" draggable="false" src="images/eye2.png">';
4263
+ html += '<img class="eye-btn black-eye" draggable="false" src="images/eye.png">';
4264
+ html += '<img class="eye-btn green-eye" draggable="false" src="images/eye2.png">';
4290
4265
  }
4291
4266
  html += '</div>';
4292
4267
  return html;
@@ -4354,7 +4329,7 @@
4354
4329
 
4355
4330
  if (pinnable) {
4356
4331
  // init pin button
4357
- GUI.onClick(entry.findChild('img.unpinned'), function(e) {
4332
+ GUI.onClick(entry.findChild('img.black-eye'), function(e) {
4358
4333
  var target = findLayerById(id);
4359
4334
  var pinned = target.layer.pinned;
4360
4335
  e.stopPropagation();
@@ -4364,8 +4339,8 @@
4364
4339
  map.redraw();
4365
4340
  });
4366
4341
 
4367
- // catch click event on pin button
4368
- GUI.onClick(entry.findChild('img.unpinned'), function(e) {
4342
+ // catch click event on black (top) pin button button
4343
+ GUI.onClick(entry.findChild('img.black-eye'), function(e) {
4369
4344
  e.stopPropagation();
4370
4345
  });
4371
4346
  }
@@ -4507,8 +4482,8 @@
4507
4482
  }
4508
4483
  };
4509
4484
 
4510
- this.dataValueUpdated = function(id, field, value) {
4511
- var cmd = `-each 'd[${JSON.stringify(field)}] = ${JSON.stringify(value)}' where='this.id == ${id}'`;
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
- this.addHistoryState(undo, redo);
4618
- }, this);
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 = this.makeDataSetter(e.FID);
4624
- }, this);
4620
+ stashedUndo = makeDataSetter(e.FID);
4621
+ });
4625
4622
 
4626
4623
  gui.on('label_dragend', function(e) {
4627
- var redo = this.makeDataSetter(e.FID);
4628
- this.addHistoryState(stashedUndo, redo);
4629
- }, this);
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 = this.makeDataSetter(e.FID);
4636
- }, this);
4632
+ stashedUndo = makeMultiDataSetter(e.ids);
4633
+ });
4637
4634
 
4638
4635
  gui.on('data_postupdate', function(e) {
4639
- var redo = this.makeDataSetter(e.FID);
4640
- this.addHistoryState(stashedUndo, redo);
4641
- }, this);
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
- this.addHistoryState(undo, redo);
4661
- }, this);
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
- this.addHistoryState(undo, redo);
4673
- }, this);
4669
+ addHistoryState(undo, redo);
4670
+ });
4674
4671
 
4675
4672
  this.clear = function() {
4676
4673
  reset();
4677
4674
  };
4678
4675
 
4679
- this.makeDataSetter = function(id) {
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 InteractiveSelection(gui, ext, mouse) {
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() && interactionMode != 'selection';
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(mergeClickData(hitTest(e)));
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
- function mergeClickData(hitData) {
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 currId = -1;
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
- currId = id;
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
- currId = -1;
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(recId, lyr);
8404
+ renderAddFieldPopup(recIds, lyr);
8365
8405
  }).text('+ add field');
8366
8406
  }
8367
8407
  }
8368
8408
 
8369
- function renderAddFieldPopup(recId, lyr) {
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 += `this.id != ${recId} ? null : `;
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', {FID: currId}); // for undo/redo
8497
+ gui.dispatchEvent('data_preupdate', {ids: currIds}); // for undo/redo
8455
8498
  rec[key] = val2;
8456
- gui.dispatchEvent('data_postupdate', {FID: currId});
8499
+ gui.dispatchEvent('data_postupdate', {ids: currIds});
8457
8500
  input.value(strval);
8458
8501
  setFieldClass(el, val2, type);
8459
- self.dispatchEvent('update', {field: key, value: val2, id: currId});
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('update', function(e) {
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.id, e.field, e.value);
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();
@@ -10371,7 +10414,7 @@
10371
10414
  }
10372
10415
  obj.properties.transform = getSvgFurnitureTransform(ext);
10373
10416
  obj.properties.class = 'mapshaper-svg-furniture';
10374
- obj.children = internal.importFurniture(internal.getFrameLayerData(lyr), frame);
10417
+ obj.children = internal.renderFurnitureLayer(lyr, frame);
10375
10418
  return internal.svg.stringify(obj);
10376
10419
  }
10377
10420
 
@@ -10817,12 +10860,14 @@
10817
10860
  }
10818
10861
 
10819
10862
  if (internal.layerHasFurniture(layer)) {
10820
- obj.furniture = true;
10821
- obj.furniture_type = internal.getFurnitureLayerType(layer);
10822
10863
  obj.layer = layer;
10864
+ obj.tabular = true;
10865
+ // TODO: consider how to render furniture in GUI
10866
+ // obj.furniture = true;
10867
+ // obj.furniture_type = internal.getFurnitureLayerType(layer);
10823
10868
  // treating furniture layers (other than frame) as tabular for now,
10824
10869
  // so there is something to show if they are selected
10825
- obj.tabular = obj.furniture_type != 'frame';
10870
+ // obj.tabular = obj.furniture_type != 'frame';
10826
10871
  } else if (obj.empty) {
10827
10872
  obj.layer = {shapes: []}; // ideally we should avoid empty layers
10828
10873
  } else if (!layer.geometry_type) {
@@ -11323,7 +11368,7 @@
11323
11368
  gui.buttons.show();
11324
11369
 
11325
11370
  if (opts.inspectorControl) {
11326
- _hit = new InteractiveSelection(gui, _ext, _mouse),
11371
+ _hit = new HitControl(gui, _ext, _mouse),
11327
11372
  new InspectionControl2(gui, _hit);
11328
11373
  new SelectionTool(gui, _ext, _hit),
11329
11374
  new BoxTool(gui, _ext, _nav),
@@ -11368,7 +11413,6 @@
11368
11413
  };
11369
11414
  }
11370
11415
 
11371
-
11372
11416
  // Update map frame after user navigates the map in frame edit mode
11373
11417
  function updateFrameExtent() {
11374
11418
  var frameLyr = internal.findFrameLayer(model);
@@ -11434,10 +11478,6 @@
11434
11478
  return isActiveLayer(lyr) || lyr.pinned;
11435
11479
  }
11436
11480
 
11437
- function isVisibleDataLayer(lyr) {
11438
- return isVisibleLayer(lyr) && !internal.isFurnitureLayer(lyr);
11439
- }
11440
-
11441
11481
  function isFrameLayer(lyr) {
11442
11482
  return !!(lyr && lyr == internal.findFrameLayer(model));
11443
11483
  }
@@ -11446,20 +11486,25 @@
11446
11486
  return !isPreviewView() && !!_activeLyr.tabular;
11447
11487
  }
11448
11488
 
11489
+ // Preview view: a special view centering the map 'frame'
11490
+ // (disabling this pending interface rethink)
11449
11491
  function isPreviewView() {
11450
- var frameLyr = internal.findFrameLayer(model);
11451
- return !!frameLyr; // && isVisibleLayer(frameLyr)
11492
+ return false;
11493
+ // var frameLyr = internal.findFrameLayer(model);
11494
+ // return !!frameLyr; // && isVisibleLayer(frameLyr)
11452
11495
  }
11453
11496
 
11454
11497
  // Frame view means frame layer is visible and active (selected)
11498
+ // (disabling pending rethink)
11455
11499
  function isFrameView() {
11456
- var frameLyr = internal.findFrameLayer(model);
11457
- return isActiveLayer(frameLyr) && isVisibleLayer(frameLyr);
11500
+ return false;
11501
+ // var frameLyr = internal.findFrameLayer(model);
11502
+ // return isActiveLayer(frameLyr) && isVisibleLayer(frameLyr);
11458
11503
  }
11459
11504
 
11460
11505
  function getFrameData() {
11461
11506
  var frameLyr = internal.findFrameLayer(model);
11462
- return frameLyr && internal.getFrameLayerData(frameLyr) || null;
11507
+ return frameLyr && internal.getFurnitureLayerData(frameLyr) || null;
11463
11508
  }
11464
11509
 
11465
11510
  function clearAllDisplayArcs() {