// ==UserScript== // @name WME Place Interface Enhancements // @namespace https://greasyfork.org/users/30701-justins83-waze // @version 0.7.3 // @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 // @downloadURL none // ==/UserScript== var UpdateObject, MultiAction; (function() { 'use strict'; var settings = {}; var placeMenuSelector = "#edit-buttons > div > div.toolbar-button.waze-icon-place.toolbar-submenu.toolbar-group.toolbar-group-venues.ItemInactive > menu"; var pointStyle = { pointRadius: 6, fillOpacity: 0, strokeColor: '#00ece3', strokeWidth: '2', strokeLinecap: 'round' }; var layerName = "WME PIE"; var newPlaceLayer; var placementMode = false; var drawPoly; // 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 = $("
", {style:"padding:8px 16px", id:"WMEPIESettings"}); $section.html([ '

WME Place Interface Enhancements

', '
', '
', '
', '
', '
', '
', '

', 'Zoom
', 'New Places
', '
', '
', '
', '
Lock level
', '
', 'Place Menu Customization
', buildItemOption(1), buildItemOption(2), buildItemOption(3), buildItemOption(4), buildItemOption(5), buildItemOption(6), buildItemOption(7), buildItemOption(8), buildItemOption(9), buildItemOption(10), buildItemOption(11), '
' ].join(' ')); UpdateObject = require("Waze/Action/UpdateObject"); MultiAction = require("Waze/Action/MultiAction"); newPlaceLayer = new OL.Layer.Vector(layerName,{displayInLayerSwitcher: false}); W.map.addLayer(newPlaceLayer); injectCss(); new WazeWrap.Interface.Tab('PIE', $section.html(), init2); } function buildNewPlaceList(){ //Clear out the Places menu $('#edit-buttons > div > div.toolbar-button.waze-icon-place.toolbar-submenu.toolbar-group.toolbar-group-venues.ItemInactive > menu').empty(); var cat = ""; var i; for(i=0;i<11;i++){ cat = $('#pieItem' + (i+1))[0].value; if(cat !== "PARKING_LOT" && cat !== "RESIDENCE_HOME") $(placeMenuSelector).append('
' + $('#pieItem' + (i+1))[0].options[$('#pieItem' + (i+1))[0].selectedIndex].innerHTML + '
'); else{ if(cat === "RESIDENCE_HOME") //force point $(placeMenuSelector).append('
' + $('#pieItem' + (i+1))[0].options[$('#pieItem' + (i+1))[0].selectedIndex].innerHTML + '
'); else //Parking lot - force area $(placeMenuSelector).append('
' + $('#pieItem' + (i+1))[0].options[$('#pieItem' + (i+1))[0].selectedIndex].innerHTML + '
'); } } $('[id^="piePlaceMainItem"]').click(function(e){ startPlacementMode($('#' + this.id).data("category"), true); }); $('[id^="piePlaceAreaItem"]').click(function(e){ e.stopPropagation(); startPlacementMode($('#' + this.id).data("category"), false); }); } function init2(){ //Load settings loadSettings(); //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 { $('#pieRPPLockButtonsContainer').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); } }); $('#_cbShowPlaceLocatorCrosshair').change(function(){ if(this.checked){ W.selectionManager.events.register("selectionchanged", null, ShowPlaceLocatorCrosshair); W.model.actionManager.events.register("afterundoaction",null, ShowPlaceLocatorCrosshair); W.model.actionManager.events.register("afterclearactions",null, ShowPlaceLocatorCrosshair); W.model.actionManager.events.register("afteraction",null, ShowPlaceLocatorCrosshair); } else{ W.selectionManager.events.unregister("selectionchanged", null, ShowPlaceLocatorCrosshair); W.model.actionManager.events.unregister("afterundoaction",null, ShowPlaceLocatorCrosshair); W.model.actionManager.events.unregister("afterclearactions",null, ShowPlaceLocatorCrosshair); W.model.actionManager.events.unregister("afteraction",null, ShowPlaceLocatorCrosshair); } }); //Load settings to interface setChecked('_cbShowAreaPlaceSize', settings.ShowAreaPlaceSize); setChecked('_cbShowAreaPlaceSizeImperial', settings.ShowAreaPlaceSizeImperial); setChecked('_cbShowAreaPlaceSizeMetric', settings.ShowAreaPlaceSizeMetric); setChecked('_cbShowLockButtonsRPP', settings.ShowLockButtonsRPP); setChecked('_cbEditRPPAfterCreated', settings.EditRPPAfterCreated); setChecked('_cbUseStreetFromClosestSeg', settings.UseStreetFromClosestSeg); setChecked('_cbUseCityFromClosestSeg', settings.UseCityFromClosestSeg); setChecked('_cbShowPlaceLocatorCrosshair', settings.ShowPlaceLocatorCrosshair); $('#piePlaceZoom')[0].value = settings.PlaceZoom; $('#pieDefaultLockLevel')[0].value = settings.DefaultLockLevel; if(settings.ShowAreaPlaceSize){ $('#_cbShowAreaPlaceSizeImperial')[0].disabled = false; $('#_cbShowAreaPlaceSizeMetric')[0].disabled = false; attachPlaceSizeHandlers(); } if(settings.ShowPlaceLocatorCrosshair){ W.selectionManager.events.register("selectionchanged", null, ShowPlaceLocatorCrosshair); W.model.actionManager.events.register("afterundoaction",null, ShowPlaceLocatorCrosshair); W.model.actionManager.events.register("afterclearactions",null, ShowPlaceLocatorCrosshair); W.model.actionManager.events.register("afteraction",null, ShowPlaceLocatorCrosshair); ShowPlaceLocatorCrosshair(); //in case the user opened a PL with a Place selected } if(settings.ShowLockButtonsRPP) attachRPPLockButtonHandlers(); $('.pieSettingsCheckbox').change(function() { var settingName = $(this)[0].id.substr(3); settings[settingName] = this.checked; saveSettings(); }); $('#piePlaceZoom').change(function(){ var settingName = $(this)[0].id.substr(3); settings[settingName] = $(this)[0].value; saveSettings(); }); $('#pieDefaultLockLevel').change(function(){ settings[$(this)[0].id.substr(3)] = $(this)[0].value; saveSettings(); }); var i; //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(); buildNewPlaceList(); }); //Load settings into Place Customization list options for(i=0; i<11;i++) $('#pieItem'+(i+1))[0].value = settings.NewPlacesList[i]; //Build our new menu buildNewPlaceList(); new WazeWrap.Interface.Shortcut('CreateResidentialPlaceShortcut', 'Creates a resdiential Place point', 'wmepie', 'Place Interface Enhancements', settings.CreateResidentialPlaceShortcut, function(){startPlacementMode("RESIDENCE_HOME", true);}, null).add(); new WazeWrap.Interface.Shortcut('CreateParkingLotShortcut', 'Creates a parking lot Place', 'wmepie', 'Place Interface Enhancements', settings.CreateParkingLotShortcut, function(){startPlacementMode("PARKING_LOT", false);}, null).add(); window.addEventListener("beforeunload", function() { saveSettings(); }, false); } var areaCategory = ""; function startPlacementMode(category, isPoint){ $('#edit-buttons > div > div.toolbar-button.waze-icon-place.toolbar-submenu.toolbar-group.toolbar-group-venues.ItemInactive').removeClass("open"); if(isPoint){ $("#map").on('mousemove', MouseMoveHandler); $("#map").click(function(){endPlacementMode(category, isPoint);}); } else{ areaCategory = category; var polyDrawFeatureOptions = {callbacks : {"done": doneHandler}}; drawPoly = new OpenLayers.Control.DrawFeature(newPlaceLayer, OpenLayers.Handler.Polygon, polyDrawFeatureOptions); W.map.addControl(drawPoly); drawPoly.activate(); } document.addEventListener('keyup', keyUpHandler, false); } function doneHandler(geom){ drawPoly.destroy(); createPlace(geom, areaCategory, false); } function keyUpHandler(e){ if (e.keyCode == 27){ disablePlacementMode(); if(drawPoly !== "undefined") drawPoly.destroy(); } else if(e.keyCode == 90 && e.ctrlKey) drawPoly.undo(); else if(e.keyCode == 89 && e.ctrlKey) drawPoly.redo(); else if(e.keyCode == 13) drawPoly.finishSketch(); } function disablePlacementMode(){ $("#map").off('click');//, endPlacementMode); $("#map").off('mousemove', MouseMoveHandler); clearLayer(); document.removeEventListener('keyup', keyUpHandler); } function endPlacementMode(category, isPoint){ disablePlacementMode(); createPlace(getMousePos900913(), category, isPoint); } function getMousePos900913(){ var mousePosition = $('.WazeControlMousePosition').text().split(" "); return WazeWrap.Geometry.ConvertTo900913(mousePosition[0], mousePosition[1]); } function MouseMoveHandler(e){ clearLayer(); drawCircle(getMousePos900913()); } function clearLayer() { var layer = W.map.getLayersByName(layerName)[0]; layer.removeAllFeatures(); } function drawCircle(e){ var pointFeature = new OL.Feature.Vector(new OL.Geometry.Point(e.lon, e.lat), {}, pointStyle); W.map.getLayersByName(layerName)[0].addFeatures([pointFeature]); } function createPlace(pos, category, isPoint){ var PlaceObject = require("Waze/Feature/Vector/Landmark"); var AddPlace = require("Waze/Action/AddLandmark"); var multiaction = new MultiAction(); multiaction.setModel(W.model); var NewPlace = new PlaceObject(); if(isPoint) NewPlace.geometry = new OL.Geometry.Point(pos.lon, pos.lat); else{ var points = []; var i; for(i=0;i 0) { $('.edit-button').trigger("click"); $('.house-number:first').focus(); } else if (rppTries < 1000) { console.log("not found"); setTimeout(function () {editRPPAddress(rppTries++);}, 200); } } function buildItemOption(itemNumber){ var $section = $("
", {style:"padding:8px 16px", id:"piePlaceCat" + itemNumber}); $section.html([ 'Item ', itemNumber, buildItemList(itemNumber), '
' ].join(' ')); return $section.html(); } function buildLockLevelsList(){ var $lockLevels = $("
"); for(var i=0;i" + (i+1) + ""); } return $lockLevels.html(); } function buildItemList(itemNumber){ var $places = $("
"); $places.html([ '' ].join(' ')); return $places.html(); } function attachRPPLockButtonHandlers(){ $('#pieRPPLockButtonsContainer').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 ShowPlaceLocatorCrosshair(){ $('#pieCrosshairs').remove(); if(W.selectionManager.selectedItems.length > 0){ if(W.selectionManager.selectedItems[0].model.type === "venue"){ var panelWidth = $('#landmark-edit-general').width(); var $crosshairs = $('
'); $('#landmark-edit-general > form > div:nth-child(1) > i').after($crosshairs); $('#pieCrosshairs').click(function(){ CenterOnPlace(W.selectionManager.selectedItems[0].model, settings.PlaceZoom); }); } } } function CenterOnPlace(venue, zoom){ var centroid = venue.geometry.getCentroid(); W.map.setCenter([centroid.x, centroid.y], zoom); } 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) + " m2"; newList.appendChild(newItem); } if(isChecked("_cbShowAreaPlaceSizeImperial")){ newItem = document.createElement("LI"); newItem.innerHTML = "Area: " + ftArea.toFixed(2) + " ft2"; newList.appendChild(newItem); } if(metersArea < 500){ newItem = document.createElement("LI"); newItem.innerHTML = "Places smaller than 500 m2/5382 ft2 will not show in the client"; newList.appendChild(newItem); } if(list.before != null) list.before(newList); else{ var parent = $('#landmark-edit-general > ul')[0].parentNode; parent.insertBefore(newList,$('#landmark-edit-general > ul')[0]); } $('#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(), EditRPPAfterCreated: false, UseStreetFromClosestSeg: false, UseCityFromClosestSeg: false, ShowPlaceLocatorCrosshair: false, PlaceZoom: 6, DefaultLockLevel: 0, CreateResidentialPlaceShortcut: "A+r", CreateParkingLotShortcut: "A+p" }; 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, EditRPPAfterCreated: settings.EditRPPAfterCreated, UseStreetFromClosestSeg: settings.UseStreetFromClosestSeg, UseCityFromClosestSeg: settings.UseCityFromClosestSeg, ShowPlaceLocatorCrosshair: settings.ShowPlaceLocatorCrosshair, PlaceZoom: settings.PlaceZoom, DefaultLockLevel: settings.DefaultLockLevel, CreateResidentialPlaceShortcut: settings.CreateResidentialPlaceShortcut, CreateParkingLotShortcut: settings.CreateParkingLotShortcut }; for (var name in Waze.accelerators.Actions) { var TempKeys = ""; if (Waze.accelerators.Actions[name].group == 'wmepie') { console.log(name); if (Waze.accelerators.Actions[name].shortcut) { if (Waze.accelerators.Actions[name].shortcut.altKey === true) { TempKeys += 'A'; } if (Waze.accelerators.Actions[name].shortcut.shiftKey === true) { TempKeys += 'S'; } if (Waze.accelerators.Actions[name].shortcut.ctrlKey === true) { TempKeys += 'C'; } if (TempKeys !== "") { TempKeys += '+'; } if (Waze.accelerators.Actions[name].shortcut.keyCode) { TempKeys += Waze.accelerators.Actions[name].shortcut.keyCode; } } else { TempKeys = "-1"; } localsettings[name] = TempKeys; //var ShortcutRegisterObj = {}; //ShortcutRegisterObj[TempKeys] = Waze.accelerators.Actions[name].id; //TempToSave[TempToSave.length] = ShortcutRegisterObj; } } //localStorage[ScriptName + 'KBS'] = JSON.stringify(TempToSave); 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){ 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 = $('#pieRPPLockButtonsContainer'); $div.remove(); $div = $('
',{id:'pieRPPLockButtonsContainer',style:'margin-bottom:5px;'}); $div.append(''); 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( $('
', { 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 injectCss() { var css = [ // Lock button formatting '.btn-lh {cursor:pointer;padding:1px 6px;height:22px;border:solid 1px #c1c1c1;margin-right:3px;}', '.btn.btn-lh.btn-lh-selected {background-color:#6999ae;color:white}', '.btn.btn-lh.btn-lh-selected:hover {color:white}', '.btn.btn-lh.disabled {color:#909090;background-color:#f7f7f7;}', '.btn.btn-lh.btn-lh-selected.disabled {color:white;background-color:#6999ae;}' ].join(' '); $('').appendTo('head'); } function listPlaces(){ var category = ""; for(i=0; i