WME E58 Map's previews

Create small previews for chosen map providers

Bu betiği kurabilmeniz için Tampermonkey, Greasemonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği yüklemek için Tampermonkey gibi bir uzantı yüklemeniz gerekir.

Bu betiği kurabilmeniz için Tampermonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Userscripts gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği indirebilmeniz için ayrıca Tampermonkey gibi bir eklenti kurmanız gerekmektedir.

Bu komut dosyasını yüklemek için bir kullanıcı komut dosyası yöneticisi uzantısı yüklemeniz gerekecek.

(Zaten bir kullanıcı komut dosyası yöneticim var, kurmama izin verin!)

Bu stili yüklemek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için Stylus gibi bir uzantı kurmanız gerekir.

Bu stili yükleyebilmek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı kurmanız gerekir.

Bu stili yükleyebilmek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

(Zateb bir user-style yöneticim var, yükleyeyim!)

// ==UserScript==
// @name         WME E58 Map's previews
// @name:uk      WME 🇺🇦 E58 Map's previews
// @name:ru      WME 🇺🇦 E58 Map's previews
// @version      0.10.0
// @description  Create small previews for chosen map providers
// @description:uk Створює невеличку карту для перегляду
// @description:ru Создаёт небольшую карту для просмотра
// @license      MIT License
// @author       Anton Shevchuk
// @namespace    https://greasyfork.org/users/227648-anton-shevchuk
// @supportURL   https://github.com/AntonShevchuk/wme-e58/issues
// @match        https://*.waze.com/editor*
// @match        https://*.waze.com/*/editor*
// @exclude      https://*.waze.com/user/editor*
// @icon         data:image/png;base64,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
// @grant        none
// @require      https://update.greasyfork.org/scripts/389765/1793258/CommonUtils.js
// @require      https://update.greasyfork.org/scripts/450160/1792042/WME-Bootstrap.js
// @require      https://update.greasyfork.org/scripts/450221/1793261/WME-Base.js
// @require      https://update.greasyfork.org/scripts/450320/1794414/WME-UI.js
// ==/UserScript==

(function () {
    'use strict';

    const NAME = 'E58';

    const TRANSLATION = {
        'en': {
            // Tab title
            title: 'Map preview',
            // Tab description
            description: 'Open a small preview modal window with the map',
            // Tab help
            help: 'You can use the <strong>Keyboard shortcuts</strong> to open the map preview window. It\'s more convenient than clicking on the button.',
            maps: {
                // Fieldset's legend
                title: 'Sources',
                // Fieldset's description
                description: 'Choose a map provider',
                // Description for option `Google`
                google: 'Google',
                // Description for option `OSM`
                osm: 'Open Street Map',
            },
            options: {
                title: 'Options',
                description: 'Choose a map provider in the settings',
                controls: 'Controls on the map',
                interactive: 'Interaction with the map',
            },
        },
        'uk': {
            title: 'Карта',
            description: 'Відкрити маленьку карту',
            help: 'Використовуйте <strong>гарячі клавіши</strong>, це значно швидше ніж використовувати кнопку',
            maps: {
                title: 'Джерела',
                description: 'Оберіть карту для відображення',
                google: 'Google',
                osm: 'Open Street Map',
            },
            options: {
                title: 'Налаштування',
                description: 'Оберіть у налаштуваннях карту для відображення',
                controls: 'Елементи управління',
                interactive: 'Можливість взаємодіяти с картою',
            },
        },
        'ru': {
            title: 'Карта',
            description: 'Открыть маленькую карту',
            help: 'Используйте <strong>комбинации клавиш</strong>, и не надо будет клацать кнопку',
            maps: {
                title: 'Источники',
                description: 'Выберите карту для отображения',
                google: 'Google',
                osm: 'Open Street Map',
            },
            options: {
                title: 'Настройки',
                description: 'Выберите в настройках карту для отображения',
                controls: 'Элементы управления карты',
                interactive: 'Возможность взаимодействия с картой',
            },
        }
    };

    const SETTINGS = {
        map: 'google',
        maps: [
            'google', 'osm'
        ],
        options: {
            controls: false,
            interactive: false,
        }
    };

    /**
     * Basic Map class
     */
    class MapPreview {
        constructor(uid, container, settings, wmeSDK) {
            this.uid = uid;
            this.map = null;
            this.wrapper = this._wrapper();
            container.append(this.wrapper);
            container.style.height = '256px';
            this.settings = settings;
            this.wmeSDK = wmeSDK;
            this.controls = settings.get('options', 'controls');
            this.interactive = settings.get('options', 'interactive');
        }
        /**
         * Load external JS Map library
         * @param  {String} url
         * @return {Promise<*>}
         */
        async script(url) {
            return $.ajax({
                url: url,
                cache: true,
                dataType: 'script',
                success: () => console.log(NAME, this.uid, 'loaded')
            });
        }
        /**
         * Build div for map
         * @return {HTMLDivElement}
         * @protected
         */
        _wrapper() {
            let div = document.createElement('div');
            div.id = this._uid();
            div.style.height = '256px';
            return div;
        }
        _uid() {
            return NAME + '-map-' + this.uid;
        }
        _center() {
            let center = this.wmeSDK.Map.getMapCenter();
            return {
                lon: center.lon,
                lat: center.lat,
            };
        }
        _zoom() {
            return this.wmeSDK.Map.getZoomLevel() - 1;
        }
        update() {
            let center = this._center();
            this._update(center.lat, center.lon, this._zoom());
        }
        _update(lat, lon, zoom) {
            throw new Error('Abstract method');
        }
    }
    /**
     * Google Maps
     */
    class GooglePreview extends MapPreview {
        constructor(container, settings, wmeSDK) {
            super('Google', container, settings, wmeSDK);
        }
        async render() {
            let pos = this._center();
            this.map = new google.maps.Map(this.wrapper, {
                center: new google.maps.LatLng(pos.lat, pos.lon),
                zoom: this._zoom(),
                mapTypeId: 'roadmap',
                mapTypeControl: false,
                streetViewControl: false,
                disableDefaultUI: !this.controls,
                gestureHandling: this.interactive ? 'cooperative' : 'none',
                zoomControl: this.controls,
            });
            // Setup handler
            this.wmeSDK.Events.on({ eventName: 'wme-map-move-end', eventHandler: () => this.update() });
        }
        _update(lat, lon, zoom) {
            this.map.setZoom(zoom);
            this.map.setCenter(new google.maps.LatLng(lat, lon));
        }
    }
    /**
     * Open Street Maps
     */
    class OSMPreview extends MapPreview {
        constructor(container, settings, wmeSDK) {
            super('OSM', container, settings, wmeSDK);
        }
        async render() {
            let pos = this._center();
            this.map = new google.maps.Map(this.wrapper, {
                center: new google.maps.LatLng(pos.lat, pos.lon),
                zoom: this._zoom(),
                mapTypeId: 'OSM',
                mapTypeControl: false,
                streetViewControl: false,
                disableDefaultUI: !this.controls,
                gestureHandling: this.interactive ? 'cooperative' : 'none',
                zoomControl: this.controls,
            });
            // Define OSM map type pointing at the OpenStreetMap tile server
            this.map.mapTypes.set('OSM', new google.maps.ImageMapType({
                getTileUrl: function (coord, zoom) {
                    return 'https://tile.openstreetmap.org/' + zoom + '/' + coord.x + '/' + coord.y + '.png';
                },
                tileSize: new google.maps.Size(256, 256),
                name: 'OpenStreetMap',
                maxZoom: 18
            }));
            // Setup handler
            this.wmeSDK.Events.on({ eventName: 'wme-map-move-end', eventHandler: () => this.update() });
        }
        _update(lat, lon, zoom) {
            this.map.setZoom(zoom);
            this.map.setCenter(new google.maps.LatLng(lat, lon));
        }
    }

    /**
     * E58 Map Preview class
     */
    class E58 extends WMEBase {
        constructor(name, settings) {
            super(name, settings);
            this.initTab(settings);
            this.initShortcuts();
        }
        initTab(settings) {
            let tab = this.helper.createTab(WMEUI.t(NAME).title, {
                sidebar: this.wmeSDK.Sidebar,
                image: GM_info.script.icon
            });
            tab.addText('description', WMEUI.t(NAME).description);
            tab.addButton('preview', WMEUI.t(NAME).title, '', () => this.toggleMap(), { className: 'waze-btn waze-btn-small waze-btn-white waze-btn-blue' });
            // Setup providers map settings
            let fsMap = this.helper.createFieldset(WMEUI.t(NAME).maps.title);
            for (let i = 0; i < settings.maps.length; i++) {
                let map = settings.maps[i];
                fsMap.addRadio('maps-' + map, WMEUI.t(NAME).maps[map], () => this.settings.set('map', map), 'maps', map, this.settings.get('map') === map);
            }
            tab.addElement(fsMap);
            // Setup options for maps
            let fsOptions = this.helper.createFieldset(WMEUI.t(NAME).options.title);
            let checkboxes = {};
            for (let item in settings.options) {
                if (settings.options.hasOwnProperty(item)) {
                    checkboxes['options-' + item] = {
                        title: WMEUI.t(NAME).options[item],
                        callback: (event) => this.settings.set('options', item, event.target.checked),
                        checked: this.settings.get('options', item),
                    };
                }
            }
            fsOptions.addCheckboxes(checkboxes);
            tab.addElement(fsOptions);
            tab.addDiv('text', WMEUI.t(NAME).help);
            tab.addText('info', '<a href="' + GM_info.scriptUpdateURL + '">' + GM_info.script.name + '</a> ' + GM_info.script.version);
            tab.addText('blue', 'made in');
            tab.addText('yellow', 'Ukraine');
            tab.inject();
        }
        initShortcuts() {
            this.createShortcut('toggle', WMEUI.t(NAME).description, 'A+N', () => this.toggleMap());
        }
        /**
         * Show modal with map preview
         */
        toggleMap() {
            if (document.getElementById('e58-map-preview')) {
                this.log('hide preview map');
                $('.wme-ui-panel.e58 button.wme-ui-close-panel').click();
                return;
            }
            /** @type {WMEUIHelperModal} */
            let modal = this.helper.createModal(WMEUI.t(NAME).title);
            // Setup Preview Map element
            let map = modal.addDiv('map-preview').html();
            modal.inject();
            this.log('show preview map', this.settings.get('map'));
            if (this.settings.get('map') === 'google') {
                let Google = new GooglePreview(map, this.settings, this.wmeSDK);
                Google.render();
            }
            else if (this.settings.get('map') === 'osm') {
                let OSM = new OSMPreview(map, this.settings, this.wmeSDK);
                OSM.render();
            }
            else {
                // disabled
                map.innerText = WMEUI.t(NAME).maps.description;
            }
        }
    }

    var css_248z = ".e58 .header h5 {\n  padding: 16px 16px 0;\n  font-size: 16px;\n}\n.e58 legend {\n  cursor: pointer;\n  font-size: 12px;\n  font-weight: bold;\n  width: auto;\n  text-align: right;\n  border: 0;\n  margin: 0;\n  padding: 0 8px;\n}\n.e58 fieldset {\n  border: 1px solid #ddd;\n  padding: 4px;\n}\n.e58 fieldset p {\n  padding: 0;\n  margin: 0 8px !important;\n}\n.e58 fieldset.e58 .wme-ui-fieldset-content label {\n  white-space: normal;\n  font-weight: 400;\n}\ndiv.e58.e58-text {\n  margin: 15px 0;\n}\n.e58 .wme-ui-tab-content {\n  padding: 8px;\n}\np.e58-info {\n  border-top: 1px solid #ccc;\n  color: #777;\n  font-size: x-small;\n  margin-top: 15px;\n  padding-top: 10px;\n  text-align: center;\n}\n#sidebar p.e58-blue {\n  background-color: #0057B8;\n  color: white;\n  height: 32px;\n  text-align: center;\n  line-height: 32px;\n  font-size: 24px;\n  margin: 0;\n}\n#sidebar p.e58-yellow {\n  background-color: #FFDD00;\n  color: black;\n  height: 32px;\n  text-align: center;\n  line-height: 32px;\n  font-size: 24px;\n  margin: 0;\n}\n";

    $(document).on('bootstrap.wme', () => {
        WMEUI.addTranslation(NAME, TRANSLATION);
        WMEUI.addStyle(css_248z);
        new E58(NAME, SETTINGS);
    });

})();