WME GIS Buttons

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

当前为 2022-08-11 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴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.6.1
// ==/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 class="input-group input-group-sm" style="float:left; padding-left:2rem;"><span class="input-group-addon" style="display:table-cell; font-size:x-large; line-height:0; width:0;"><span id="gisStatus" class="fa fa-spinner fa-pulse" style="line-height:0;vertical-align: middle;"></span></span><div class="input-group-btn" style="width:0;"><a id="gisLocality" class="btn btn-default disabled hidden" style="border:1px solid" target="_blank" href="#">Locality</a><a id="gisCounty" class="btn btn-default disabled hidden" style="border:1px solid" target="_blank" href="#">County</a><a id="gisState" class="btn btn-default disabled hidden" style="border:1px solid" target="_blank" href="#">State</a></span></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','');
        $('#gisLocality, #gisCounty, #gisState').addClass('hidden');
        let locality = '', county = '', state = '';

        const center = W.map.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('hidden').text(state);
            }
            if (censusData.result.geographies.hasOwnProperty('Counties')) {
                county = censusData.result.geographies['Counties'][0].NAME;
                $('#gisCounty').removeClass('hidden').text(county);
            }
            if (censusData.result.geographies.hasOwnProperty('Incorporated Places')) {
                locality = censusData.result.geographies['Incorporated Places'][0].BASENAME;
                $('#gisLocality').removeClass('hidden').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('hidden').text(state);
                    } else if (locs[loc].types.indexOf('administrative_area_level_2') !== -1) {
                        county = locs[loc].long_name;
                        $('#gisCounty').removeClass('hidden').text(county);
                    } else if (locs[loc].types.indexOf('locality') !== -1) {
                        locality = locs[loc].long_name;
                        $('#gisLocality').removeClass('hidden').text(locality);
                    }
            } 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 mapEvents = W.map.events || W.map.getMapEventsListener();

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

        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);
            $('#gisLocality, #gisCounty, #gisState').addClass('hidden');
            $('#gisStatus').removeClass().addClass('fa fa-power-off').css('color','red').attr('title',"Click to turn on GIS Buttons");
        }
    }

    start();
}

gis_init();