SK WMS layers

Displays layers from Slovak WMS services in WME

Pada tanggal 29 Juni 2020. Lihat %(latest_version_link).

// ==UserScript==
// @name		SK WMS layers
// @version		2020.06.29
// @authorCZ		petrjanik, d2-mac, MajkiiTelini, hamilnes
// @description		Displays layers from Slovak WMS services in WME
// @include		/^https:\/\/(www|beta)\.waze\.com\/(?!user\/)(.{2,6}\/)?editor.*$/
// @run-at		document-end587499
// @namespace		https://greasyfork.org/cs/users/587499
// ==/UserScript==

var WMSLayersTechSource = {};
var W;
var OL;
var I18n;
init();

function init(e) {
    W = unsafeWindow.W;
    OL = unsafeWindow.OpenLayers;
    I18n = unsafeWindow.I18n;
    if (e && e.user === null) {
        return;
    }
    if (typeof W === "undefined" || typeof W.loginManager === "undefined") {
        setTimeout(init, 100);
        return;
    }
    if (!W.loginManager.user) {
        W.loginManager.events.register("login", null, init);
        W.loginManager.events.register("loginStatus", null, init);
    }
    if (document.getElementById("layer-switcher") === null && document.getElementById("layer-switcher-group_display") === null) {
        setTimeout(init, 200);
        return;
    }
    WMSLayersTechSource.tileSizeG = new OL.Size(512,512);
    WMSLayersTechSource.resolutions =	 [156543.03390625,
                                          78271.516953125,
                                          39135.7584765625,
                                          19567.87923828125,
                                          9783.939619140625,
                                          4891.9698095703125,
                                          2445.9849047851562,
                                          1222.9924523925781,
                                          611.4962261962891,
                                          305.74811309814453,
                                          152.87405654907226,
                                          76.43702827453613,
                                          38.218514137268066,
                                          19.109257068634033,
                                          9.554628534317017,
                                          4.777314267158508,
                                          2.388657133579254,
                                          1.194328566789627,
                                          0.5971642833948135,
                                          0.298582141697406,
                                          0.149291070848703,
                                          0.0746455354243515,
                                          0.0373227677121757
                                         ];
    // Adresy WMS služieb
    var service_wms_cdb_cesty = {"type" : "WMS", "url" : "https://ismcs.cdb.sk/inspire/services/FREE/WMS_ReferencnaSiet/MapServer/WMSServer?", "attribution" : "© CDB", "comment" : "CDB - cestná sieť"};
    var service_wms_cdb_objekty = {"type" : "WMS", "url" : "http://ismcs.cdb.sk/inspire/services/FREE/WMS_CestneObjekty/MapServer/WMSServer?", "attribution" : "© CDB", "comment" : "CDB - cestné objekty"};
    var service_wms_orto = {"type" : "WMS", "url" : "https://zbgisws.skgeodesy.sk/zbgis_ortofoto_wms/service.svc/get?", "attribution" : "© GKÚ, NLC; r.2017 - 2019", "comment" : "Geoportál ZBGIS - Ortofotomozaika"};
    var service_wms_hranice = {"type" : "WMS", "url" : "https://zbgisws.skgeodesy.sk/zbgis_administrativne_hranice_wms_featureinfo/service.svc/get??", "attribution" : "© GKÚ Bratislava; r. 2017", "comment" : "Geoportál ZBGIS - Administratívne hranice"};
    var service_wms_geonames = {"type" : "WMS", "url" : "https://zbgisws.skgeodesy.sk/zbgis_geograficke_nazvoslovie_wms/service.svc/get?", "attribution" : "© GKÚ Bratislava; r. 2017", "comment" : "Geoportál ZBGIS - Geografické názvoslovie"};
    var service_wms_katastr = {"type" : "WMS", "url" : "https://kataster.skgeodesy.sk/eskn/services/NR/kn_wms_orto/MapServer/WmsServer?", "attribution" : "© ÚGKK SR; r. 2015", "comment" : "Geoportál ZBGIS - Služba WMS - Parcely C (SJTSK aj Web Mercator)"};
    var service_wms_zbgis = {"type" : "WMS", "url" : "https://zbgisws.skgeodesy.sk/zbgis_wms_featureinfo/service.svc/get?", "attribution" : "© GKÚ Bratislava; r. 2017", "comment" : "Geoportál ZBGIS - všetky kategórie"};
    // Adresy externé
    var service_xyz_google_streetview = {"type" : "XYZ", "url" : ["https://mts0.google.com/mapslt?lyrs=svv&&x=${x}&y=${y}&z=${z}&style=40", "https://mts1.google.com/mapslt?lyrs=svv&&x=${x}&y=${y}&z=${z}&style=40", "https://mts2.google.com/mapslt?lyrs=svv&&x=${x}&y=${y}&z=${z}&style=40", "https://mts3.google.com/mapslt?lyrs=svv&&x=${x}&y=${y}&z=${z}&style=40"],
    									 "attribution" : "Google <a href='https://www.google.com/intl/cs_cz/help/terms_maps.html' target='_blank'>Smluvní podmínky</a>", "comment" : "Google Streetview"};
    // Skupiny vrstev v menu
    var groupTogglerPlaces = addGroupToggler(true, "layer-switcher-group_places");
    var groupTogglerRoad = addGroupToggler(true, "layer-switcher-group_road");
    var groupTogglerDisplay = addGroupToggler(true, "layer-switcher-group_display");
    var groupTogglerNames = addGroupToggler(false, "layer-switcher-group_names", "Názvy");
    var groupTogglerBorders = addGroupToggler(false, "layer-switcher-group_borders", "Hranice");

    // Vrstvy v menu
    var WMSLayerTogglers = {};
    // MIESTA
    WMSLayerTogglers.wms_lesvoda = addLayerToggler(groupTogglerPlaces, "Lesy a vody", true, [addNewLayer("wms_lesvoda", service_wms_zbgis, "6,129", 400), addNewLayer("wms_lesvoda_1", service_wms_zbgis, "20,21,22,25,38,39,50,52,69,70,72,75,77,103,104,137,149,151", 201, 0.7)]);
    // CESTA
    WMSLayerTogglers.wms_cdb_cesty = addLayerToggler(groupTogglerRoad, "Cesty CDB", true, [addNewLayer("wms_cdb_cesty", service_wms_cdb_cesty, "3,4,6,7,8,10,11,12,14,15,18,19,20,22,23,24,26,27,28,29,30,31,38")]);
    WMSLayerTogglers.wms_cdb_objekty = addLayerToggler(groupTogglerRoad, "Objekty CDB", true, [addNewLayer("wms_cdb_objekty", service_wms_cdb_objekty, "1,2,3,4,5,6,7,8")]);
    //WMSLayerTogglers.wms_doprava = addLayerToggler(groupTogglerRoad, "Doprava", true, [addNewLayer("wms_doprava", service_wms_zbgis, "33,56,57,58,59,60,61,63,73,96,138,139,140,141,142")]);
    // ZOBRAZIŤ
    WMSLayerTogglers.wms_orto = addLayerToggler(groupTogglerDisplay, "Ortofoto ZBGIS", true, [addNewLayer("wms_orto", service_wms_orto, "1,2,3", 200)]);
    WMSLayerTogglers.wms_katastr = addLayerToggler(groupTogglerDisplay, "Katastrálna mapa", true, [addNewLayer("wms_katastr", service_wms_katastr, "1,2,3,5,6,7,8,10,11,12,13,14,15")]);
    // NÁZVY
    WMSLayerTogglers.wms_geonames = addLayerToggler(groupTogglerNames, "Názvy geo", true, [addNewLayer("wms_geonames", service_wms_geonames, "0,1,2,3,4", 470)]);
    // HRANICE
    WMSLayerTogglers.wms_stat = addLayerToggler(groupTogglerBorders, "Štátne hranice", true, [addNewLayer("wms_stat", service_wms_hranice, "3")]);
    WMSLayerTogglers.wms_kraje = addLayerToggler(groupTogglerBorders, "Hranice krajov", true, [addNewLayer("wms_kraje", service_wms_hranice, "2")]);
    WMSLayerTogglers.wms_okresy = addLayerToggler(groupTogglerBorders, "Hranice okresov", true, [addNewLayer("wms_okresy", service_wms_hranice, "1")]);
    WMSLayerTogglers.wms_obce = addLayerToggler(groupTogglerBorders, "Hranice obcí", true, [addNewLayer("wms_obce", service_wms_hranice, "0")]);

    W.map.olMap.events.register("addlayer", null, fillWMSLayersSelectList);
    W.map.olMap.events.register("removelayer", null, fillWMSLayersSelectList);
    W.map.olMap.events.register("addlayer", null, setZOrdering(WMSLayerTogglers));
    W.map.olMap.events.register("removelayer", null, setZOrdering(WMSLayerTogglers));
    W.map.olMap.events.register("moveend", null, setZOrdering(WMSLayerTogglers));

    var isLoaded = false;
    window.addEventListener("beforeunload", function() {
        if (localStorage !== undefined & isLoaded) {
            var JSONStorageOptions = {};
            for (var key in WMSLayerTogglers) {
                if (WMSLayerTogglers[key].serviceType == "WMS") {
                    JSONStorageOptions[key] = document.getElementById(WMSLayerTogglers[key].htmlItem).checked;
                }
            }
            localStorage.WMSLayers = JSON.stringify(JSONStorageOptions);
        }
    }, false);
    window.addEventListener("load", function() {
        isLoaded = true;
        if (localStorage.WMSLayers) {
            var JSONStorageOptions = JSON.parse(localStorage.WMSLayers);
            for (var key in WMSLayerTogglers) {
                if (JSONStorageOptions[key] & WMSLayerTogglers[key].serviceType == "WMS") {
                    document.getElementById(WMSLayerTogglers[key].htmlItem).click();
                }
            }
        }
    }, false);

    var userTabs = document.getElementById("user-info");
    var navTabs = document.getElementsByClassName("nav-tabs", userTabs)[0];
    var tabContent = document.getElementsByClassName("tab-content", userTabs)[0];

    var newtab = document.createElement("li");
    newtab.innerHTML = "<a href='#sidepanel-wms' data-toggle='tab' title='SK WMS layers'>WMS</a>";
    navTabs.appendChild(newtab);

    var addon = document.createElement("section");
    addon.innerHTML = "<b><u><a href='https://greasyfork.org/scripts/406085' target='_blank'>" + GM_info.script.name + "</a></u></b> &nbsp; v" + GM_info.script.version;
    addon.id = "sidepanel-wms";
    addon.className = "tab-pane";
    tabContent.appendChild(addon);

    var section = document.createElement("section");
    section.style.fontSize = "13px";
    section.id = "WMS";
    section.style.marginBottom = "15px";
    section.appendChild(document.createElement("br"));
    section.appendChild(document.createTextNode("WMS vrstva: "));
    var WMSSelect = document.createElement("select");
    WMSSelect.id = "WMSLayersSelect";
    section.appendChild(WMSSelect);
    var opacityRange = document.createElement("input");
    var opacityLabel = document.createElement("label");
    opacityRange.type = "range";
    opacityRange.min = 0;
    opacityRange.max = 100;
    opacityRange.value = 100;
    opacityRange.id = "WMSOpacity";
    opacityLabel.textContent = " Priehľadnosť vrstvy: " + opacityRange.value + " %";
    opacityLabel.id = "WMSOpacityLabel";
    opacityLabel.htmlFor = opacityRange.id;
    section.appendChild(opacityLabel);
    section.appendChild(opacityRange);
    addon.appendChild(section);
    opacityRange.addEventListener("input", function() {
        var value = document.getElementById("WMSLayersSelect").value;
        if (value !== "" && value !== "undefined") {
            var layer = W.map.getLayerByUniqueName(value);
            layer.setOpacity(opacityRange.value / 100);
            document.getElementById("WMSOpacityLabel").textContent = " Priehľadnosť vrstvy: " + document.getElementById("WMSOpacity").value + " %";
        }
    });
    WMSSelect.addEventListener("change", function() {
        opacityRange.value = W.map.layers.filter(layer => layer.uniqueName == WMSSelect.value)[0].opacity * 100;
        document.getElementById("WMSOpacityLabel").textContent = " Priehľadnosť vrstvy: " + document.getElementById("WMSOpacity").value + " %";
    });
    setZOrdering(WMSLayerTogglers);
}

function fillWMSLayersSelectList() {
    var select = document.getElementById("WMSLayersSelect");
    var value = select.value;
    var htmlCode;
    W.map.layers.filter(layer => layer.uniqueName !== undefined && layer.uniqueName.startsWith("_wms_")).forEach(
        layer => (htmlCode += "<option value='" + layer.uniqueName + "'>" + layer.name + " [" + layer.uniqueName + "]</option><br>"));
    select.innerHTML = htmlCode;
    select.value = value;
}

function addNewLayer(id, service, serviceLayers, zIndex = 0, opacity = 1) {
    var newLayer = {};
    newLayer.uniqueName = "_" + id;
    newLayer.serviceType = service.type;
    newLayer.zIndex = (service.type == "XYZ" & zIndex == 0) ? 200 : zIndex;
    switch(service.type) {
        case "WMS":
            newLayer.layer = new OL.Layer.WMS(
                id, service.url,
                {
                    layers: serviceLayers ,
                    transparent: "true",
                    format: "image/png"
                },
                {
                    opacity: opacity,
                    tileSize: WMSLayersTechSource.tileSizeG,
                    isBaseLayer: false,
                    visibility: false,
                    transitionEffect: "resize",
                    attribution: service.attribution,
                    uniqueName: newLayer.uniqueName,
                    projection: new OL.Projection("EPSG:3857") //alternativa defaultní EPSG:900913
                }
            );
            break;
        case "WMS_4326":
            newLayer.layer = new OL.Layer.WMS(
                id, service.url,
                {
                    layers: serviceLayers ,
                    transparent: "true",
                    format: "image/png"
                },
                {
                    opacity: opacity,
                    tileSize: WMSLayersTechSource.tileSizeG,
                    isBaseLayer: false,
                    visibility: false,
                    transitionEffect: "resize",
                    attribution: service.attribution,
                    uniqueName: newLayer.uniqueName,
                    epsg4326: new OL.Projection("EPSG:4326"),
                    getURL: getUrl4326,
                    getFullRequestString: getFullRequestString4326
                }
            );
            break;
        case "XYZ":
            newLayer.layer = new OL.Layer.XYZ(
                id, service.url,
                {
                    sphericalMercator: true,
                    isBaseLayer: false,
                    visibility: false,
                    zoomOffset: 12,
                    RESOLUTION_PROPERTIES: {},
                    resolutions: WMSLayersTechSource.resolutions,
                    serverResolutions: WMSLayersTechSource.resolutions.slice(0, ("maxZoom" in service & service.maxZoom > 0) ? service.maxZoom : 23),
                    transitionEffect: "resize",
                    attribution: service.attribution,
                    uniqueName: newLayer.uniqueName
                }
            );
            break;
        default:
            newLayer.layer = null;
    }
    return newLayer;
}

function addGroupToggler(isDefault, layerSwitcherGroupItemName, layerGroupVisibleName) {
    var group;
    if (isDefault === true) {
        group = document.getElementById(layerSwitcherGroupItemName).parentElement.parentElement;
    }
    else {
        var layerGroupsList = document.getElementsByClassName("list-unstyled togglers")[0];
        group = document.createElement("li");
        group.className = "group";
        var togglerContainer = document.createElement("div");
        togglerContainer.className = "layer-switcher-toggler-tree-category";
        var iCaretDown = document.createElement("i");
        iCaretDown.className = "toggle-category w-icon w-icon-caret-down";
        iCaretDown.dataset.groupId = layerSwitcherGroupItemName.replace("layer-switcher-", "").toUpperCase();
        iCaretDown.addEventListener("click", layerTogglerGroupMinimizerEventHandler(iCaretDown));
        var togglerSwitch = document.createElement("wz-toggle-switch");
        togglerSwitch.className = layerSwitcherGroupItemName + " hydrated";
        togglerSwitch.id = layerSwitcherGroupItemName;
        togglerSwitch.checked = true;
        var label = document.createElement("label");
        label.className = "label-text";
        label.htmlFor = togglerSwitch.id;
        var togglerChildrenList = document.createElement("ul");
        togglerChildrenList.className = "collapsible-" + layerSwitcherGroupItemName.replace("layer-switcher-", "").toUpperCase();
        label.appendChild(document.createTextNode(layerGroupVisibleName));
        togglerContainer.appendChild(iCaretDown);
        togglerContainer.appendChild(togglerSwitch);
        togglerContainer.appendChild(label);
        group.appendChild(togglerContainer);
        group.appendChild(togglerChildrenList);
        layerGroupsList.appendChild(group);
    }
    return group;
}

function addLayerToggler(groupToggler, layerName, isPublic, layerArray) {
    var layerToggler = {};
    layerToggler.layerName = layerName;
    layerToggler.serviceType = (layerArray.filter(function(e) {return e.serviceType == "XYZ";}).length > 0) ? "XYZ" : "WMS";
    var layerShortcut = layerName.replace(/ /g, "_").replace(".", "");
    layerToggler.htmlItem = "layer-switcher-item_" + layerShortcut;
    layerToggler.layerArray = layerArray;
    var layer_container = groupToggler.getElementsByTagName("UL")[0];
    var layerGroupCheckbox = groupToggler.getElementsByClassName("layer-switcher-toggler-tree-category")[0].getElementsByTagName("wz-toggle-switch")[0];
    var toggler = document.createElement("li");
    var togglerCheckbox = document.createElement("wz-checkbox");
    togglerCheckbox.id = layerToggler.htmlItem;
    togglerCheckbox.className = "hydrated";
    var labelSymbol = document.createElement("span");
    labelSymbol.className = (isPublic) ? "fa fa-location-arrow" : "fa fa-lock";
    togglerCheckbox.appendChild(labelSymbol);
    togglerCheckbox.appendChild(document.createTextNode(layerName));
    toggler.appendChild(togglerCheckbox);
    layer_container.appendChild(toggler);
    for (var i = 0; i < layerArray.length; i++){
        togglerCheckbox.addEventListener("click", layerTogglerEventHandler(layerArray[i]));
        layerGroupCheckbox.addEventListener("click", layerTogglerGroupEventHandler(togglerCheckbox, layerArray[i]));
        layerArray[i].layer.name = layerName;
    }
    registerKeyShortcut("WMS: " + layerName, layerKeyShortcutEventHandler(layerGroupCheckbox, togglerCheckbox), layerShortcut);
    return layerToggler;
}

function registerKeyShortcut(actionName, callback, keyName) {
    I18n.translations[I18n.locale].keyboard_shortcuts.groups.default.members[keyName] = actionName;
    W.accelerators.addAction(keyName, {group: "default"});
    W.accelerators.events.register(keyName, null, callback);
    W.accelerators._registerShortcuts({[""]: keyName});
}

function layerTogglerEventHandler(layerType) {
    return function() {
        if (this.checked) {
            W.map.addLayer(layerType.layer);
            layerType.layer.setVisibility(this.checked);
        }
        else {
            layerType.layer.setVisibility(this.checked);
            W.map.removeLayer(layerType.layer);
        }
    };
}

function layerKeyShortcutEventHandler(groupCheckbox, checkbox) {
    return function() {
        if (!groupCheckbox.disabled) {
            checkbox.click();
        }
    };
}

function layerTogglerGroupEventHandler(checkbox, layerType) {
    return function() {
        if (this.checked) {
            if (checkbox.checked) {
                W.map.addLayer(layerType.layer);
                layerType.layer.setVisibility(this.checked & checkbox.checked);
            }
        }
        else {
            if (checkbox.checked) {
                layerType.layer.setVisibility(this.checked & checkbox.checked);
                W.map.removeLayer(layerType.layer);
            }
        }
        checkbox.disabled = !this.checked;
    };
}

function layerTogglerGroupMinimizerEventHandler(iCaretDown) {
    return function() {
        var ulCollapsible = iCaretDown.parentElement.parentElement.getElementsByTagName("UL")[0];
        if (!iCaretDown.classList.contains("upside-down")) {
            iCaretDown.classList.add("upside-down");
            ulCollapsible.classList.add("collapse-layer-switcher-group");
        }
        else {
            iCaretDown.classList.remove("upside-down");
            ulCollapsible.classList.remove("collapse-layer-switcher-group");
        }
    };
}

function setZOrdering(layerTogglers) {
    return function() {
        for (var key in layerTogglers) {
            for (var j = 0; j < layerTogglers[key].layerArray.length; j++) {
                if (layerTogglers[key].layerArray[j].zIndex > 0) {
                    var l = W.map.getLayersBy("uniqueName", layerTogglers[key].layerArray[j].uniqueName);
                    if (l.length > 0) {
                        l[0].setZIndex(layerTogglers[key].layerArray[j].zIndex);
                    }
                }
            }
        }
    };
}

function getUrl4326(bounds) {
    var newParams = {};
    bounds.transform(this.projection, this.epsg4326);
    newParams.BBOX = bounds.toArray(this.reverseAxisOrder());
    newParams.WIDTH = 742;
    newParams.HEIGHT = 485;
    var requestString = this.getFullRequestString(newParams);
    return requestString;
}

function getFullRequestString4326(newParams) {
    this.params.SRS = "EPSG:4326";
    return OL.Layer.Grid.prototype.getFullRequestString.apply(this, arguments);
}