WME GIS Buttons

Displays the locality of the current map location and provides links to open GIS if available

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name          WME GIS Buttons
// @author        @Philistine11
// @namespace     https://greasyfork.org/en/users/53803
// @description   Displays the locality of the current map location and provides links to open GIS if available
// @match         *://*.waze.com/*editor*
// @exclude       *://*.waze.com/user/editor*
// @grant         GM.xmlHttpRequest
// @connect       script.google.com
// @connect       script.googleusercontent.com
// @connect       maps.googleapis.com
// @version       1.7.0
// ==/UserScript==
/* global $, W, OpenLayers */

function gm_get(url) {
    return new Promise((resolve, reject) => {
        GM.xmlHttpRequest({
            method: 'GET',
            url: url,
            responseType: 'json',
            onload: e => resolve(e.response),
            onerror: reject,
            ontimeout: reject,
        });
    });
}

async function gis_init() {
    let gisButtonsOn = JSON.parse(localStorage.getItem('gisButtonsOn'));
    let gisButtonsApiKey = localStorage.getItem('gisButtonsApiKey');
    let gisButtonsDefaultGoogle = JSON.parse(localStorage.getItem('gisButtonsDefaultGoogle'));
    const gisButtons = $('<div style="display:flex; gap:2px; padding-left:2rem;"><div class="btn btn-default" style="padding:5px;"><span id="gisStatus" class="fa fa-spinner fa-pulse" style="font-size:x-large;"></span></div><a id="gisSubLocality" class="btn btn-default disabled hide" target="_blank" href="#">Sublocality</a><a id="gisLocality" class="btn btn-default disabled hide" target="_blank" href="#">Locality</a><a id="gisCounty" class="btn btn-default disabled hide" target="_blank" href="#">County</a><a id="gisState" class="btn btn-default disabled hide" target="_blank" href="#">State</a></div>');

    gisButtons.find('#gisStatus').click(() => {
        gisButtonsOn = !gisButtonsOn;
        localStorage.setItem('gisButtonsOn', gisButtonsOn);
        start();
    }).contextmenu(() => {
        do {
            gisButtonsApiKey = prompt("Enter your Google Maps API key:", gisButtonsApiKey || "").trim();
        } while (gisButtonsApiKey && gisButtonsApiKey.length != 39);
        localStorage.setItem('gisButtonsApiKey', gisButtonsApiKey);
        if (gisButtonsApiKey) {
            gisButtonsDefaultGoogle = confirm("Use Google Maps API by default ('OK'), or only when Census data is not available ('Cancel')?");
            localStorage.setItem('gisButtonsDefaultGoogle', gisButtonsDefaultGoogle);
        }
        start();
        return false;
    });

    let trigger;
    const setTrigger = () => {trigger = setTimeout(update, 1000);}
    const clearTrigger = () => clearTimeout(trigger);

    const states = {};
    const rows = await gm_get('https://script.google.com/macros/s/AKfycbx2bytvT5Un0TWcaU7BpVkauqeE8zqt8Mek7Zq-OF-bznGYDyZw/exec?link=10dR8z16eKPHeI-ywLcHh2UNS3enQ7gt36Hhzm9nOJbA');
    for (let row in rows) states[rows[row][0]] = rows[row][1];

    const update = async () => {
        $('#gisStatus').removeClass().addClass('fa fa-spinner fa-pulse').css('color','').attr('title','');
        $('#gisSubLocality, #gisLocality, #gisCounty, #gisState').addClass('hide');
        let sublocality = '', locality = '', county = '', state = '';

        const center = W.map.getOLMap().getCenter().transform(new OpenLayers.Projection('EPSG:900913'), new OpenLayers.Projection('EPSG:4326'));
        const censusData = gisButtonsDefaultGoogle ? {} : await $.getJSON(`https://geocoding.geo.census.gov/geocoder/geographies/coordinates?benchmark=Public_AR_Current&vintage=Current_Current&format=jsonp&callback=?&x=${center.lon}&y=${center.lat}`);
        if (censusData.result && Object.keys(censusData.result.geographies).length) {
            if (censusData.result.geographies.hasOwnProperty('States')) {
                state = censusData.result.geographies['States'][0].NAME;
                $('#gisState').removeClass('hide').text(state);
            }
            if (censusData.result.geographies.hasOwnProperty('Counties')) {
                county = censusData.result.geographies['Counties'][0].NAME;
                $('#gisCounty').removeClass('hide').text(county);
            }
            if (censusData.result.geographies.hasOwnProperty('Incorporated Places')) {
                locality = censusData.result.geographies['Incorporated Places'][0].BASENAME;
                $('#gisLocality').removeClass('hide').text(locality);
            }
        } else {
            if (!gisButtonsApiKey)
                return $('#gisStatus').removeClass().addClass('fa fa-key').css('color','red').attr('title',"Right-click to set Google Maps API Key");

            const googleData = await gm_get(`https://maps.googleapis.com/maps/api/geocode/json?latlng=${center.lat},${center.lon}&key=${gisButtonsApiKey}`);
            if (googleData.status === 'OK') {
                const locs = googleData.results.find((result) => !result.types.includes("point_of_interest")).address_components || [];
                for (let loc = 0; loc < locs.length; loc++)
                    if (locs[loc].types.indexOf('administrative_area_level_1') !== -1) {
                        state = locs[loc].long_name;
                        $('#gisState').removeClass('hide').text(state);
                    } else if (locs[loc].types.indexOf('administrative_area_level_2') !== -1) {
                        county = locs[loc].long_name;
                        $('#gisCounty').removeClass('hide').text(county);
                    } else if (locs[loc].types.indexOf('locality') !== -1) {
                        locality = locs[loc].long_name;
                        $('#gisLocality').removeClass('hide').text(locality);
                    } else if (locs[loc].types.indexOf('sublocality') !== -1 || locs[loc].types.indexOf('neighborhood') !== -1) {
                        sublocality = locs[loc].long_name;
                        $('#gisSubLocality').removeClass('hide').text(sublocality);
                    }
            } else {
                $('#gisStatus').removeClass().addClass('fa fa-exclamation-circle').css('color','red').attr('title', "Check console for errors");
                return console.error("GIS Buttons", censusData, googleData);
            }
        }

        $('#gisLocality, #gisCounty, #gisState').prop('href', '#').addClass('disabled');
        if (states.hasOwnProperty(state)) {
            if (typeof (states[state]) === 'string')
                states[state] = await gm_get(`https://script.google.com/macros/s/AKfycbx2bytvT5Un0TWcaU7BpVkauqeE8zqt8Mek7Zq-OF-bznGYDyZw/exec?link=${states[state]}`);
            for (let row in states[state])
                if (states[state][row][2] !== '')
                    if (states[state][row][1] === 'State') {
                        $('#gisState').prop('href', states[state][row][2].replace('<lat>',center.lat).replace('<lon>',center.lon).replace('<zoom>',W.map.getZoom())).removeClass('disabled');
                    } else if (states[state][row][1] === 'County') {
                        if (county.indexOf(states[state][row][0]) != -1)
                            $('#gisCounty').prop('href', states[state][row][2].replace('<lat>',center.lat).replace('<lon>',center.lon).replace('<zoom>',W.map.getZoom())).removeClass('disabled');
                    } else if (states[state][row][0] === locality)
                        $('#gisLocality').prop('href', states[state][row][2].replace('<lat>',center.lat).replace('<lon>',center.lon).replace('<zoom>',W.map.getZoom())).removeClass('disabled');
        }
        $('#gisStatus').removeClass().addClass('fa fa-power-off').css('color','green').attr('title',"Click to turn off GIS Buttons");
    };

    function start() {
        const location = $('div.topbar:not(.topbar-mte) > div.location-info-region');
        if (location.length === 0) return setTimeout(start, 500);
        location.after(gisButtons);

        const mapEvents = W.map.events;
        if (gisButtonsOn) {
            mapEvents.register('movestart', null, clearTrigger);
            mapEvents.register('moveend', null, setTrigger);
            update();
        } else {
            clearTrigger();
            mapEvents.unregister('movestart', null, clearTrigger);
            mapEvents.unregister('moveend', null, setTrigger);
            $('#gisSubLocality, #gisLocality, #gisCounty, #gisState').addClass('hide');
            $('#gisStatus').removeClass().addClass('fa fa-power-off').css('color','red').attr('title',"Click to turn on GIS Buttons");
        }
    }

    start();
}

gis_init();