mapshaper 0.6.74 → 0.6.76

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/mapshaper.js CHANGED
@@ -749,7 +749,7 @@
749
749
  }
750
750
 
751
751
  function getGenericComparator(asc) {
752
- asc = asc !== false;
752
+ asc = asc !== false && asc != 'descending'; // ascending is the default
753
753
  return function(a, b) {
754
754
  var retn = 0;
755
755
  if (b == null) {
@@ -1362,13 +1362,13 @@
1362
1362
  }
1363
1363
 
1364
1364
  // Format an array of (preferably short) strings in columns for console logging.
1365
- function formatStringsAsGrid(arr) {
1365
+ function formatStringsAsGrid(arr, width) {
1366
1366
  // TODO: variable column width
1367
1367
  var longest = arr.reduce(function(len, str) {
1368
1368
  return Math.max(len, str.length);
1369
1369
  }, 0),
1370
1370
  colWidth = longest + 2,
1371
- perLine = Math.floor(80 / colWidth) || 1;
1371
+ perLine = Math.floor((width || 80) / colWidth) || 1;
1372
1372
  return arr.reduce(function(memo, name, i) {
1373
1373
  var col = i % perLine;
1374
1374
  if (i > 0 && col === 0) memo += '\n';
@@ -3720,8 +3720,6 @@
3720
3720
  }
3721
3721
  var require$1 = f;
3722
3722
 
3723
- // import { createRequire } from "module";
3724
-
3725
3723
  var iconv = require$1('iconv-lite');
3726
3724
 
3727
3725
  // import iconv from 'iconv-lite';
@@ -4289,6 +4287,10 @@
4289
4287
  return layerHasPaths(lyr) || layerHasPoints(lyr);
4290
4288
  }
4291
4289
 
4290
+ function layerIsGeometric(lyr) {
4291
+ return !!lyr.geometry_type; // only checks type, includes empty layers
4292
+ }
4293
+
4292
4294
  function layerHasPaths(lyr) {
4293
4295
  return (lyr.geometry_type == 'polygon' || lyr.geometry_type == 'polyline') &&
4294
4296
  layerHasNonNullShapes(lyr);
@@ -4552,6 +4554,7 @@
4552
4554
  getLayerDataTable: getLayerDataTable,
4553
4555
  layerHasNonNullData: layerHasNonNullData,
4554
4556
  layerHasGeometry: layerHasGeometry,
4557
+ layerIsGeometric: layerIsGeometric,
4555
4558
  layerHasPaths: layerHasPaths,
4556
4559
  layerHasPoints: layerHasPoints,
4557
4560
  layerIsRectangle: layerIsRectangle,
@@ -5493,6 +5496,8 @@
5493
5496
  initLegacyArcs(arguments[0]); // want to phase this out
5494
5497
  } else if (arguments.length == 3) {
5495
5498
  initXYData.apply(this, arguments);
5499
+ } else if (arguments.length === 0) {
5500
+ initLegacyArcs([]); // empty collection
5496
5501
  } else {
5497
5502
  error("ArcCollection() Invalid arguments");
5498
5503
  }
@@ -13184,15 +13189,11 @@
13184
13189
  return findVertexIds(p2.x, p2.y, arcs);
13185
13190
  }
13186
13191
 
13187
-
13188
- function snapVerticesToPoint(ids, p, arcs, final) {
13192
+ function snapVerticesToPoint(ids, p, arcs) {
13189
13193
  var data = arcs.getVertexData();
13190
13194
  ids.forEach(function(idx) {
13191
- if (final) {
13192
- // recalculate bounding box for arc
13193
- arcs.updateArcBounds(findArcIdFromVertexId(idx, data.ii));
13194
- }
13195
13195
  setVertexCoords(p[0], p[1], idx, arcs);
13196
+ arcs.updateArcBounds(findArcIdFromVertexId(idx, data.ii));
13196
13197
  });
13197
13198
  }
13198
13199
 
@@ -19955,8 +19956,8 @@
19955
19956
  }
19956
19957
 
19957
19958
  function parseScalebarUnits(str) {
19958
- var isMiles = /miles?$/.test(str.toLowerCase());
19959
- var isKm = /(k\.m\.|km|kilometers?|kilometres?)$/.test(str.toLowerCase());
19959
+ var isMiles = /(miles?|mi[.]?|英里)$/.test(str.toLowerCase());
19960
+ var isKm = /(k\.m\.|km|kilometers?|kilom.tres?|公里)$/.test(str.toLowerCase());
19960
19961
  var units = isMiles && 'mile' || isKm && 'km' || '';
19961
19962
  return units;
19962
19963
  }
@@ -23046,28 +23047,30 @@ ${svg}
23046
23047
  // @samples Array of buffers containing sample text fields
23047
23048
  // TODO: Improve reliability and number of detectable encodings.
23048
23049
  function detectEncoding(samples) {
23049
- var encoding = null;
23050
- var utf8 = looksLikeUtf8(samples);
23051
- var win1252 = looksLikeWin1252(samples);
23052
- if (utf8 == 2 || utf8 > win1252) {
23053
- encoding = 'utf8';
23054
- } else if (win1252 > 0) {
23055
- encoding = 'win1252';
23056
- } else {
23057
- encoding = 'latin1'; // the original Shapefile encoding, using as an (imperfect) fallback
23058
- }
23059
-
23060
- return {
23061
- encoding: encoding,
23062
- confidence: Math.max(utf8, win1252)
23063
- };
23050
+ // score each encoding as 2 (high confidence) 1 (low confidence) or 0 (fail)
23051
+ var candidates = [{
23052
+ // latin1 is the original Shapefile encoding, using as an imperfect fallback
23053
+ // (sorts to the top only if all other encodings score 0)
23054
+ encoding: 'latin1',
23055
+ confidence: 0
23056
+ },{
23057
+ encoding: 'win1252',
23058
+ confidence: looksLikeWin1252(samples)
23059
+ }, {
23060
+ encoding: 'utf8',
23061
+ confidence: looksLikeUtf8(samples)
23062
+ }, {
23063
+ encoding: 'gb18030',
23064
+ confidence: looksLikeGB18030(samples)
23065
+ }];
23066
+ utils.sortOn(candidates, 'confidence', 'descending');
23067
+ return candidates[0];
23064
23068
  }
23065
23069
 
23066
- // Convert an array of text samples to a single string using a given encoding
23067
23070
  function decodeSamples(enc, samples) {
23068
23071
  return samples.map(function(buf) {
23069
23072
  return decodeString(buf, enc).trim();
23070
- }).join('\n');
23073
+ });
23071
23074
  }
23072
23075
 
23073
23076
  // Win1252 is the same as Latin1, except it replaces a block of control
@@ -23082,45 +23085,67 @@ ${svg}
23082
23085
  //
23083
23086
  function looksLikeWin1252(samples) {
23084
23087
  //common l.c. ascii chars
23085
- var ascii = 'abcdefghijklmnopqrstuvwxyz0123456789.()\'"?+-\n,:;/|_$% ',
23086
- // common extended + NBS (found in the wild)
23087
- extended = 'ßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿ°–±’‘' + '\xA0',
23088
- str = decodeSamples('win1252', samples),
23089
- asciiScore = getCharScore(str, ascii),
23090
- totalScore = getCharScore(str, extended + ascii);
23091
- return totalScore > 0.98 && asciiScore >= 0.8 && 2 ||
23092
- totalScore > 0.97 && asciiScore >= 0.6 && 1 || 0;
23088
+ var commonAscii = 'abcdefghijklmnopqrstuvwxyz0123456789.()\'"?+-\n,:;/|_$% ',
23089
+ // more common extended chars + NBS (found in the wild)
23090
+ moreChars = 'ßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿ°–±’‘' + '\xA0',
23091
+ str = decodeSamples('win1252', samples).join(''),
23092
+ commonAsciiPct = calcCharPct(str, commonAscii),
23093
+ expandedPct = calcCharPct(str, moreChars) + commonAsciiPct;
23094
+ var high = expandedPct > 0.98 && commonAsciiPct >= 0.8;
23095
+ var low = expandedPct > 0.97 && commonAsciiPct >= 0.6;
23096
+ return getScore(high, low);
23093
23097
  }
23094
23098
 
23095
- // Reject string if it contains the "replacement character" after decoding to UTF-8
23096
23099
  function looksLikeUtf8(samples) {
23097
- // Remove the byte sequence for the utf-8-encoded replacement char before decoding,
23098
- // in case the file is in utf-8, but contains some previously corrupted text.
23099
- // samples = samples.map(internal.replaceUtf8ReplacementChar);
23100
- var str = decodeSamples('utf8', samples);
23101
- var count = (str.match(/\ufffd/g) || []).length;
23102
- var score = 1 - count / str.length;
23103
- return score == 1 && 2 || score > 0.97 && 1 || 0;
23104
- }
23105
-
23106
- // function replaceUtf8ReplacementChar(buf) {
23107
- // var isCopy = false;
23108
- // for (var i=0, n=buf.length; i<n; i++) {
23109
- // // Check for UTF-8 encoded replacement char (0xEF 0xBF 0xBD)
23110
- // if (buf[i] == 0xef && i + 2 < n && buf[i+1] == 0xbf && buf[i+2] == 0xbd) {
23111
- // if (!isCopy) {
23112
- // buf = utils.createBuffer(buf);
23113
- // isCopy = true;
23114
- // }
23115
- // buf[i] = buf[i+1] = buf[i+2] = 63; // ascii question mark
23116
- // }
23117
- // }
23118
- // return buf;
23119
- // }
23100
+ // Reject string if it contains the "replacement character" after decoding
23101
+ // as utf-8
23102
+ var str = decodeSamples('utf8', samples).join('');
23103
+ var invalidPct = getInvalidPct(str);
23104
+ var high = invalidPct == 0;
23105
+ var low = invalidPct < 0.03;
23106
+ return getScore(high, low);
23107
+ }
23108
+
23109
+ function looksLikeGB18030(samples) {
23110
+ // from Jun Da's frequency table
23111
+ var commonHanZi = '的一了是不我他在人有这来个说上你们到地大着子那就也时道中出得为里下她要么去可以过和看之然后会自没小好生天而起对能还事想都心只家面样把国多又于头年手发如什开前当所无知老但见长已军从方声儿回意作话两点现很成身情十用些走经同进动己三行种向日明女正问此学太打间分因给本眼定二气力被门真法外听实其高先几笑再主将山战才口文最部第它西与全白者便相住公使东等边信像斯机光次感神却死理名重四做别叫王并水月果何位怎马常觉海张少处亲安特美呢色原直望命由候吧让应尔难关许车平师民夫书新接吗路利世比放活快总立队更花爱清五内金带工风克任至指往入空德吃表连解教思飞物电受今完林干代告兵加认通找远非性脸体轻记目令变似反南场跟必石拉士报李火且满该孩字红象即结言员房件万条提写或坐北早失离步陈乎请转近切黑深城办倒各父传音站官半男击合阿英决怕杀未形及算青黄落刚百论谁突交团度义罗始强紧敌八母钱极片化流管惊每题晚虽政兴答司妈夜越啊奇达谈武友数领朝保服曾拿则哪格尽根急语容喜求衣留双影刻制随冷九苦量备布照周故准客船江系姐争功怪星断句龙竟视界讲取古六静底精七河久绝阳识哈台确息期整伤忙娘终剑送计愿欢微您沉装敢云脚消若复收千木乐毛华集树弟皇响希诉号巴穿线汉攻呀警派刘酒雷停史阵错建足显丽另包势破亮首志观病热跑业治田冲运约暗待共院仍区害元哥围屋胡产室调类细议爷注易务众帝市摇乱密姑斗除式示睛楼造朋社持慢般皮京况块忽脑校甚查土怀福单联赶背统喝疑支血饭灵够章群威举兰游器察嘴痛铁掉宝历改推枪念参术帮党据品须居称旁退梦科岁低严引吉睡爸呼追局露维苏证村挥独节谢香亚波角案读图左掌假跳究楚余鬼钟座礼展玉肯既止守广考恩异料段尼画续米草胜存唐医程弹烟商顾招宗堂野初府激雨尚渐诗顿伯孙际沙雪板闻导致护春态基设耳简婚幸味右买演权卡继依恶庄炮亦虎州刀球需兄闪笔否烈玩啦逃排仅弄具散默景顶郑洋丝卫速侠差贵君习妇助恐救湖莫窗险顺封佛委旧印伙妹副宫洞永罪松责组防艺营班试鲁宋靠索灯介翻喊纪秘妻纸银略充戏担某杨射魔遇鱼陆级坏忘乡鲜哭费抓叶醒族纳床咱桌境列午振抱专毫店街怒托剧置秋藏赵划普岛较承脱革忍伸份免齐抗猛园临犯食架选歌按败良隐养属洛朱狂修坚压寻旅谋温探资端投泪阴换药麻施丈冰雄著绿职负短模荣遗农叹川毒吴蒋卖范禁杂富秀县祖梅谷凡刺登蓝奶缓姓牛价规篇劳质婆仙馆摆舞层狗占墙善熟验肉臣状呆圣懂袋唱值迷替归巨讨毕批镇吸森拍灭握伊杰勒卷偷奔省谓危付伦休厅预迎罢恨博亡欲悲宣标闹岸';
23112
+ var str = decodeSamples('gb18030', samples).join('');
23113
+ // Almost all the common Unicode Hanzi are in this range (along with many more uncommon ones)
23114
+ var chineseStr = str.replace(/[^\u4e00-\u9fa5]/g, '');
23115
+ var chinesePct = chineseStr.length / str.length;
23116
+ var commonAsciiStr = extractCommonAsciiChars(str);
23117
+ var commonAsciiPct = commonAsciiStr.length / str.length;
23118
+ // Some encodings get converted almost completely into valid (but mostly
23119
+ // uncommon) Chinese characters by the gb18030 converter.
23120
+ // To guard against this, we're requiring that a certain percentage of
23121
+ // characters be on a list of the most common characters.
23122
+ var commonHanZiPct = calcCharPct(chineseStr, commonHanZi);
23123
+ // check for non-convertible characters
23124
+ var invalidPct = getInvalidPct(str);
23125
+ var high = chinesePct > 0.5 && (chinesePct + commonAsciiPct) > 0.9 &&
23126
+ invalidPct === 0 && commonHanZiPct > 0.25;
23127
+ var low = chinesePct > 0.3 && (chinesePct + commonAsciiPct) > 0.8 &&
23128
+ commonHanZiPct > 0.15;
23129
+ return getScore(high, low);
23130
+ }
23131
+
23132
+ function getScore(high, low) {
23133
+ return high && 2 || low && 1 || 0;
23134
+ }
23135
+
23136
+ function getInvalidPct(str) {
23137
+ // count occurences of the "replacement" character
23138
+ var invalidCount = (str.match(/\ufffd/g) || []).length;
23139
+ return invalidCount / str.length;
23140
+ }
23141
+
23142
+ function extractCommonAsciiChars(str) {
23143
+ return str.replace(/[^a-zA-Z0-9.()'"?+\n,:;/|_$% -]/g, '');
23144
+ }
23120
23145
 
23121
23146
  // Calc percentage of chars in a string that are present in a second string
23122
23147
  // @chars String of chars to look for in @str
23123
- function getCharScore(str, chars) {
23148
+ function calcCharPct(str, chars) {
23124
23149
  var index = {},
23125
23150
  count = 0;
23126
23151
  str = str.toLowerCase();
@@ -23130,9 +23155,16 @@ ${svg}
23130
23155
  for (i=0, n=str.length; i<n; i++) {
23131
23156
  count += index[str[i]] || 0;
23132
23157
  }
23133
- return count / str.length;
23158
+ return count / str.length || 0;
23134
23159
  }
23135
23160
 
23161
+ var EncodingDetection = /*#__PURE__*/Object.freeze({
23162
+ __proto__: null,
23163
+ detectEncodingFromBOM: detectEncodingFromBOM,
23164
+ detectEncoding: detectEncoding,
23165
+ decodeSamples: decodeSamples
23166
+ });
23167
+
23136
23168
  // Convert a string containing delimited text data into a dataset object
23137
23169
  function importDelim(str, opts) {
23138
23170
  return importDelim2({content: str}, opts);
@@ -26644,25 +26676,19 @@ ${svg}
26644
26676
  var info = detectEncoding(samples);
26645
26677
  encoding = info.encoding;
26646
26678
  if (info.confidence < 2) {
26647
- msg = 'Warning: Unable to auto-detect the text encoding of a DBF file with high confidence.';
26679
+ msg = 'Warning: Unable to auto-detect the DBF file text encoding with high confidence.';
26648
26680
  msg += '\n\nDefaulting to: ' + encoding + (encoding in encodingNames ? ' (' + encodingNames[encoding] + ')' : '');
26649
- msg += '\n\nSample of how non-ascii text was imported:';
26650
- msg += '\n' + formatStringsAsGrid(decodeSamples(encoding, samples).split('\n'));
26651
- msg += decodeSamples(encoding, samples);
26681
+ msg += '\n\nSample of how non-ascii text was imported:\n';
26682
+ if (runningInBrowser()) {
26683
+ msg += '<pre>' + formatStringsAsGrid(decodeSamples(encoding, samples), 50) + '</pre>';
26684
+ } else {
26685
+ msg += formatStringsAsGrid(decodeSamples(encoding, samples));
26686
+ }
26652
26687
  msg += '\n\n' + ENCODING_PROMPT + '\n';
26653
26688
  message(msg);
26654
26689
  }
26655
26690
  }
26656
26691
 
26657
- // Show a sample of decoded text if non-ascii-range text has been found
26658
- // if (encoding && samples.length > 0) {
26659
- // msg = "Detected DBF text encoding: " + encoding + (encoding in encodingNames ? " (" + encodingNames[encoding] + ")" : "");
26660
- // message(msg);
26661
- // msg = decodeSamples(encoding, samples);
26662
- // msg = formatStringsAsGrid(msg.split('\n'));
26663
- // msg = "\nSample text containing non-ascii characters:" + (msg.length > 60 ? '\n' : '') + msg;
26664
- // verbose(msg);
26665
- // }
26666
26692
  return encoding;
26667
26693
  }
26668
26694
 
@@ -37783,7 +37809,7 @@ ${svg}
37783
37809
  filteredLyr = copyLayer(filteredLyr);
37784
37810
  }
37785
37811
 
37786
- if (opts.verbose !== false) {
37812
+ if (opts.verbose !== false && !opts.quiet) {
37787
37813
  message(utils.format('Retained %,d of %,d features', getFeatureCount(filteredLyr), n));
37788
37814
  }
37789
37815
 
@@ -37833,14 +37859,15 @@ ${svg}
37833
37859
  }
37834
37860
 
37835
37861
  function combineFilters(a, b) {
37836
- return (a && b && function(id) {
37862
+ return a && b ? function(id) {
37837
37863
  return a(id) && b(id);
37838
- }) || a || b;
37864
+ } : (a || b);
37839
37865
  }
37840
37866
 
37841
- cmd.evaluateEachFeature = function(lyr, dataset, exp, opts) {
37867
+ cmd.evaluateEachFeature = function(lyr, dataset, expArg, opts) {
37842
37868
  var n = getFeatureCount(lyr),
37843
37869
  arcs = dataset.arcs,
37870
+ exp = expArg || '',
37844
37871
  compiled, filter;
37845
37872
 
37846
37873
  var exprOpts = {
@@ -42377,6 +42404,9 @@ ${svg}
42377
42404
  candidates.forEach(function(candId) {
42378
42405
  var hit;
42379
42406
  if (candId == absId) return; // ignore self-intersections
42407
+ if (absArcId(candId) >= arcs.size()) {
42408
+ return;
42409
+ }
42380
42410
  hit = geom.getPointToPathInfo(endpoint.point[0], endpoint.point[1], [candId], arcs);
42381
42411
  if (hit && hit.distance <= maxGapLen && (!target || hit.distance < target.distance)) {
42382
42412
  target = hit;
@@ -42462,7 +42492,9 @@ ${svg}
42462
42492
  // if (opts.gap_tolerance) {
42463
42493
  //opts = utils.defaults({snap_interval: opts.gap_tolerance * 0.1}, opts);
42464
42494
  // }
42465
- addIntersectionCuts(dataset, opts);
42495
+ if (!opts.no_cuts) {
42496
+ addIntersectionCuts(dataset, opts);
42497
+ }
42466
42498
  return layers.map(function(lyr) {
42467
42499
  if (lyr.geometry_type != 'polyline') stop("Expected a polyline layer");
42468
42500
  if (opts.from_rings) {
@@ -42492,7 +42524,12 @@ ${svg}
42492
42524
  }
42493
42525
 
42494
42526
  function createPolygonLayer(lyr, dataset, opts) {
42495
- var nodes = closeUndershoots(lyr, dataset, opts);
42527
+ var nodes;
42528
+ if (opts.no_cuts) {
42529
+ nodes = new NodeCollection(dataset.arcs);
42530
+ } else {
42531
+ nodes = closeUndershoots(lyr, dataset, opts);
42532
+ }
42496
42533
  // ignore arcs that don't belong to this layer
42497
42534
  nodes.setArcFilter(getArcPresenceTest(lyr.shapes, nodes.arcs));
42498
42535
  var data = buildPolygonMosaic(nodes);
@@ -45485,7 +45522,7 @@ ${svg}
45485
45522
  });
45486
45523
  }
45487
45524
 
45488
- var version = "0.6.74";
45525
+ var version = "0.6.76";
45489
45526
 
45490
45527
  // Parse command line args into commands and run them
45491
45528
  // Function takes an optional Node-style callback. A Promise is returned if no callback is given.
@@ -46162,6 +46199,7 @@ ${svg}
46162
46199
  DelimExport,
46163
46200
  DelimImport,
46164
46201
  DelimReader,
46202
+ EncodingDetection,
46165
46203
  Encodings,
46166
46204
  Explode,
46167
46205
  Export,
package/www/page.css CHANGED
@@ -40,6 +40,20 @@ body {
40
40
  cursor: default;
41
41
  }
42
42
 
43
+ .fade-out {
44
+ animation: fadeOut ease forwards 0.6s;
45
+ }
46
+
47
+ @keyframes fadeOut {
48
+ 0% {
49
+ opacity: 1;
50
+ }
51
+ 100% {
52
+ opacity: 0;
53
+ }
54
+ }
55
+
56
+
43
57
  .selectable,.selectable * {
44
58
  user-select: default;
45
59
  -webkit-user-select: text;
@@ -51,12 +65,14 @@ body {
51
65
  /* --- Themed elements -------------- */
52
66
 
53
67
  .page-header,
54
- .dialog-btn {
68
+ .dialog-btn,
69
+ .sidebar-btn {
55
70
  background-color: #1385B7;
56
71
  }
57
72
 
58
73
  .colored-text,
59
74
  .save-menu-link,
75
+ .context-menu-item,
60
76
  .save-menu-btn,
61
77
  .add-field-btn,
62
78
  .nav-menu-item,
@@ -98,6 +114,7 @@ body {
98
114
  }
99
115
 
100
116
  .dialog-btn:hover:not(.disabled),
117
+ .sidebar-btn:hover,
101
118
  .btn.header-btn:hover,
102
119
  .dialog-btn.default-btn,
103
120
  .dialog-btn.selected-btn {
@@ -214,17 +231,18 @@ body {
214
231
  pointer-events: none;
215
232
  }
216
233
 
217
- .box-tool-options .btn {
234
+ .box-tool-options .btn,
235
+ .selection-tool-options .btn {
218
236
  pointer-events: initial;
219
237
  }
220
238
 
221
- .box-tool-options .info-box {
222
- text-align: center;
223
- }
224
-
225
239
  .box-coords {
226
- margin-top: 7px;
240
+ margin-top: -23px;
227
241
  pointer-events: initial;
242
+ position: absolute;
243
+ z-index: -1;
244
+ padding: 1px 25px;
245
+ right: 55px;
228
246
  }
229
247
 
230
248
  /* --- Export dialog --------- */
@@ -528,13 +546,19 @@ body.dragover #import-options-drop-area .drop-area {
528
546
  text-align: center;
529
547
  }
530
548
 
531
- .info-box,.popup {
549
+ .info-box,.popup,.contextmenu {
532
550
  border-radius: 9px;
533
- /* border: 1px solid #ddd; */
551
+ border: 1px solid #ddd;
534
552
  box-shadow: 0 3px 6px rgba(0,0,0,0.35);
553
+ box-shadow: 0 1px 7px rgba(0,0,0,0.15);
535
554
  background-color: #fff;
536
555
  }
537
556
 
557
+ .contextmenu-item {
558
+ padding: 6px;
559
+ }
560
+
561
+
538
562
  .info-box {
539
563
  min-width: 230px;
540
564
  word-wrap: break-word;
@@ -547,6 +571,25 @@ body.dragover #import-options-drop-area .drop-area {
547
571
  /* border: 1px solid #aaa; */
548
572
  }
549
573
 
574
+ .sidebar-buttons {
575
+ display: none;
576
+ position: absolute;
577
+ background-color: white;
578
+ padding: 1px 3px;
579
+ top: 207px;
580
+ right: 0;
581
+ z-index: 19;
582
+ }
583
+
584
+ .btn.sidebar-btn {
585
+ display: block;
586
+ margin-bottom: 2px;
587
+ margin-top: 2px;
588
+ font-size: 13px;
589
+ color: white;
590
+ min-width: 28px;
591
+ }
592
+
550
593
  .info-box h3 {
551
594
  font-size: 19px;
552
595
  line-height: 1.1;
@@ -773,7 +816,7 @@ body.simplify .layer-control-btn {
773
816
  max-height: 500px;
774
817
  overflow: hidden;
775
818
  overflow-y: auto;
776
- padding: 9px 14px 6px 14px;
819
+ padding: 8px 14px 9px 14px;
777
820
  pointer-events: auto;
778
821
  border-radius: 9px;
779
822
  }
@@ -1000,6 +1043,14 @@ img.close-btn:hover,
1000
1043
  visibility: hidden;
1001
1044
  }*/
1002
1045
 
1046
+
1047
+ .contextmenu {
1048
+ font-size: 13px;
1049
+ position: absolute;
1050
+ z-index: 40;
1051
+ padding: 5px 0;
1052
+ }
1053
+
1003
1054
  /* --- Popup -------------------- */
1004
1055
 
1005
1056
  .popup {
@@ -1206,6 +1257,10 @@ div.basemap-style-btn.active img {
1206
1257
  cursor: crosshair;
1207
1258
  }
1208
1259
 
1260
+ .map-layers.drawing.dragging {
1261
+ cursor: default;
1262
+ }
1263
+
1209
1264
  .map-layers canvas {
1210
1265
  pointer-events: none;
1211
1266
  position: absolute;
@@ -1235,11 +1290,19 @@ div.basemap-style-btn.active img {
1235
1290
  cursor: pointer;
1236
1291
  }
1237
1292
 
1293
+ .map-layers > svg text.active-label {
1294
+ stroke: #fac0ff; /* #efacf4; */
1295
+ paint-order: stroke fill;
1296
+ stroke-width: 4px;
1297
+ stroke-linecap: round;
1298
+ stroke-linejoin: round;
1299
+ }
1300
+
1238
1301
  /* --- MAP BUTTONS --- */
1239
1302
 
1240
- .pointer-btn {
1303
+ /*.pointer-btn {
1241
1304
  z-index: 2;
1242
- }
1305
+ }*/
1243
1306
 
1244
1307
  .nav-buttons {
1245
1308
  z-index: 20;
@@ -1269,9 +1332,6 @@ div.basemap-style-btn.active img {
1269
1332
  fill: black !important;
1270
1333
  }
1271
1334
 
1272
- .save-btn .save-menu {
1273
- top: 23px;
1274
- }
1275
1335
 
1276
1336
  .inline-checkbox {
1277
1337
  margin-left: 5px;
@@ -1283,13 +1343,23 @@ div.basemap-style-btn.active img {
1283
1343
 
1284
1344
  .nav-sub-menu {
1285
1345
  position: absolute;
1286
- z-index: -1;
1346
+ z-index: -1;
1287
1347
  display: none;
1288
1348
  pointer-events: none;
1289
- padding-top: 4px;
1290
- top: 27px;
1291
- right: -3px;
1349
+ padding: 5px 0px;
1350
+ background-color: white;
1351
+ top: 0px;
1352
+ right: 24px;
1353
+ text-align: right;
1292
1354
  white-space: nowrap;
1355
+ border-radius: 6px;
1356
+ border: 1px solid #ddd;
1357
+ box-shadow: 0 2px 5px rgba(0,0,0,0.35);
1358
+ box-shadow: 0 1px 7px rgba(0,0,0,0.12);
1359
+ }
1360
+
1361
+ .pointer-btn .nav-sub-menu {
1362
+ top: -3px;
1293
1363
  }
1294
1364
 
1295
1365
  .nav-btn.open .nav-sub-menu {
@@ -1297,33 +1367,6 @@ div.basemap-style-btn.active img {
1297
1367
  pointer-events: inherit;
1298
1368
  }
1299
1369
 
1300
- .nav-menu-item {
1301
- background-color: #fff;
1302
- float: right;
1303
- clear: right;
1304
- white-space: nowrap;
1305
- display: inline-block;
1306
- padding: 5px 7px 5px 7px;
1307
- line-height: 11px;
1308
- cursor: pointer;
1309
- }
1310
-
1311
-
1312
- .nav-menu-item:hover,
1313
- .nav-btn:hover .nav-sub-menu:not(.active):not(:hover) .nav-menu-item[data-name=info] {
1314
- font-weight: bold;
1315
- background: #e6f7ff;
1316
- }
1317
-
1318
- .nav-menu-item.selected {
1319
- color: black;
1320
- font-weight: bold;
1321
- }
1322
-
1323
- /* bullets https://www.w3schools.com/charsets/ref_utf_geometric.asp */
1324
- .nav-sub-menu.active .nav-menu-item.selected:before {
1325
- content: "\25B8 "
1326
- }
1327
1370
 
1328
1371
  .nav-btn {
1329
1372
  position: relative;
@@ -1339,7 +1382,6 @@ div.basemap-style-btn.active img {
1339
1382
 
1340
1383
  .nav-btn.selected {
1341
1384
  background-color: black;
1342
- /* border-radius: 3px; */
1343
1385
  }
1344
1386
 
1345
1387
  .nav-btn:hover:not(.disabled) svg *,
@@ -1351,16 +1393,43 @@ div.basemap-style-btn.active img {
1351
1393
  fill: white;
1352
1394
  }
1353
1395
 
1396
+ .nav-menu-item,
1397
+ .contextmenu-item {
1398
+ background-color: #fff;
1399
+ white-space: nowrap;
1400
+ padding: 6px 11px 7px 11px;
1401
+ line-height: 11px;
1402
+ cursor: pointer;
1403
+ }
1404
+
1405
+ .nav-menu-item:hover,
1406
+ .contextmenu-item:hover,
1407
+ .nav-btn:hover .nav-sub-menu:not(.active):not(:hover) .nav-menu-item[data-name=info] {
1408
+ color: black;
1409
+ background: #e6f7ff;
1410
+ }
1411
+
1412
+ .nav-menu-item.selected {
1413
+ color: black;
1414
+ }
1415
+
1416
+ /* bullets https://www.w3schools.com/charsets/ref_utf_geometric.asp */
1417
+ .nav-sub-menu.active .nav-menu-item.selected:before {
1418
+ content: "\25B8";
1419
+ position: relative;
1420
+ margin-left: -7px;
1421
+ left: -2px;
1422
+ top: 1px;
1423
+ }
1424
+
1354
1425
  .save-menu {
1355
1426
  text-align: right;
1356
1427
  padding-bottom: 5px;
1357
1428
  }
1358
1429
 
1359
1430
  .save-menu-entry {
1360
- /* padding: 4px 7px 5px 7px; */
1361
1431
  line-height: 11px;
1362
1432
  padding: 4px 7px 5px 7px;
1363
- display: inline-block;
1364
1433
  background: white;
1365
1434
  }
1366
1435
 
@@ -1396,8 +1465,7 @@ div.basemap-style-btn.active img {
1396
1465
 
1397
1466
 
1398
1467
  .save-menu-link:hover {
1399
- /* background: #e6f7ff; */
1400
- font-weight: bold;
1468
+ color: black;
1401
1469
  }
1402
1470
 
1403
1471
  .save-item-label {