WME Place Interface Enhancements

Enhancements to various Place interfaces

目前為 2017-01-09 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         WME Place Interface Enhancements
// @namespace    https://greasyfork.org/users/30701-justins83-waze
// @version      0.3.0
// @description  Enhancements to various Place interfaces
// @include      https://www.waze.com/editor/*
// @include      https://www.waze.com/*/editor/*
// @include      https://beta.waze.com/*
// @exclude      https://www.waze.com/user/editor*
// @author       JustinS83
// @grant        none
// @require      https://greasyfork.org/scripts/24851-wazewrap/code/WazeWrap.js
// @license      GPLv3
// ==/UserScript==

(function() {
    'use strict';

    var settings = {};

    // Your code here...
    function bootstrap(tries) {
        tries = tries || 1;

        if (window.W &&
            window.W.map &&
            window.W.model &&
            $) {
            init();
        } else if (tries < 1000) {
            setTimeout(function () {bootstrap(tries++);}, 200);
        }
    }

    bootstrap();

    function init(){
        var $section = $("<div>", {style:"padding:8px 16px", id:"WMEPIESettings"});
        $section.html([
            '<h4><b>WME Place Interface Enhancements</b></h4>',
            '<div class="controls-container" id="divAreaPlaceSizeControls">',
            '<div id="divShowAreaPlaceSize" class="controls-container"><input type="checkbox" id="_cbShowAreaPlaceSize" class="pieSettingsCheckbox" /><label for="_cbShowAreaPlaceSize">Show area Place size</label></div>',
            '<div id="divShowAreaPlaceSizeImperial"class="controls-container" style="padding-left:30px;"><input type="checkbox" id="_cbShowAreaPlaceSizeImperial" class="pieSettingsCheckbox" disabled /><label for ="_cbShowAreaPlaceSizeImperial"> Show imperial </label></div>',
            '<div id="divShowAreaPlaceSizeMetric" class="controls-container" style="padding-left:30px;"><input type="checkbox" id="_cbShowAreaPlaceSizeMetric" class="pieSettingsCheckbox" disabled /><label for ="_cbShowAreaPlaceSizeMetric"> Show metric</label></div>',
            '</div>',
            '<div class="controls-container" id="divShowLockButtonsRPP"><input type="checkbox" id="_cbShowLockButtonsRPP" class="pieSettingsCheckbox" /><label for="_cbShowLockButtonsRPP">Show lock buttons for RPPs</label></div>',
            '<div class="controls-container" id="divPlaceMenuCustomization">',
            '<b>Place Menu Customization</b></br>',
            buildItemOption(1),
            buildItemOption(2),
            buildItemOption(3),
            buildItemOption(4),
            buildItemOption(5),
            buildItemOption(6),
            buildItemOption(7),
            buildItemOption(8),
            buildItemOption(9),
            buildItemOption(10),
            buildItemOption(11),
            '</div>'

        ].join(' '));
        new WazeWrap.Interface.Tab('PIE', $section.html(), init2);
    }

    function buildNewPlaceList(){
        /*<div class="drawing-controls">
        <span class="drawing-control polygon secondary-control" title="Place (area)"></span>
        <span class="drawing-control main-control point" title="Place (point)"></span>
        </div>
        $('#pieItem1')[0].options[$('#pieItem1')[0].selectedIndex].innerHTML //get selected option text
        */
    }

    function init2(){
        //First load settings
        loadSettings();
        //Second set up event handlers
        $('#_cbShowAreaPlaceSize').change(function() {
            if(this.checked) {
                attachPlaceSizeHandlers();
                updatePlaceSizeDisplay();
                $('#_cbShowAreaPlaceSizeImperial')[0].disabled = false;
                $('#_cbShowAreaPlaceSizeMetric')[0].disabled = false;
            }
            else
            {
                removePlaceSizeHandlers();
                $('#AreaSize').remove();
                $('#_cbShowAreaPlaceSizeImperial')[0].disabled = true;
                $('#_cbShowAreaPlaceSizeMetric')[0].disabled = true;
            }
        });

        $('#_cbShowLockButtonsRPP').change(function() {
            if(this.checked) {
                attachRPPLockButtonHandlers();
            }
            else
            {
                $('#RPPOptionPlaceLockButtonsContainer').remove();
                W.selectionManager.events.unregister("selectionchanged", null, addLockButtons);
                W.model.actionManager.events.unregister("afterundoaction",null, addLockButtons);
                W.model.actionManager.events.unregister("afterclearactions",null, addLockButtons);
                W.model.actionManager.events.unregister("afteraction",null, addLockButtons);
            }
        });

        //Third load settings to interface
        setChecked('_cbShowAreaPlaceSize', settings.ShowAreaPlaceSize);
        setChecked('_cbShowAreaPlaceSizeImperial', settings.ShowAreaPlaceSizeImperial);
        setChecked('_cbShowAreaPlaceSizeMetric', settings.ShowAreaPlaceSizeMetric);
        setChecked('_cbShowLockButtonsRPP', settings.ShowLockButtonsRPP);
        if(settings.ShowAreaPlaceSize){
            $('#_cbShowAreaPlaceSizeImperial')[0].disabled = false;
            $('#_cbShowAreaPlaceSizeMetric')[0].disabled = false;
            attachPlaceSizeHandlers();
        }

        if(settings.ShowLockButtonsRPP)
            attachRPPLockButtonHandlers();

        $('.pieSettingsCheckbox').change(function() {
             var settingName = $(this)[0].id.substr(3);
            settings[settingName] = this.checked;
            saveSettings();
        });

        //Whenever a Place item is changed, read the settings and save to localStorage
        $('[id^="pieItem"]').change(function(){
            for(i=0;i<11;i++){
                settings.NewPlacesList[i] = $('#pieItem'+(i+1))[0].value;
            }
            saveSettings();
        });

        //Load settings into Place Customization list options
        for(i=0; i<11;i++)
            $('#pieItem'+(i+1))[0].value = settings.NewPlacesList[i];
    }

    function buildItemOption(itemNumber){
        var $section = $("<div>", {style:"padding:8px 16px", id:"piePlaceCat" + itemNumber});
        $section.html([
            'Item ',
            itemNumber,
            buildItemList(itemNumber),
            '</br>'
            ].join(' '));

        return $section.html();
    }

    function buildItemList(itemNumber){
        /*var yourSelect = document.getElementById( "your-select-id" );
        alert( yourSelect.options[ yourSelect.selectedIndex ].value )*/
        
        var $places = $("<div>");
        $places.html([
            '<select id="pieItem' + itemNumber + '">',
            '<option value="CAR_SERVICES" style="font-weight:bold;">Car Services</option>',
            '<option value="GAS_STATION">Gas Station</option>',
            '<option value="GARAGE_AUTOMOTIVE_SHOP">Garage / Automotive Shop</option>',
            '<option value="CAR_WASH">Car Wash</option>',
            '<option value="CHARGING_STATION">Charging Station</option>',
            '<option value="TRANSPORTATION" style="font-weight:bold;">Transportation</option>',
            '<option value="AIRPORT">Airport</option>',
            '<option value="BUS_STATION">Bus Station</option>',
            '<option value="FERRY_PIER">Ferry / Pier</option>',
            '<option value="SEAPORT_MARINA_HARBOR">Seaport / Marina / Harbor</option>',
            '<option value="SUBWAY_STATION">Subway Station</option>',
            '<option value="TRAIN_STATION">Train Station</option>',
            '<option value="BRIDGE">Bridge</option>',
            '<option value="TUNNEL">Tunnel</option>',
            '<option value="TAXI_STATION">Taxi Station</option>',
            '<option value="JUNCTION_INTERCHANGE">Junction / Interchange</option>',
            '<option value="PROFESSIONAL_AND_PUBLIC" style="font-weight:bold;">Professional and public</option>',
            '<option value="COLLEGE_UNIVERSITY">College / University</option>',
            '<option value="SCHOOL">School</option>',
            '<option value="CONVENTIONS_EVENT_CENTER">Conventions / Event Center</option>',
            '<option value="GOVERNMENT">Government</option>',
            '<option value="LIBRARY">Library</option>',
            '<option value="CITY_HALL">City Hall</option>',
            '<option value="ORGANIZATION_OR_ASSOCIATION">Organization or Association</option>',
            '<option value="COURTHOUSE">Courthouse</option>',
            '<option value="CEMETERY">Cemetery</option>',
            '<option value="FIRE_DEPARTMENT">Fire Department</option>',
            '<option value="POLICE_STATION">Police Station</option>',
            '<option value="MILITARY">Military</option>',
            '<option value="HOSPITAL_MEDICAL_CARE">Hospital / Medical Care</option>',
            '<option value="OFFICES">Offices</option>',
            '<option value="POST_OFFICE">Post Office</option>',
            '<option value="RELIGIOUS_CENTER">Religious Center</option>',
            '<option value="KINDERGARDEN">Kindergarden</option>',
            '<option value="FACTORY_INDUSTRIAL">Factory / Industrial</option>',
            '<option value="EMBASSY_CONSULATE">Embassy / Consulate</option>',
            '<option value="INFORMATION_POINT">Information Point</option>',
            '<option value="EMERGENCY_SHELTER">Emergency Shelter</option>',
            '<option value="SHOPPING_AND_SERVICES" style="font-weight:bold;">Shopping and services</option>',
            '<option value="ARTS_AND_CRAFTS">Arts & Crafts</option>',
            '<option value="BANK_FINANCIAL">Bank / Financial</option>',
            '<option value="SPORTING_GOODS">Sporting Goods</option>',
            '<option value="BOOKSTORE">Bookstore</option>',
            '<option value="PHOTOGRAPHY">Photography</option>',
            '<option value="CAR_DEALERSHIP">Car Dealership</option>',
            '<option value="FASHION_AND_CLOTHING">Fashion and Clothing</option>',
            '<option value="CONVENIENCE_STORE">Convenience Store</option>',
            '<option value="PERSONAL_CARE">Personal Care</option>',
            '<option value="DEPARTMENT_STORE">Department Store</option>',
            '<option value="PHARMACY">Pharmacy</option>',
            '<option value="ELECTRONICS">Electronics</option>',
            '<option value="FLOWERS">Flowers</option>',
            '<option value="FURNITURE_HOME_STORE">Furniture / Home Store</option>',
            '<option value="GIFTS">Gifts</option>',
            '<option value="GYM_FITNESS">Gym / Fitness</option>',
            '<option value="SWIMMING_POOL">Swimming Pool</option>',
            '<option value="HARDWARE_STORE">Hardware Store</option>',
            '<option value="MARKET">Market</option>',
            '<option value="SUPERMARKET_GROCERY">Supermarket / Grocery</option>',
            '<option value="JEWELRY">Jewelry</option>',
            '<option value="LAUNDRY_DRY_CLEAN">Laundry / Dry Clean</option>',
            '<option value="SHOPPING_CENTER">Shopping Center</option>',
            '<option value="MUSIC_STORE">Music Store</option>',
            '<option value="PET_STORE_VETERINARIAN_SERVICES">Pet Store / Veterinarian Services</option>',
            '<option value="TOY_STORE">Toy Store</option>',
            '<option value="TRAVEL_AGENCY">Travel Agency</option>',
            '<option value="ATM">ATM</option>',
            '<option value="CURRENCY_EXCHANGE">Currency Exchange</option>',
            '<option value="CAR_RENTAL">Car Rental</option>',
            '<option value="FOOD_AND_DRINK" style="font-weight:bold;">Food and Drink</option>',
            '<option value="RESTAURANT">Restaurant</option>',
            '<option value="BAKERY">Bakery</option>',
            '<option value="DESSERT">Dessert</option>',
            '<option value="CAFE">Cafe</option>',
            '<option value="FAST_FOOD">Fast Food</option>',
            '<option value="FOOD_COURT">Food Court</option>',
            '<option value="BAR">Bar</option>',
            '<option value="ICE_CREAM">Ice Cream</option>',
            '<option value="CULTURE_AND_ENTERTAINEMENT" style="font-weight:bold;">Culture & Entertainment</option>',
            '<option value="ART_GALLERY">Art Gallery</option>',
            '<option value="CASINO">Casino</option>',
            '<option value="CLUB">Club</option>',
            '<option value="TOURIST_ATTRACTION_HISTORIC_SITE">Tourist Attraction / History Site</option>',
            '<option value="MOVIE_THEATER">Movie Theater</option>',
            '<option value="MUSEUM">Museum</option>',
            '<option value="MUSIC_VENUE">Music Venue</option>',
            '<option value="PERFORMING_ARTS_VENUE">Performing Arts Venue</option>',
            '<option value="GAME_CLUB">Game Club</option>',
            '<option value="STADIUM_ARENA">Stadium / Arena</option>',
            '<option value="THEME_PARK">Theme Park</option>',
            '<option value="ZOO_AQUARIUM">Zoo / Aquarium</option>',
            '<option value="RACING_TRACK">Racing Track</option>',
            '<option value="THEATER">Theater</option>',
            '<option value="OTHER" style="font-weight:bold;">Other</option>',
            '<option value="CONSTRUCTION_SITE">Construction Site</option>',
            '<option value="LODGING" style="font-weight:bold;">Lodging</option>',
            '<option value="HOTEL">Hotel</option>',
            '<option value="HOSTEL">Hostel</option>',
            '<option value="CAMPING_TRAILER_PARK">Camping / Trailer Park</option>',
            '<option value="COTTAGE_CABIN">Cottage / Cabin</option>',
            '<option value="BED_AND_BREAKFAST">Bed & Breakfast</option>',
            '<option value="OUTDOORS" style="font-weight:bold;">Outdoors</option>',
            '<option value="PARK">Park</option>',
            '<option value="PLAYGROUND">Playground</option>',
            '<option value="BEACH">Beach</option>',
            '<option value="SPORTS_COURT">Sports Court</option>',
            '<option value="GOLF_COURSE">Golf Course</option>',
            '<option value="PLAZA">Plaza</option>',
            '<option value="PROMENADE">Promenade</option>',
            '<option value="POOL">Pool</option>',
            '<option value="SCENIC_LOOKOUT_VIEWPOINT">Scenic Lookout / Viewpoint</option>',
            '<option value="SKI_AREA">Ski Area</option>',
            '<option value="NATURAL_FEATURES" style="font-weight:bold;">Natural Features</option>',
            '<option value="ISLAND">Island</option>',
            '<option value="SEA_LAKE_POOL">Sea / Lake / Pool</option>',
            '<option value="RIVER_STREAM">River / Stream</option>',
            '<option value="FOREST_GROVE">Forest / Grove</option>',
            '<option value="FARM">Farm</option>',
            '<option value="CANAL">Canal</option>',
            '<option value="SWAMP_MARSH">Swamp / Marsh</option>',
            '<option value="DAM">Dam</option>',
            '<option value="PARKING_LOT" style="font-weight:bold;">Parking Lot</option>',
            '<option value="RESIDENCE_HOME" style="font-weight:bold;">Residential</option>',
            '</select>'
            ].join(' '));

        return $places.html();
    }

    function attachRPPLockButtonHandlers(){
        $('#RPPOptionPlaceLockButtonsContainer').remove();
        W.selectionManager.events.register("selectionchanged", null, addLockButtons);
        W.model.actionManager.events.register("afterundoaction",null, addLockButtons);
        W.model.actionManager.events.register("afterclearactions",null, addLockButtons);
        W.model.actionManager.events.register("afteraction",null, addLockButtons);
    }

    function attachPlaceSizeHandlers(){
        W.selectionManager.events.register("selectionchanged", null, updatePlaceSizeDisplay);
        W.model.actionManager.events.register("afteraction",null, updatePlaceSizeDisplay);
        W.model.actionManager.events.register("afterundoaction",null, updatePlaceSizeDisplay);
        W.model.actionManager.events.register("afterclearactions",null, updatePlaceSizeDisplay);
        W.model.actionManager.events.register("noActions",null, noActions);
        updatePlaceSizeDisplay();
    }

    function removePlaceSizeHandlers(){
        W.selectionManager.events.unregister("selectionchanged", null, updatePlaceSizeDisplay);
        W.model.actionManager.events.unregister("afteraction",null, updatePlaceSizeDisplay);
        W.model.actionManager.events.unregister("afterundoaction",null, updatePlaceSizeDisplay);
        W.model.actionManager.events.unregister("afterclearactions",null, updatePlaceSizeDisplay);
        W.model.actionManager.events.unregister("noActions",null, noActions);
    }

    function isChecked(checkboxId) {
        return $('#' + checkboxId).is(':checked');
    }

    function setChecked(checkboxId, checked) {
        $('#' + checkboxId).prop('checked', checked);
    }

    function noActions(){
        setTimeout(updatePlaceSizeDisplay, 100 ); //have to put in a delay for when the user uses undo to clear all actions - WME updates on top of my changes otherwise.
    }

    function updatePlaceSizeDisplay(){
        var count = W.selectionManager.selectedItems.length;
        var metersArea = 0;
        var bold = false;
        if(count === 1){
           var venue = W.selectionManager.selectedItems[0];
           var isArea = venue.geometry.toString().match(/^POLYGON/);
           //var isPoint = venue.geometry.toString().match(/^POINT/);

            if(venue.model.type === "venue" && isArea){
                if($('#AreaSize'))
                    $('#AreaSize').remove();
                metersArea = W.selectionManager.selectedItems[0].model.geometry.getGeodesicArea(W.map.getProjectionObject());

                if(metersArea > 0 && isArea){
                    var ftArea = Math.round(metersArea * 10.76391 *100)/100;

                    var list = $('#landmark-edit-general > ul')[0];
                    var newList = document.createElement("UL");
                    newList.id = "AreaSize";

                    var newItem = document.createElement("LI");
                    if(isChecked("_cbShowAreaPlaceSizeMetric")){
                        newItem.innerHTML = "Area: " + metersArea.toFixed(2) + " m<sup>2</sup>";
                        newList.append(newItem);
                    }

                    if(isChecked("_cbShowAreaPlaceSizeImperial")){
                        newItem = document.createElement("LI");
                        newItem.innerHTML = "Area: " + ftArea.toFixed(2) + " ft<sup>2</sup>";
                        newList.append(newItem);
                    }
                    if(metersArea < 500){
                        newItem = document.createElement("LI");
                        newItem.innerHTML = "<span style='color:red; font-weight:bold;'>Places smaller than 500 m<sup>2</sup>/5382 ft<sup>2</sup> will not show in the client</span>";
                        newList.append(newItem);
                    }
                    list.before(newList);

                    $('#AreaSize').addClass("list-unstyled");
                    $('#AreaSize').addClass("additional-attributes");
                }
            }
        }
    }

    function loadSettings() {
        var loadedSettings = $.parseJSON(localStorage.getItem("WMEPIE_Settings"));
        var defaultSettings = {
            ShowAreaPlaceSize: false,
            ShowAreaPlaceSizeImperial: false,
            ShowAreaPlaceSizeMetric: false,
            ShowLockButtonsRPP: true,
            NewPlacesList: W.Config.venues.categories.clone()
        };
        settings = loadedSettings ? loadedSettings : defaultSettings;
        for (var prop in defaultSettings) {
            if (!settings.hasOwnProperty(prop))
                settings[prop] = defaultSettings[prop];
        }

        if(settings.ShowAreaPlaceSizeImperial === false && settings.ShowAreaPlaceSizeMetric === false)
            if(Waze.prefs.attributes.isImperial)
                settings.ShowAreaPlaceSizeImperial = true;
            else
                settings.ShowAreaPlaceSizeMetric = true;
    }

     function saveSettings() {
        if (localStorage) {
            var localsettings = {
                ShowAreaPlaceSize: settings.ShowAreaPlaceSize,
                ShowAreaPlaceSizeImperial: settings.ShowAreaPlaceSizeImperial,
                ShowAreaPlaceSizeMetric: settings.ShowAreaPlaceSizeMetric,
                ShowLockButtonsRPP: settings.ShowLockButtonsRPP,
                NewPlacesList: settings.NewPlacesList
            };

            localStorage.setItem("WMEPIE_Settings", JSON.stringify(localsettings));
        }
    }

    //Using the same display for lock buttons as ClickSaver (with permission from MapoMatic) - thanks MoM!
    function addLockButtons() {
        if(W.selectionManager.selectedItems.length > 0){
            var item = W.selectionManager.selectedItems[0];
            var isRPP = (item.model.type === "venue" && item.model.attributes.residential === true);

            if(isRPP){
                console.log("adding!!!");
                var attr = item.model.attributes;
                var autoRank = attr.rank;
                var manualRank = attr.lockRank;
                var firstManualRank = manualRank;
                var userRank = WazeWrap.User.Rank() - 1;
                var maxAutoRank = autoRank;
                var disabled = false;

                var $div = $('#RPPOptionPlaceLockButtonsContainer');
                $div.remove();
                $div = $('<div>',{id:'RPPOptionPlaceLockButtonsContainer',style:'margin-bottom:5px;'});
                $div.append('<label class="control-label">Lock</label>');
                var btnInfos = [];

                for(var iBtn=0;iBtn<=6;iBtn++){btnInfos.push({r:iBtn,val:iBtn});}
                btnInfos.forEach(function(btnInfo){
                    var selected = (btnInfo.val === manualRank);
                    disabled = userRank < btnInfo.val;
                    if (btnInfo.val !== 6) {
                        $div.append(
                            $('<div>', {
                                class:'btn btn-lh' + (selected ? ' btn-lh-selected':'') + (btnInfo.r < 6 & (userRank < btnInfo.r || disabled) ? ' disabled' : '')
                            })
                            .text(btnInfo.hasOwnProperty('title') ? btnInfo.title : btnInfo.r + 1)
                            .data('val',btnInfo.hasOwnProperty('val') ? btnInfo.val : btnInfo.r + 1)
                            .hover(function() {})
                            .click(function() {
                                if((userRank >= $(this).data('val')) && (btnInfo.r < 6)) {
                                    W.model.actionManager.add(new UpdateObject(item.model,{lockRank:($(this).data('val'))}));
                                    addLockButtons();
                                }
                            })
                        );
                    }
                });
                $('#landmark-edit-general > div').after($div);
            }
        }
    }

    function listPlaces(){
        var category = "";
        for(i=0; i<W.Config.venues.categories.length; i++){
            category = W.Config.venues.categories[i];
            console.log(category + " Main");
            var subCategories = W.Config.venues.subcategories[category];
            for(var j=0; j<subCategories.length;j++){
                console.log(subCategories[j]);
            }
        }
    }
})();