mapshaper 0.6.111 → 0.6.113
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 +1124 -630
- package/package.json +3 -2
- package/www/basemap.js +6 -4
- package/www/elements.css +1 -1
- package/www/images/eye3.png +0 -0
- package/www/index.html +27 -8
- package/www/mapshaper-gui.js +276 -62
- package/www/mapshaper.js +1124 -630
- package/www/modules.js +147 -0
- package/www/page.css +71 -34
package/www/mapshaper-gui.js
CHANGED
|
@@ -655,9 +655,14 @@
|
|
|
655
655
|
},
|
|
656
656
|
|
|
657
657
|
show: function(css) {
|
|
658
|
-
var tag = this.el && this.el.tagName;
|
|
658
|
+
// var tag = this.el && this.el.tagName;
|
|
659
659
|
if (!this.visible()) {
|
|
660
|
-
|
|
660
|
+
// don't assume 'display:block'
|
|
661
|
+
this.el?.style.removeProperty('display');
|
|
662
|
+
if (this.computedStyle().display == 'none') {
|
|
663
|
+
this.css('display', 'block');
|
|
664
|
+
}
|
|
665
|
+
// this.css('display', tag == 'SPAN' ? 'inline-block' : 'block');
|
|
661
666
|
this._hidden = false;
|
|
662
667
|
}
|
|
663
668
|
return this;
|
|
@@ -666,13 +671,15 @@
|
|
|
666
671
|
html: function(html) {
|
|
667
672
|
if (arguments.length == 0) {
|
|
668
673
|
return this.el.innerHTML;
|
|
669
|
-
} else {
|
|
670
|
-
this.el.innerHTML = html;
|
|
671
|
-
return this;
|
|
672
674
|
}
|
|
675
|
+
this.el.innerHTML = html;
|
|
676
|
+
return this;
|
|
673
677
|
},
|
|
674
678
|
|
|
675
679
|
text: function(str) {
|
|
680
|
+
if (arguments.length == 0) {
|
|
681
|
+
return this.el.innerText;
|
|
682
|
+
}
|
|
676
683
|
this.html(utils$1.htmlEscape(str));
|
|
677
684
|
return this;
|
|
678
685
|
},
|
|
@@ -1936,14 +1943,27 @@
|
|
|
1936
1943
|
.on('drop', ondrop)
|
|
1937
1944
|
.on('paste', onpaste);
|
|
1938
1945
|
area.node().addEventListener('paste', onpaste);
|
|
1946
|
+
// TODO: use same function for drop and paste
|
|
1939
1947
|
function ondrop(e) {
|
|
1948
|
+
var files = e.dataTransfer.files;
|
|
1949
|
+
var types = e.dataTransfer.types;
|
|
1940
1950
|
block(e);
|
|
1941
|
-
|
|
1951
|
+
if (files.length) {
|
|
1952
|
+
cb(files);
|
|
1953
|
+
} else if (types.includes('text/uri-list')) {
|
|
1954
|
+
cb(e.dataTransfer.getData('text/uri-list').split(','));
|
|
1955
|
+
} else if (types.includes('text/html')) {
|
|
1956
|
+
// drag-dropping a highlighted link may pull in a chunk of html
|
|
1957
|
+
var urls = pastedHtmlToUrls(e.dataTransfer.getData('text/html'));
|
|
1958
|
+
if (urls.length) {
|
|
1959
|
+
cb(urls);
|
|
1960
|
+
}
|
|
1961
|
+
}
|
|
1942
1962
|
}
|
|
1943
1963
|
function onpaste(e) {
|
|
1944
1964
|
var types = Array.from(e.clipboardData.types || []).join(',');
|
|
1945
1965
|
var items = Array.from(e.clipboardData.items || []);
|
|
1946
|
-
var files;
|
|
1966
|
+
var files, str, urls;
|
|
1947
1967
|
if (GUI.textIsSelected()) {
|
|
1948
1968
|
// user is probably pasting text into an editable text field
|
|
1949
1969
|
return;
|
|
@@ -1955,15 +1975,28 @@
|
|
|
1955
1975
|
// Single files of all types are pasted as a string and an image/png
|
|
1956
1976
|
// Multiple files are pasted as a string containing a list of file names
|
|
1957
1977
|
|
|
1958
|
-
// import text from the clipboard (could be csv, json, etc)
|
|
1978
|
+
// import text from the clipboard (could be csv, json, a url, etc)
|
|
1959
1979
|
// formatted text can be available as both text/plain and text/html (e.g.
|
|
1960
1980
|
// a JSON data object copied from a GitHub issue).
|
|
1961
1981
|
//
|
|
1982
|
+
|
|
1983
|
+
// if html is present, it could be data (e.g. from Google Sheets) or a pasted link.
|
|
1984
|
+
// first we check for a link
|
|
1985
|
+
if (types.includes('text/html')) {
|
|
1986
|
+
urls = pastedHtmlToUrls(e.clipboardData.getData('text/html'));
|
|
1987
|
+
if (urls.length) {
|
|
1988
|
+
return cb(urls);
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1962
1991
|
if (types.includes('text/plain')) {
|
|
1963
|
-
// if (types == 'text/plain') {
|
|
1964
1992
|
// text from clipboard (supported by Chrome, FF, Safari)
|
|
1965
1993
|
// TODO: handle FF case of string containing multiple file names.
|
|
1966
|
-
|
|
1994
|
+
str = e.clipboardData.getData('text/plain');
|
|
1995
|
+
urls = pastedTextToUrls(str);
|
|
1996
|
+
if (urls.length) {
|
|
1997
|
+
return cb(urls);
|
|
1998
|
+
}
|
|
1999
|
+
files = [pastedTextToFile(str)];
|
|
1967
2000
|
} else {
|
|
1968
2001
|
files = items.map(function(item) {
|
|
1969
2002
|
return item.kind == 'file' && !item.type.includes('image') ?
|
|
@@ -1983,6 +2016,21 @@
|
|
|
1983
2016
|
}
|
|
1984
2017
|
}
|
|
1985
2018
|
|
|
2019
|
+
function pastedHtmlToUrls(html) {
|
|
2020
|
+
var hrefRegex = /href\s*=\s*["']([^"']+)["']/gi;
|
|
2021
|
+
var matches = html.matchAll(hrefRegex);
|
|
2022
|
+
var urls = Array.from(matches, match => match[1]);
|
|
2023
|
+
return urls;
|
|
2024
|
+
}
|
|
2025
|
+
|
|
2026
|
+
function pastedTextToUrls(str) {
|
|
2027
|
+
if (!looksLikeUrl(str)) return [];
|
|
2028
|
+
var regex = /https?:\/\/[^\s]+?(?=[\s,]|$)/g;
|
|
2029
|
+
var matches = str.matchAll(regex);
|
|
2030
|
+
var urls = Array.from(matches, match => match[0]);
|
|
2031
|
+
return urls;
|
|
2032
|
+
}
|
|
2033
|
+
|
|
1986
2034
|
function pastedTextToFile(str) {
|
|
1987
2035
|
var type = internal.guessInputContentType(str);
|
|
1988
2036
|
var name;
|
|
@@ -1997,6 +2045,10 @@
|
|
|
1997
2045
|
return new File([blob], name);
|
|
1998
2046
|
}
|
|
1999
2047
|
|
|
2048
|
+
function looksLikeUrl(str) {
|
|
2049
|
+
return /^https?:\/\//.test(str);
|
|
2050
|
+
}
|
|
2051
|
+
|
|
2000
2052
|
// @el DOM element for select button
|
|
2001
2053
|
// @cb function(<FileList>)
|
|
2002
2054
|
function FileChooser(el, cb) {
|
|
@@ -2040,7 +2092,7 @@
|
|
|
2040
2092
|
|
|
2041
2093
|
var submitBtn = new SimpleButton('#import-options .submit-btn').on('click', importQueuedFiles);
|
|
2042
2094
|
new SimpleButton('#import-options .cancel-btn').on('click', gui.clearMode);
|
|
2043
|
-
new DropControl(gui, 'body',
|
|
2095
|
+
new DropControl(gui, 'body', receiveDroppedItems);
|
|
2044
2096
|
new FileChooser('#import-options .add-btn', receiveFilesWithOption);
|
|
2045
2097
|
new FileChooser('#add-file-btn', receiveFiles);
|
|
2046
2098
|
new SimpleButton('#add-empty-btn').on('click', function() {
|
|
@@ -2056,7 +2108,7 @@
|
|
|
2056
2108
|
|
|
2057
2109
|
function turnOn() {
|
|
2058
2110
|
if (manifestFiles.length > 0) {
|
|
2059
|
-
downloadFiles(manifestFiles
|
|
2111
|
+
downloadFiles(manifestFiles);
|
|
2060
2112
|
manifestFiles = [];
|
|
2061
2113
|
} else if (model.isEmpty()) {
|
|
2062
2114
|
showImportMenu();
|
|
@@ -2157,6 +2209,14 @@
|
|
|
2157
2209
|
submitBtn.classed('disabled', queuedFiles.length === 0);
|
|
2158
2210
|
}
|
|
2159
2211
|
|
|
2212
|
+
function receiveDroppedItems(arr) {
|
|
2213
|
+
if (utils$1.isString(arr[0])) { // assume array of URLs
|
|
2214
|
+
downloadFiles(arr);
|
|
2215
|
+
} else { // assume array of Files
|
|
2216
|
+
receiveFilesWithOption(arr);
|
|
2217
|
+
}
|
|
2218
|
+
}
|
|
2219
|
+
|
|
2160
2220
|
function receiveFilesWithOption(files) {
|
|
2161
2221
|
var quickView = !El('.advanced-import-options').node().checked;
|
|
2162
2222
|
receiveFiles(files, quickView);
|
|
@@ -2312,9 +2372,8 @@
|
|
|
2312
2372
|
|
|
2313
2373
|
function prepFilesForDownload(names) {
|
|
2314
2374
|
var items = names.map(function(name) {
|
|
2315
|
-
var isUrl = /:\/\//.test(name);
|
|
2316
2375
|
var item = {name: name};
|
|
2317
|
-
if (
|
|
2376
|
+
if (looksLikeUrl(name)) {
|
|
2318
2377
|
item.url = name;
|
|
2319
2378
|
item.basename = GUI.getUrlFilename(name);
|
|
2320
2379
|
|
|
@@ -2667,7 +2726,7 @@
|
|
|
2667
2726
|
var lyr;
|
|
2668
2727
|
if (memo) return memo; // already found a match
|
|
2669
2728
|
// try to match import filename of this dataset
|
|
2670
|
-
if (d.info
|
|
2729
|
+
if (d.info?.input_files?.[0] == src) return d;
|
|
2671
2730
|
// try to match name of a layer in this dataset
|
|
2672
2731
|
lyr = utils$1.find(d.layers, function(lyr) {return lyr.name == src;});
|
|
2673
2732
|
return lyr ? internal.isolateLayer(lyr, d) : null;
|
|
@@ -5068,7 +5127,7 @@
|
|
|
5068
5127
|
var lyr = o.layer;
|
|
5069
5128
|
var opts = {
|
|
5070
5129
|
show_source: layerCount < 5,
|
|
5071
|
-
pinnable: pinnableCount >
|
|
5130
|
+
pinnable: pinnableCount > 0 && isPinnable(lyr)
|
|
5072
5131
|
};
|
|
5073
5132
|
var html, element;
|
|
5074
5133
|
html = renderLayer(lyr, o.dataset, opts);
|
|
@@ -6299,6 +6358,18 @@
|
|
|
6299
6358
|
}
|
|
6300
6359
|
}
|
|
6301
6360
|
|
|
6361
|
+
function time(slug) {
|
|
6362
|
+
if (useDebug()) {
|
|
6363
|
+
console.time(slug);
|
|
6364
|
+
}
|
|
6365
|
+
}
|
|
6366
|
+
|
|
6367
|
+
function timeEnd(slug) {
|
|
6368
|
+
if (useDebug()) {
|
|
6369
|
+
console.timeEnd(slug);
|
|
6370
|
+
}
|
|
6371
|
+
}
|
|
6372
|
+
|
|
6302
6373
|
function printError(err) {
|
|
6303
6374
|
var msg;
|
|
6304
6375
|
if (!LOGGING) return;
|
|
@@ -7462,8 +7533,13 @@
|
|
|
7462
7533
|
if (len >= 2) {
|
|
7463
7534
|
first = str.charAt(0);
|
|
7464
7535
|
last = str.charAt(len-1);
|
|
7465
|
-
if (first == '"' && last == '"' && !str.includes('","') ||
|
|
7466
|
-
|
|
7536
|
+
// if (first == '"' && last == '"' && !str.includes('","') ||
|
|
7537
|
+
// first == "'" && last == "'" && !str.includes("','")) {
|
|
7538
|
+
// don't strip if there are unescaped quotes
|
|
7539
|
+
// e.g. expressions that start and end with quotes
|
|
7540
|
+
// e.g. comma-separated list of quoted values
|
|
7541
|
+
if (first == '"' && last == '"' && !/[^\\]"./.test(str) ||
|
|
7542
|
+
first == "'" && last == "'" && !/[^\\]'./.test(str)) {
|
|
7467
7543
|
str = str.substr(1, len-2);
|
|
7468
7544
|
// remove string escapes
|
|
7469
7545
|
str = str.replace(first == '"' ? /\\(?=")/g : /\\(?=')/g, '');
|
|
@@ -13505,6 +13581,12 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13505
13581
|
});
|
|
13506
13582
|
}
|
|
13507
13583
|
|
|
13584
|
+
var EMPTY_STYLE = {
|
|
13585
|
+
version: 8,
|
|
13586
|
+
sources: {},
|
|
13587
|
+
layers: []
|
|
13588
|
+
};
|
|
13589
|
+
|
|
13508
13590
|
function loadScript(url, cb) {
|
|
13509
13591
|
var script = document.createElement('script');
|
|
13510
13592
|
script.onload = cb;
|
|
@@ -13522,60 +13604,107 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13522
13604
|
}
|
|
13523
13605
|
|
|
13524
13606
|
function Basemap(gui) {
|
|
13525
|
-
var
|
|
13526
|
-
var
|
|
13527
|
-
var
|
|
13528
|
-
var
|
|
13607
|
+
var menuWrapper = gui.container.findChild('.display-options');
|
|
13608
|
+
var mainMenu = gui.container.findChild('.display-main-options');
|
|
13609
|
+
var addLayerMenu = gui.container.findChild('.add-basemap-menu').hide();
|
|
13610
|
+
var basemapList = gui.container.findChild('.added-basemaps');
|
|
13529
13611
|
var overlayButtons = gui.container.findChild('.basemap-overlay-buttons');
|
|
13530
13612
|
var container = gui.container.findChild('.basemap-container');
|
|
13531
13613
|
var basemapNote = gui.container.findChild('.basemap-note');
|
|
13532
|
-
var
|
|
13614
|
+
var addBasemap = gui.container.findChild('.add-basemap');
|
|
13615
|
+
var basemapWarning = gui.container.findChild('.basemap-warning').hide();
|
|
13533
13616
|
var mapEl = gui.container.findChild('.basemap');
|
|
13534
13617
|
var extentNote = El('div').addClass('basemap-prompt').appendTo(container).hide();
|
|
13535
13618
|
var params = window.mapboxParams;
|
|
13536
13619
|
var map;
|
|
13537
13620
|
var activeStyle;
|
|
13538
13621
|
var loading = false;
|
|
13539
|
-
var faded = false;
|
|
13622
|
+
// var faded = false;
|
|
13623
|
+
// var fadeBtn, clearBtn; // not in use
|
|
13624
|
+
var addBtn, addLayerBtn, cancelBtn;
|
|
13625
|
+
var customStyles = [];
|
|
13540
13626
|
|
|
13541
13627
|
if (params) {
|
|
13542
13628
|
// TODO: check page URL for compatibility with mapbox key
|
|
13543
13629
|
init();
|
|
13544
13630
|
} else {
|
|
13545
|
-
|
|
13631
|
+
menuWrapper.findChild('.basemap-opts').hide();
|
|
13546
13632
|
}
|
|
13547
13633
|
|
|
13548
13634
|
function init() {
|
|
13549
13635
|
gui.on('mode', function(e) {
|
|
13550
13636
|
if (e.prev == 'display_options') {
|
|
13551
|
-
|
|
13552
|
-
|
|
13637
|
+
// reset UI when leaving display options mode
|
|
13638
|
+
basemapWarning.hide();
|
|
13639
|
+
basemapNote.hide();
|
|
13640
|
+
// make sure secondary options menu gets closed
|
|
13641
|
+
mainMenu.show();
|
|
13642
|
+
addLayerMenu.hide();
|
|
13553
13643
|
}
|
|
13554
13644
|
if (e.name == 'display_options') {
|
|
13555
13645
|
onUpdate();
|
|
13556
13646
|
}
|
|
13557
13647
|
});
|
|
13558
13648
|
|
|
13559
|
-
|
|
13560
|
-
|
|
13561
|
-
|
|
13562
|
-
|
|
13563
|
-
|
|
13564
|
-
|
|
13649
|
+
customStyles = GUI.getSavedValue('custom_basemaps') || [];
|
|
13650
|
+
updateBasemapList();
|
|
13651
|
+
|
|
13652
|
+
addBtn = new SimpleButton(menuWrapper.findChild('.add-btn'));
|
|
13653
|
+
addBtn.on('click', function(e) {
|
|
13654
|
+
addLayerMenu.show();
|
|
13655
|
+
mainMenu.hide();
|
|
13565
13656
|
});
|
|
13566
13657
|
|
|
13567
|
-
|
|
13568
|
-
|
|
13569
|
-
|
|
13570
|
-
|
|
13571
|
-
|
|
13572
|
-
|
|
13573
|
-
|
|
13574
|
-
|
|
13575
|
-
|
|
13576
|
-
|
|
13658
|
+
addLayerBtn = new SimpleButton(menuWrapper.findChild('.add-layer-btn'));
|
|
13659
|
+
addLayerBtn.on('click', function(e) {
|
|
13660
|
+
var name = menuWrapper.findChild('.add-layer-name').el.value || 'Custom layer';
|
|
13661
|
+
var mapboxUrl = menuWrapper.findChild('.add-mapbox-url').el.value;
|
|
13662
|
+
var mapboxKey = menuWrapper.findChild('.add-mapbox-key')?.el?.value;
|
|
13663
|
+
var templateUrl = menuWrapper.findChild('.add-template-url').el.value;
|
|
13664
|
+
var style = {name};
|
|
13665
|
+
|
|
13666
|
+
if (mapboxUrl) {
|
|
13667
|
+
style.url = mapboxUrl;
|
|
13668
|
+
style.key = mapboxKey; // may be undefined
|
|
13669
|
+
style.type = 'mapbox';
|
|
13670
|
+
} else if (templateUrl) {
|
|
13671
|
+
style.url = templateUrl;
|
|
13672
|
+
style.type = menuWrapper.findChild('.tms').el.checked ? 'tms' : 'xyz';
|
|
13673
|
+
}
|
|
13674
|
+
|
|
13675
|
+
customStyles.push(style);
|
|
13676
|
+
updateBasemapList();
|
|
13677
|
+
showBasemap(style);
|
|
13678
|
+
addLayerMenu.hide();
|
|
13679
|
+
mainMenu.show();
|
|
13577
13680
|
});
|
|
13578
13681
|
|
|
13682
|
+
cancelBtn = new SimpleButton(menuWrapper.findChild('.add-cancel-btn'));
|
|
13683
|
+
cancelBtn.on('click', function() {
|
|
13684
|
+
addLayerMenu.hide();
|
|
13685
|
+
mainMenu.show();
|
|
13686
|
+
});
|
|
13687
|
+
|
|
13688
|
+
// fadeBtn = new SimpleButton(menuWrapper.findChild('.fade-btn'));
|
|
13689
|
+
// clearBtn = new SimpleButton(menuWrapper.findChild('.clear-btn'));
|
|
13690
|
+
// clearBtn.on('click', function() {
|
|
13691
|
+
// if (activeStyle) {
|
|
13692
|
+
// turnOffBasemap();
|
|
13693
|
+
// }
|
|
13694
|
+
// });
|
|
13695
|
+
|
|
13696
|
+
// fadeBtn.on('click', function() {
|
|
13697
|
+
// if (faded) {
|
|
13698
|
+
// mapEl.css('opacity', 1);
|
|
13699
|
+
// faded = false;
|
|
13700
|
+
// fadeBtn.text('Fade');
|
|
13701
|
+
// } else if (activeStyle) {
|
|
13702
|
+
// mapEl.css('opacity', 0.35);
|
|
13703
|
+
// faded = true;
|
|
13704
|
+
// fadeBtn.text('Unfade');
|
|
13705
|
+
// }
|
|
13706
|
+
// });
|
|
13707
|
+
|
|
13579
13708
|
gui.model.on('update', onUpdate);
|
|
13580
13709
|
|
|
13581
13710
|
gui.on('map_click', function() {
|
|
@@ -13584,10 +13713,10 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13584
13713
|
});
|
|
13585
13714
|
|
|
13586
13715
|
params.styles.forEach(function(style) {
|
|
13587
|
-
El('div')
|
|
13588
|
-
.html(`<div class="basemap-style-btn"><img src="${style.icon}"></img></div><div class="basemap-style-label">${style.name}</div>`)
|
|
13589
|
-
.appendTo(menuButtons)
|
|
13590
|
-
.findChild('.basemap-style-btn').on('click', onClick);
|
|
13716
|
+
// El('div')
|
|
13717
|
+
// .html(`<div class="basemap-style-btn"><img src="${style.icon}"></img></div><div class="basemap-style-label">${style.name}</div>`)
|
|
13718
|
+
// .appendTo(menuButtons)
|
|
13719
|
+
// .findChild('.basemap-style-btn').on('click', onClick);
|
|
13591
13720
|
|
|
13592
13721
|
El('div').addClass('basemap-overlay-btn basemap-style-btn')
|
|
13593
13722
|
.html(`<img src="${style.icon}"></img>`).on('click', onClick)
|
|
@@ -13601,7 +13730,6 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13601
13730
|
showBasemap(style);
|
|
13602
13731
|
}
|
|
13603
13732
|
updateButtons();
|
|
13604
|
-
// closeMenu();
|
|
13605
13733
|
}
|
|
13606
13734
|
});
|
|
13607
13735
|
}
|
|
@@ -13616,7 +13744,6 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13616
13744
|
function turnOffBasemap() {
|
|
13617
13745
|
activeStyle = null;
|
|
13618
13746
|
gui.map.setDisplayCRS(null);
|
|
13619
|
-
refresh();
|
|
13620
13747
|
}
|
|
13621
13748
|
|
|
13622
13749
|
function showBasemap(style) {
|
|
@@ -13625,20 +13752,98 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13625
13752
|
// Make sure that the selected layer style gets updated in gui-map.js
|
|
13626
13753
|
// gui.state.dark_basemap = style && style.dark || false;
|
|
13627
13754
|
if (map) {
|
|
13628
|
-
|
|
13755
|
+
setStyle(activeStyle);
|
|
13629
13756
|
refresh();
|
|
13630
13757
|
} else if (prepareMapView()) {
|
|
13631
13758
|
initMap();
|
|
13632
13759
|
}
|
|
13633
13760
|
}
|
|
13634
13761
|
|
|
13635
|
-
function
|
|
13636
|
-
|
|
13637
|
-
|
|
13762
|
+
function updateBasemapList() {
|
|
13763
|
+
var styles = params.styles.concat(customStyles);
|
|
13764
|
+
basemapList.empty();
|
|
13765
|
+
styles.forEach(function(style) {
|
|
13766
|
+
renderBasemapListItem(basemapList, style);
|
|
13767
|
+
});
|
|
13768
|
+
updateButtons();
|
|
13769
|
+
GUI.setSavedValue('custom_basemaps', customStyles);
|
|
13770
|
+
}
|
|
13771
|
+
|
|
13772
|
+
function isActiveStyle(style) {
|
|
13773
|
+
return style.url == activeStyle?.url;
|
|
13774
|
+
}
|
|
13775
|
+
|
|
13776
|
+
function renderBasemapListItem(parent, style) {
|
|
13777
|
+
var isCustomStyle = !!style.type;
|
|
13778
|
+
var el = El('div').html(`<div data-slug="${getStyleId(style)}" class="basemap-list-item"><img class="on-icon" src="images/eye3.png"><img class="off-icon" src="images/eye.png"> ${style.name} ${isCustomStyle ? '<img class="close-btn" draggable="false" src="images/close.png">' : ''}</div>`);
|
|
13779
|
+
el.appendTo(parent);
|
|
13780
|
+
el.findChild('.basemap-list-item').on('click', function() {
|
|
13781
|
+
if (isActiveStyle(style)) {
|
|
13782
|
+
turnOffBasemap();
|
|
13783
|
+
} else {
|
|
13784
|
+
showBasemap(style);
|
|
13785
|
+
}
|
|
13786
|
+
});
|
|
13787
|
+
|
|
13788
|
+
var closeBtn = el.findChild('.close-btn');
|
|
13789
|
+
closeBtn?.on('click', function(e) {
|
|
13790
|
+
e.stopPropagation();
|
|
13791
|
+
customStyles = customStyles.filter(function(o) {
|
|
13792
|
+
return o.url != style.url;
|
|
13793
|
+
});
|
|
13794
|
+
updateBasemapList();
|
|
13795
|
+
if (isActiveStyle(style)) {
|
|
13796
|
+
turnOffBasemap();
|
|
13797
|
+
}
|
|
13638
13798
|
});
|
|
13799
|
+
el.appendTo(parent);
|
|
13800
|
+
}
|
|
13801
|
+
|
|
13802
|
+
function getStyleId(style) {
|
|
13803
|
+
return ((style.name || '') + style.url).replace(/[^a-z0-9_]+/ig, '_');
|
|
13804
|
+
}
|
|
13805
|
+
|
|
13806
|
+
function setStyle(style) {
|
|
13807
|
+
// update mapbox access token (user-defined styles may have a different key)
|
|
13808
|
+
window.mapboxgl.accessToken = style.key || (window.location.hostname == 'localhost' ?
|
|
13809
|
+
params.localhost_key : params.production_key) || params.key;
|
|
13810
|
+
|
|
13811
|
+
if (style.type == 'mapbox' || !style.type) {
|
|
13812
|
+
map.setStyle(style.url);
|
|
13813
|
+
} else if (style.type == 'xyz' || style.type == 'tms') {
|
|
13814
|
+
map.setStyle({
|
|
13815
|
+
'version': 8,
|
|
13816
|
+
'sources': {
|
|
13817
|
+
'raster-tiles': {
|
|
13818
|
+
'type': 'raster',
|
|
13819
|
+
'tiles': [style.url],
|
|
13820
|
+
'scheme': style.type, // xyz or tms
|
|
13821
|
+
'tileSize': 256, // style.url.includes('@2x') ? 512 : 256
|
|
13822
|
+
}
|
|
13823
|
+
},
|
|
13824
|
+
'layers': [
|
|
13825
|
+
{
|
|
13826
|
+
'id': getStyleId(style),
|
|
13827
|
+
'type': 'raster',
|
|
13828
|
+
'source': 'raster-tiles',
|
|
13829
|
+
'minzoom': 0
|
|
13830
|
+
// 'maxzoom': 22
|
|
13831
|
+
}
|
|
13832
|
+
]
|
|
13833
|
+
});
|
|
13834
|
+
} else {
|
|
13835
|
+
error$1('unsupported map style:', style);
|
|
13836
|
+
}
|
|
13837
|
+
}
|
|
13838
|
+
|
|
13839
|
+
function updateButtons() {
|
|
13639
13840
|
overlayButtons.findChildren('.basemap-style-btn').forEach(function(el, i) {
|
|
13640
13841
|
el.classed('active', params.styles[i] == activeStyle);
|
|
13641
13842
|
});
|
|
13843
|
+
|
|
13844
|
+
menuWrapper.findChildren('.basemap-list-item').forEach(function(el, i) {
|
|
13845
|
+
el.classed('active', el.node().getAttribute('data-slug') == (activeStyle ? getStyleId(activeStyle) : ''));
|
|
13846
|
+
});
|
|
13642
13847
|
}
|
|
13643
13848
|
|
|
13644
13849
|
function onUpdate() {
|
|
@@ -13646,16 +13851,18 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13646
13851
|
var info = getDatasetCrsInfo(activeLyr?.dataset); // defaults to wgs84
|
|
13647
13852
|
var dataCRS = info.crs || null;
|
|
13648
13853
|
var displayCRS = gui.map.getDisplayCRS();
|
|
13854
|
+
var basemapsNotAvailable = !dataCRS || !displayCRS || !crsIsUsable(displayCRS) || !crsIsUsable(dataCRS);
|
|
13649
13855
|
var warning, note;
|
|
13650
13856
|
|
|
13651
|
-
|
|
13652
|
-
if (!dataCRS || !displayCRS || !crsIsUsable(displayCRS) || !crsIsUsable(dataCRS)) {
|
|
13857
|
+
if (basemapsNotAvailable) {
|
|
13653
13858
|
warning = 'This data is incompatible with the basemaps.';
|
|
13654
|
-
if (!internal.layerHasGeometry(activeLyr.layer)) {
|
|
13859
|
+
if (activeLyr && !internal.layerHasGeometry(activeLyr.layer)) {
|
|
13655
13860
|
warning += ' Reason: layer is missing geographic data';
|
|
13656
13861
|
} else if (!dataCRS) {
|
|
13657
13862
|
warning += ' Reason: unknown projection.';
|
|
13658
13863
|
}
|
|
13864
|
+
basemapList.hide();
|
|
13865
|
+
addBasemap.hide();
|
|
13659
13866
|
basemapWarning.html(warning).show();
|
|
13660
13867
|
basemapNote.hide();
|
|
13661
13868
|
overlayButtons.addClass('disabled');
|
|
@@ -13665,6 +13872,8 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13665
13872
|
note = `Note: basemaps use the Mercator projection.`;
|
|
13666
13873
|
basemapNote.text(note).show();
|
|
13667
13874
|
overlayButtons.show();
|
|
13875
|
+
basemapList.show();
|
|
13876
|
+
addBasemap.show();
|
|
13668
13877
|
overlayButtons.removeClass('disabled');
|
|
13669
13878
|
}
|
|
13670
13879
|
}
|
|
@@ -13692,17 +13901,17 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13692
13901
|
}
|
|
13693
13902
|
|
|
13694
13903
|
function initMap() {
|
|
13695
|
-
var accessToken = (window.location.hostname == 'localhost' ?
|
|
13696
|
-
|
|
13904
|
+
// var accessToken = (window.location.hostname == 'localhost' ?
|
|
13905
|
+
// params.localhost_key : params.production_key) || params.key;
|
|
13697
13906
|
if (!enabled() || map || loading) return;
|
|
13698
13907
|
loading = true;
|
|
13699
13908
|
loadStylesheet(params.css);
|
|
13700
13909
|
loadScript(params.js, function() {
|
|
13701
13910
|
map = new window.mapboxgl.Map({
|
|
13702
|
-
accessToken: accessToken,
|
|
13703
13911
|
logoPosition: 'bottom-left',
|
|
13704
13912
|
container: mapEl.node(),
|
|
13705
|
-
style: activeStyle.url,
|
|
13913
|
+
// style: activeStyle.url,
|
|
13914
|
+
style: EMPTY_STYLE, // initializing with empty style to support custom styles
|
|
13706
13915
|
bounds: getLonLatBounds(),
|
|
13707
13916
|
doubleClickZoom: false,
|
|
13708
13917
|
dragPan: false,
|
|
@@ -13711,8 +13920,10 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13711
13920
|
interactive: false,
|
|
13712
13921
|
keyboard: false,
|
|
13713
13922
|
maxPitch: 0,
|
|
13923
|
+
projection: 'mercator', // prevent globe view when zoomed out
|
|
13714
13924
|
renderWorldCopies: true // false // false prevents panning off the map
|
|
13715
13925
|
});
|
|
13926
|
+
setStyle(activeStyle);
|
|
13716
13927
|
map.on('load', function() {
|
|
13717
13928
|
loading = false;
|
|
13718
13929
|
refresh();
|
|
@@ -13761,8 +13972,11 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13761
13972
|
function refresh() {
|
|
13762
13973
|
var off = !enabled() || !map || loading || !activeStyle ||
|
|
13763
13974
|
!gui.map.getDisplayCRS(); // may be slow if getting bounds of many shapes
|
|
13764
|
-
fadeBtn.active(!off);
|
|
13765
|
-
clearBtn.active(!off);
|
|
13975
|
+
// fadeBtn.active(!off);
|
|
13976
|
+
// clearBtn.active(!off);
|
|
13977
|
+
|
|
13978
|
+
updateButtons();
|
|
13979
|
+
|
|
13766
13980
|
if (off) {
|
|
13767
13981
|
hide();
|
|
13768
13982
|
extentNote.hide();
|