// ==UserScript== // @name WME Junction Angle Info (development version) // @namespace https://github.com/milkboy/WME-ja // @description Show the angle between two selected (and connected) segments // @include /^https:\/\/(www|beta)\.waze\.com\/(?!user\/)(.{2,6}\/)?editor.*$/ // @updateURL https://github.com/milkboy/WME-ja/raw/master/wme_junctionangle.user.js // @version 1.15.0 // @grant none // @copyright 2019 Michael Wikberg // @license CC-BY-NC-SA // @icon data:image/png;base64,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 // @nocompat // ==/UserScript== /** * Copyright 2019 Michael Wikberg * WME Junction Angle Info extension is licensed under a Creative Commons * Attribution-NonCommercial-ShareAlike 3.0 Unported License. * * Contributions by: * 2014 Paweł Pyrczak "tkr85" * 2014 "AlanOfTheBerg" * 2014 "berestovskyy" * 2015 "FZ69617" * 2015 "wlodek76" * 2016 Sergey Kuznetsov "WazeRus" (Russian translation) * 2016 "MajkiiTelini" Czech translation */ /*jshint eqnull:true, nonew:true, nomen:true, curly:true, latedef:false, unused:strict, noarg:true, loopfunc:true */ /*jshint trailing:true, forin:true, noempty:true, maxparams:7, maxerr:100, eqeqeq:true, strict:true, undef:true */ /*jshint bitwise:true, newcap:true, immed:true, onevar:true, browser:true, nonbsp:true, freeze:true */ /*global I18n, console, $*/ function run_ja() { "use strict"; /* * First some variable and enumeration definitions */ var ja_version = "1.15.0"; var ja_debug = 1; //0: no output, 1: basic info, 2: debug 3: verbose debug, 4: insane debug var ja_last_restart = 0, ja_roundabout_points = [], ja_options = {}, ja_mapLayer; var ja_TURN_ANGLE = 45.04; //Turn vs. keep angle specified in Wiki. var ja_U_TURN_ANGLE = 168.24; //U-Turn angle based on map experiments. var ja_GRAY_ZONE = 0.5; //Gray zone angle intended to prevent from irregularities observed on map. var ja_OVERLAPPING_ANGLE = 0.666; //Experimentally measured overlapping angle. var ja_routing_type = { BC: "junction_none", KEEP: "junction_keep", KEEP_LEFT: "junction_keep_left", KEEP_RIGHT: "junction_keep_right", TURN: "junction_turn", EXIT: "junction_exit", EXIT_LEFT: "junction_exit_left", EXIT_RIGHT: "junction_exit_right", U_TURN: "junction_u_turn", PROBLEM: "junction_problem", NO_TURN: "junction_no_turn", NO_U_TURN: "junction_no_u_turn", ROUNDABOUT: "junction_roundabout", ROUNDABOUT_EXIT: "junction_roundabout_exit" }; var ja_road_type = { //Streets STREET: 1, PRIMARY_STREET: 2, //Highways RAMP: 4, FREEWAY: 3, MAJOR_HIGHWAY: 6, MINOR_HIGHWAY: 7, //Other drivable DIRT_ROAD: 8, FERRY: 14, PRIVATE_ROAD: 17, PARKING_LOT_ROAD: 20, //Non-drivable WALKING_TRAIL: 5, PEDESTRIAN_BOARDWALK: 10, STAIRWAY: 16, RAILROAD: 18, RUNWAY: 19 }; var ja_vehicle_types = { TRUCK: 1, PUBLIC: 2, TAXI: 4, BUS: 8, HOV2: 16, HOV3: 32, RV: 64, TOWING: 128, MOTORBIKE: 256, PRIVATE: 512, HAZ: 1024 }; var ja_settings = { defaultOn: { elementType: "checkbox", elementId: "_jaCbShowLayer", defaultValue: true }, angleMode: { elementType: "select", elementId: "_jaSelAngleMode", defaultValue: "aDeparture", options: ["aAbsolute", "aDeparture"]}, angleDisplay: { elementType: "select", elementId: "_jaSelAngleDisplay", defaultValue: "displayFancy", options: ["displayFancy", "displaySimple"]}, angleDisplayArrows: { elementType: "select", elementId: "_jaSelAngleDisplayArrows", defaultValue: "<>", options: ["<>", "⇦⇨", "⇐⇒", "←→", "⇐⇒⇖⇗", "←→↖↗"]}, guess: { elementType: "checkbox", elementId: "_jaCbGuessRouting", defaultValue: true }, noInstructionColor: { elementType: "color", elementId: "_jaTbNoInstructionColor", defaultValue: "#ffffff", group: "guess"}, keepInstructionColor: { elementType: "color", elementId: "_jaTbKeepInstructionColor", defaultValue: "#cbff84", group: "guess"}, exitInstructionColor: { elementType: "color", elementId: "_jaTbExitInstructionColor", defaultValue: "#6cb5ff", group: "guess"}, turnInstructionColor: { elementType: "color", elementId: "_jaTbTurnInstructionColor", defaultValue: "#4cc600", group: "guess"}, uTurnInstructionColor: { elementType: "color", elementId: "_jaTbUTurnInstructionColor", defaultValue: "#b66cff", group: "guess"}, noTurnColor: { elementType: "color", elementId: "_jaTbNoTurnColor", defaultValue: "#a0a0a0", group: "guess"}, problemColor: { elementType: "color", elementId: "_jaTbProblemColor", defaultValue: "#feed40", group: "guess"}, roundaboutOverlayDisplay: { elementType: "select", elementId: "_jaSelRoundaboutOverlayDisplay", defaultValue: "rOverNever", options: ["rOverNever","rOverSelected","rOverAlways"]}, roundaboutOverlayColor: { elementType: "color", elementId: "_jaTbRoundaboutOverlayColor", defaultValue: "#aa0000", group: "roundaboutOverlayDisplay"}, roundaboutColor: { elementType: "color", elementId: "_jaTbRoundaboutColor", defaultValue: "#ff8000", group: "roundaboutOverlayDisplay"}, decimals: { elementType: "number", elementId: "_jaTbDecimals", defaultValue: 0, min: 0, max: 2}, pointSize: { elementType: "number", elementId: "_jaTbPointSize", defaultValue: 12, min: 6, max: 20} }; var ja_arrow = { get: function(at) { var arrows = ja_getOption("angleDisplayArrows"); return arrows[at % arrows.length]; }, left: function() { return this.get(0); }, right: function() { return this.get(1); }, left_up: function() { return this.get(2); }, right_up: function() { return this.get(3); } }; function getWaze() { if(window.wrappedJSObject) { return window.wrappedJSOnject.W; } return window.W; } /* * Main logic functions */ function junctionangle_init() { var i, ja_select_option, navTabs, tabContent; var ja_settings_dom = document.createElement("div"); var ja_settings_dom_panel = document.createElement("div"); var ja_settings_dom_content = document.createElement("div"); var ja_settings_header = document.createElement('h4'); var style = document.createElement('style'); var form = document.createElement('form'); var section = document.createElement('div'); var ja_reset_button = document.createElement('button'); var userTabs = document.getElementById('user-info'); var ja_info = document.createElement('ul'); var ja_version_elem = document.createElement('li'); var jatab = document.createElement('li'); //Listen for selected nodes change event getWaze().selectionManager.events.register("selectionchanged", null, ja_calculate); //Temporary workaround. Beta editor changed the event listener logic, but live is still using the old version //if-else should be removed once not needed anymore if("events" in getWaze().model.segments) { //Live getWaze().model.segments.events.on({ "objectschanged": ja_calculate, "objectsremoved": ja_calculate }); getWaze().model.nodes.events.on({ "objectschanged": ja_calculate, "objectsremoved": ja_calculate }); } else if("_events" in getWaze().model.segments) { //Beta editor getWaze().model.segments.on({ "objectschanged": ja_calculate, "objectsremoved": ja_calculate }); getWaze().model.nodes.on({ "objectschanged": ja_calculate, "objectsremoved": ja_calculate }); } //Recalculate on zoom end also getWaze().map.events.register("zoomend", null, ja_calculate); ja_load(); ja_loadTranslations(); /** * Add JAI tab configuration options */ ja_settings_dom_panel.className = "side-panel-section"; ja_settings_dom_content.className = "tab-content"; ja_settings_header.appendChild(document.createTextNode(ja_getMessage("settingsTitle"))); ja_settings_dom_content.appendChild(ja_settings_header); style.appendChild(document.createTextNode(function () {/* #jaOptions > *:first-child { margin-top: 1em; } #jaOptions * { vertical-align: middle; } #jaOptions label { display: inline; } #jaOptions input, select { display: inline; margin-right: 7px; box-sizing: border-box; border: 1px solid #cccccc; border-radius: 5px; padding: 3px; } #jaOptions input[type="number"] { width: 4em; padding: 6px; } #jaOptions input[type="color"] { width: 15%; height: 2em; padding: 4px; } @supports (-webkit-appearance:none) { #jaOptions input[type="color"] { padding: 0px 2px 0px 2px; } } #jaOptions .disabled { position: relative; } #jaOptions .disabled:after { content: " "; z-index: 10; display: block; position: absolute; height: 100%; top: 0; left: 0; right: 0; background: rgba(255, 255, 255, 0.666); } */}.toString().match(/[^]*\/\*([^]*)\*\/\}$/)[1])); section.className = "form-group"; form.className = "attributes-form side-panel-section"; section.id = "jaOptions"; ja_log("---------- Creating settings HTML ----------", 2); Object.getOwnPropertyNames(ja_settings).forEach(function (a) { var setting = ja_settings[a]; var ja_controls_container = document.createElement('div'); var ja_input = document.createElement('input'); var ja_label = document.createElement('label'); ja_controls_container.className = "controls-container"; ja_input.type = setting.elementType; switch (setting.elementType) { case 'color': ja_input.id = setting.elementId; ja_controls_container.appendChild(ja_input); break; case 'number': ja_input.id = setting.elementId; ja_input.setAttribute("min", setting.min); ja_input.setAttribute("max", setting.max); ja_controls_container.appendChild(ja_input); break; /* case 'text': ja_input.id = setting.elementId; ja_input.size = (setting.max ? setting.max : 8); ja_input.maxlength = (setting.max ? setting.max : 7); ja_controls_container.appendChild(ja_input); break; */ case 'checkbox': ja_input.id = setting.elementId; ja_controls_container.appendChild(ja_input); break; case 'select': ja_input = document.createElement('select'); //Override with