WME Color Speeds

Adds colors to road segments to show their speed

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

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

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

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

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

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

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

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

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

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

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

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

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

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

/* eslint-disable max-len */
// ==UserScript==
// @name             WME Color Speeds
// @name:fr          WME Color Speeds
// @version          2025.02.04.01
// @description      Adds colors to road segments to show their speed
// @description:fr   Colorisation des segments selon leurs vitesses.
// @include          https://www.waze.com/editor*
// @include          https://www.waze.com/*/editor*
// @include          https://beta.waze.com/editor*
// @include          https://beta.waze.com/*/editor*
// @exclude          https://www.waze.com/user*
// @exclude          https://www.waze.com/*/user*
// @grant            GM_xmlhttpRequest
// @connect          greasyfork.org
// @namespace        https://greasyfork.org/scripts/14044-wme-color-speeds
// @require          https://greasyfork.org/scripts/24851-wazewrap/code/WazeWrap.js
// @author           Created by French Script Team, Maintained by WazeDev
// @copyright        Sebiseba, seb-d59 & DummyD2 - 2015-2019
// ==/UserScript==

/* global W */
/* global WazeWrap */
/* global GM_info */
/* global CSpeedsWaze */
/* global I18n */
/* global $ */

// *********************
// **  DECLARATIONS   **
// *********************

// eslint-disable-next-line camelcase
const scriptName = GM_info.script.name;
// eslint-disable-next-line camelcase
const currentVersion = GM_info.script.version;
const changelogFrench = 'UPDATED: Rollback code';
const changelogEnglish = 'UPDATED: Rollback code';
// eslint-disable-next-line camelcase
const greasyForkUrl = GM_info.script.namespace;
const downloadUrl = 'https://greasyfork.org/scripts/14044-wme-color-speeds/code/wme-color-speeds.user.js';
const forumUrl = 'https://www.waze.com/forum/viewtopic.php?t=167387';
// let oldScriptVersion;
const debug = false;
let WMECSpeeds = {};
let loadStartTime;
let scriptStartTime;

const iconUndo = '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';
const iconDelete = 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAixJREFUeNqkk81KW1EUhb9zfxJvNI3GWARDSzMwEYfSX4uDVqgToRQctLO+QO2gHfgMTvsEQtthQTsQCh2IDyBYKa2CCrUGY9qYmtwk956zO8hN0NqZGw4cFovv7L0XR4kIlymLS5YDcKh6u4Jg7gMorPWzRkFHur1+AdApQzjupYeWAPxfpVkLZ6utN8e9bG4JEfyD/VkLd+sCQDB5byCzOjBWyCKC+RIst6qVR2CID2eX03du3ZDSMdRqq43K72mF9e3fDpJACq1Rtk26MJYrb25+VMkk6cnJHKVj8H1QKhV5AVAi0t2BED6I9aXe9+dHr1qOg4hgDWXgpIqu1ahs7xy1Tk+eKpzPKkrgHCBa1pTTk3g3kB8dUZaFGANAZXvnIKifPlPYawoIgeD/MZoNlewtigEThogxSKhBpAhqoz2r4hOaJzTOAwxNLz6cXUnfvTchYjBBgAkCRIS+69cmXC+xImgPQAN+p4MrKGx0JpHNrfXfvjkV7O0R1uvI7n5RdveLutUCgd6RkalYom/NRTKJKAEL4CVNjiAXM1IIv+9A9Q/uz8PSQrM6t9Cszjk/Dkqq1cLShjiqsIvk3hDwFUN709EIL+Bhoydd9r3B8jz2TGe0eewZ3xssN9r6dCfBboxKKQuIA/ZrnOeAu0j4AUhFxuornMcK9CLhW8AAVUB3AAqIAQkbXMDR4J1NyYIGEBoQoB6dLqDzM13aBjsCcqbdIHqZ6K4B+TsAqH70jpODe78AAAAASUVORK5CYII=';
const iconSubmit = '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';
const iconEdit = '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';

const colors = [
    '(255,0,128)', '(255,0,160)', '(255,0,192)', '(255,0,224)', '(255,0,255)', '(224,0,255)',
    '(192,0,255)', '(160,0,255)', '(128,0,255)', '(96,0,255)', '(64,0,255)', '(32,0,255)',
    '(0,0,255)', '(0,32,255)', '(0,64,255)', '(0,96,255)', '(0,128,255)', '(0,160,255)',
    '(0,192,255)', '(0,224,255)', '(0,255,255)', '(0,255,224)', '(0,255,192)', '(0,255,160)',
    '(0,255,128)', '(0,255,96)', '(0,255,64)', '(0,255,32)', '(0,255,0)', '(32,255,0)',
    '(64,255,0)', '(96,255,0)', '(128,255,0)', '(160,255,0)', '(192,255,0)', '(224,255,0)',
    '(255,255,0)', '(255,224,0)', '(255,192,0)', '(255,160,0)', '(255,128,0)', '(255,96,0)',
    '(255,64,0)', '(255,0,0)', 'Pink', 'LightPink', 'HotPink', 'DeepPink', 'PaleVioletRed',
    'MediumVioletRed', 'LightSalmon', 'Salmon', 'DarkSalmon', 'LightCoral', 'IndianRed', 'Crimson',
    'FireBrick', 'DarkRed', 'Red', 'OrangeRed', 'Tomato', 'Coral', 'DarkOrange', 'Orange', 'Yellow',
    'LightYellow', 'LemonChiffon', 'LightGoldenrodYellow', 'PapayaWhip', 'Moccasin', 'PeachPuff',
    'PaleGoldenrod', 'Khaki', 'DarkKhaki', 'Gold', 'Cornsilk', 'BlanchedAlmond', 'Bisque',
    'NavajoWhite', 'Wheat', 'BurlyWood', 'Tan', 'RosyBrown', 'SandyBrown', 'Goldenrod',
    'DarkGoldenrod', 'Peru', 'Chocolate', 'SaddleBrown', 'Sienna', 'Brown', 'Maroon',
    'DarkOliveGreen', 'Olive', 'OliveDrab', 'YellowGreen', 'LimeGreen', 'Lime', 'LawnGreen',
    'Chartreuse', 'GreenYellow', 'SpringGreen', 'MediumSpringGreen', 'LightGreen', 'PaleGreen',
    'DarkSeaGreen', 'MediumAquamarine', 'MediumSeaGreen', 'SeaGreen', 'ForestGreen', 'Green',
    'DarkGreen', 'Aqua', 'Cyan', 'LightCyan', 'PaleTurquoise', 'Aquamarine', 'Turquoise',
    'MediumTurquoise', 'DarkTurquoise', 'LightSeaGreen', 'CadetBlue', 'DarkCyan', 'Teal',
    'LightSteelBlue', 'PowderBlue', 'LightBlue', 'SkyBlue', 'LightSkyBlue', 'DeepSkyBlue',
    'DodgerBlue', 'CornflowerBlue', 'SteelBlue', 'RoyalBlue', 'Blue', 'MediumBlue', 'DarkBlue',
    'Navy', 'MidnightBlue', 'Lavender', 'Thistle', 'Plum', 'Violet', 'Orchid', 'Fuchsia',
    'Magenta', 'MediumOrchid', 'MediumPurple', 'BlueViolet', 'DarkViolet', 'DarkOrchid',
    'DarkMagenta', 'Purple', 'Indigo', 'DarkSlateBlue', 'RebeccaPurple', 'SlateBlue',
    'MediumSlateBlue', 'Snow', 'Honeydew', 'MintCream', 'Azure', 'AliceBlue', 'GhostWhite',
    'WhiteSmoke', 'Seashell', 'Beige', 'OldLace', 'FloralWhite', 'Ivory', 'AntiqueWhite',
    'Linen', 'LavenderBlush', 'MistyRose', 'LightSlateGray', 'SlateGray', 'DarkSlateGray',
    'White', '#EEE', 'Gainsboro', '#DDD', 'LightGrey', '#CCC', 'Silver', '#BBB', '#AAA',
    'DarkGray', '#999', '#888', 'Gray', '#777', 'DimGray', '#666', '#555', '#444', '#333',
    '#222', '#111', 'Black'
];

// speedColors[unit][speed] = color //-----> Default
WMECSpeeds.speedColors = {
    kmh: {
        10: '#ff6232', 20: '#ff6232', 30: '#ff6232', 40: '#f9805a', 45: '#fc9a3c', 50: '#ffad2d', 60: '#fffc28', 70: '#afff23', 80: '#09ff34', 90: '#14ff88', 100: '#0fffdf', 110: '#0ac2ff', 130: '#076aff'
    },
    mph: {
        5: '#ff6232', 10: '#ff6232', 15: '#ff6232', 20: '#f9805a', 25: '#fc9a3c', 30: '#ffad2d', 35: '#fffc28', 40: '#afff23', 45: '#09ff34', 50: '#14ff88', 55: '#0fffdf', 60: '#0ac2ff', 65: '#076aff', 70: '#0055dd', 75: '#0036db', 80: '#0b07ff', 85: '#8f07ff'
    },
    Others: '#f00'
};

const colorsUS = {
    Alabama: {},
    Alaska: {},
    Arizona: {},
    Arkansas: {},
    California: {},
    Colorado: {},
    Connecticut: {},
    Delaware: {},
    District_of_Columbia: {},
    Florida: {},
    Georgia: {},
    Hawaii: {},
    Idaho: {},
    Illinois: {},
    Indiana: {},
    Iowa: {},
    Kansas: {},
    Kentucky: {},
    Louisiana: {},
    Maine: {},
    Maryland: {},
    Massachusetts: {},
    Michigan: {},
    Minnesota: {},
    Mississippi: {},
    Missouri: {},
    Montana: {},
    Nebraska: {},
    Nevada: {},
    New_Hampshire: {},
    New_Jersey: {},
    New_Mexico: {},
    New_York: {},
    North_Carolina: {},
    North_Dakota: {},
    Ohio: {},
    Oklahoma: {},
    Oregon: {},
    Pennsylvania: {},
    Rhode_Island: {},
    South_Carolina: {},
    South_Dakota: {},
    Tennessee: {},
    Texas: {},
    Utah: {},
    Vermont: {},
    Virginia: {},
    Washington: {},
    West_Virginia: {},
    Wisconsin: {},
    Wyoming: {},
    United_States_Minor_Outlying_Islands: {},
    United_States_Virgin_Islands: {}
};

const multiplePalette = false;
const paletteByCountry = false;
let unit;
let selectedState;
let selectedCountry;

let mapLayer = [];
let toggler;
let groupToggler;

let zoom = 0;
const RoadToScan = [3, 6, 7, 4, 2, 1, 22, 20, 17, 8, 999];
// var RoadUpToStreet = [2,3,6,7];
// var highway = [3,6,7];

const typeOfRoad = {
    3: { name: 'Freeways', checked: true, zoom: 14 },
    6: { name: 'Major Highway', checked: true, zoom: 14 },
    7: { name: 'Minor Highway', checked: true, zoom: 14 },
    4: { name: 'Ramps', checked: true, zoom: 15 },
    2: { name: 'Primary Street', checked: false, zoom: 15 },
    1: { name: 'Streets', checked: false, zoom: 16 },
    22: { name: 'Narrow Streets', checked: false, zoom: 16 },
    20: { name: 'Parking Lot Road', checked: false, zoom: 16 },
    17: { name: 'Private Road', checked: false, zoom: 16 },
    8: { name: 'Off Road', checked: false, zoom: 16 },
    999: { name: 'Roundabout', checked: false, zoom: false }
};

WMECSpeeds.typeOfRoad = typeOfRoad;

const roadTypeZoomInfo = {
    3: { en: 'Freeway highlights require zoom of 14+', fr: 'Surligner les autoroutes nécessite un niveau de zoom supérieur ou égal à 14' },
    6: { en: 'Major Highway highlights require zoom of 14+', fr: 'Surligner les routes majeures nécessite un niveau de zoom supérieur ou égal à 14' },
    7: { en: 'Minor Highway highlights require zoom of 14+', fr: 'Surligner les routes mineures nécessite un niveau de zoom supérieur ou égal à 14' },
    4: { en: 'Ramp highlights require zoom of 14+', fr: 'Surligner les bretelles nécessite un niveau de zoom supérieur ou égal à 14' },
    2: { en: 'Primary Street highlights require zoom of 14+', fr: 'Surligner les rue principales nécessite un niveau de zoom supérieur ou égal à 14' },
    1: { en: 'Street highlights require zoom of 16+', fr: 'Surligner les rues nécessite un niveau de zoom supérieur ou égal à 16' },
    22: { en: 'Narrow Street highlights require zoom of 15+', fr: 'Surligner les rues étroites nécessite un niveau de zoom supérieur ou égal à 15' },
    20: { en: 'Parking Lot Road highlights require zoom of 15+', fr: 'Surligner les voies de parking nécessite un niveau de zoom supérieur ou égal à 15' },
    17: { en: 'Private Road highlights require zoom of 15+', fr: 'Surligner les voies privées nécessite un niveau de zoom supérieur ou égal à 15' },
    8: { en: 'Off Road highlights require zoom of 15+', fr: 'Surligner les chemins de terre nécessite un niveau de zoom supérieur ou égal à 15' },
    999: { en: 'Roundabouts are highlighted based on their Road Type', fr: 'Les ronds-points sont surlignés en fonction de leur type de route' }
};

//   5: "Walking Trails",
//  10: "Pedestrian Bw",
//  14: "Ferry",
//  16: "Stairway",
//  17: "Private Road",
//  18: "Railroad",
//  19: "Runway/Taxiway"
//  21: "Service Road"

// WMECSpeeds.selectedRoadType = [];
/*
const dashStyles = [
    'Solid',
    'ShortDash',
    'ShortDot',
    'ShortDashDot',
    'ShortDashDotDot',
    'Dot',
    'Dash',
    'LongDash',
    'DashDot',
    'LongDashDot',
    'LongDashDotDot'
];
*/
let CSI18n = 'en';

const CSlang = {
    1: { fr: 'Vitesses :', en: 'Speeds:' },
    2: { fr: 'Configuration des couleurs :', en: 'Color Control Panel:' },
    3: { fr: 'Couleurs :', en: 'Colors:' },
    4: { fr: 'Ajouter une vitesse', en: 'Add new speed' },
    5: { fr: 'Supprimer', en: 'Delete' },
    6: { fr: 'Annuler', en: 'Cancel' },
    7: { fr: 'Autres', en: 'Others' },
    8: { fr: 'Modifier', en: 'Edit' },
    9: { fr: 'Type de route', en: 'Road type' },
    10: { fr: 'Zoom', en: 'Zoom' },
    11: { fr: 'Rouge :', en: 'Red:' },
    12: { fr: 'Vert :', en: 'Green:' },
    13: { fr: 'Bleu :', en: 'Blue:' },
    14: { fr: 'Valider', en: 'Validate' },
    15: { fr: 'Décalage :', en: 'Offset:' },
    16: { fr: 'Opacité :', en: 'Opacity:' },
    17: { fr: 'Épaisseur :', en: 'Thickness:' },
    18: { fr: 'Rond-point', en: 'Roundabout' },
    19: { fr: 'Une palette par pays', en: 'One palette by country' },
    20: { fr: 'Une palette par état (USA uniquement)', en: 'One Palette by State (US only)' },
    21: { fr: 'pour', en: 'for' },
    22: { fr: 'Autoroute', en: 'Freeway' },
    23: { fr: 'Route majeure', en: 'Major Highway' },
    24: { fr: 'Route mineure', en: 'Minor Highway' },
    25: { fr: 'Bretelle', en: 'Ramps' },
    26: { fr: 'Rue principale', en: 'Primary Street' },
    27: { fr: 'Rue', en: 'Street' },
    28: { fr: 'Rue étroite', en: 'Narrow Street' },
    29: { fr: 'Voie de parking', en: 'Parking Lot Road' },
    30: { fr: 'Voie privée', en: 'Private Road' },
    31: { fr: 'Chemin de terre', en: 'Off Road' },
    32: { fr: 'Vitesses', en: 'Speeds' },
    33: { fr: 'Couleurs', en: 'Colors' },
};

WMECSpeeds.visibility = true;

const offsetValue = 3;
const opacityValue = 0.8;
const thicknessValue = 6;
let newspeedColorDialog;

// **********************
// ** HELPER FUNCTIONS **
// **********************

function log(msg, obj) {
    if (obj == null) {
        // eslint-disable-next-line camelcase, no-undef
        console.log(`${GM_info.script.name} v${currentVersion} - ${msg}`);
    } else if (debug) {
        // eslint-disable-next-line camelcase, no-undef
        console.debug(`${GM_info.script.name} v${currentVersion} - ${msg} `, obj);
    }
}

function getId(node) {
    return document.getElementById(node);
}

function getElementsByClassName(classname, node) {
    node = node || document.body;
    return Array.from(node.querySelectorAll(`.${classname}`));
}

function getFunctionWithArgs(func, args) {
    return (
        function() {
            const jsonArgs = JSON.stringify(args);
            return function() {
                args = JSON.parse(jsonArgs);
                func.apply(this, args);
            };
        }
    )();
}

function IsJsonString(str) {
    try {
        JSON.parse(str);
    } catch (e) {
        return false;
    }
    return true;
}

function cloneObj(obj) {
    const copy = JSON.parse(JSON.stringify(obj));
    return copy;
}

function Rgb2String(rgb) {
    rgb = roundDecimals(rgb);
    return `rgb(${rgb.r},${rgb.g},${rgb.b})`;
    // return "rgb(" + Math.round(rgb.r) +","+ Math.round(rgb.g) +","+ Math.round(rgb.b) +")";
}

function color2Rgb(c) {
    c = c.toLowerCase();

    function parseRgb(arr) {
        const rgb = {
            r: parseInt(arr[0], 10) || 0,
            g: parseInt(arr[1], 10) || 0,
            b: parseInt(arr[2], 10) || 0,
            name: null
        };
        rgb.r = Math.min(255, rgb.r);
        rgb.g = Math.min(255, rgb.g);
        rgb.b = Math.min(255, rgb.b);
        if (debug) log(`Red: ${rgb.r}, Green: ${rgb.g}, Blue: ${rgb.b}`);
        return rgb;
    }

    if (c.substr(0, 3) === 'rgb') {
        const arr = c
            .substring(3)
            .replace('(', '')
            .replace(')', '')
            .split(',')
            .map(val => val.trim());

        if (arr.length === 3 && arr.every(val => !isNaN(val))) {
            const colorrgbs = getColorArr('rgbs');
            const colornames = getColorArr('names');
            const matchIndex = colorrgbs.findIndex(color => JSON.stringify(arr) === JSON.stringify(color));

            if (matchIndex !== -1) {
                return {
                    r: arr[0],
                    g: arr[1],
                    b: arr[2],
                    name: colornames[matchIndex]
                };
            }

            return parseRgb(arr);
        }
    } else {
        let colornames = getColorArr('names');
        const matchIndex = colornames.findIndex(name => c === name.toLowerCase());

        if (matchIndex !== -1) {
            const colorrgbs = getColorArr('rgbs');
            if (debug) log(`${colornames}`);
            return {
                r: colorrgbs[matchIndex][0],
                g: colorrgbs[matchIndex][1],
                b: colorrgbs[matchIndex][2],
                name: colornames[matchIndex]
            };
        }

        c = c.replace('#', '');
        const colorHex = getColorArr('hexs');
        const hexMatchIndex = colorHex.findIndex(hex => c === hex);

        if (hexMatchIndex !== -1) {
            colornames = getColorArr('names');
            return { name: colornames[hexMatchIndex] };
        }

        if (c.length === 3) {
            c = c[0] + c[0] + c[1] + c[1] + c[2] + c[2];
        }

        const arr = [
            parseInt(c.substr(0, 2), 16),
            parseInt(c.substr(2, 2), 16),
            parseInt(c.substr(4, 2), 16)
        ];
        return parseRgb(arr);
    }
    return {
        r: 0,
        g: 0,
        b: 0,
        name: null
    };
}

// eslint-disable-next-line consistent-return
function getColorArr(x) {
    if (x === 'names') {
        return ['AliceBlue', 'AntiqueWhite', 'Aqua', 'Aquamarine', 'Azure', 'Beige', 'Bisque', 'Black', 'BlanchedAlmond',
            'Blue', 'BlueViolet', 'Brown', 'BurlyWood', 'CadetBlue', 'Chartreuse', 'Chocolate', 'Coral', 'CornflowerBlue', 'Cornsilk', 'Crimson',
            'Cyan', 'DarkBlue', 'DarkCyan', 'DarkGoldenRod', 'DarkGray', 'DarkGrey', 'DarkGreen', 'DarkKhaki', 'DarkMagenta', 'DarkOliveGreen',
            'DarkOrange', 'DarkOrchid', 'DarkRed', 'DarkSalmon', 'DarkSeaGreen', 'DarkSlateBlue', 'DarkSlateGray', 'DarkSlateGrey', 'DarkTurquoise',
            'DarkViolet', 'DeepPink', 'DeepSkyBlue', 'DimGray', 'DimGrey', 'DodgerBlue', 'FireBrick', 'FloralWhite', 'ForestGreen', 'Fuchsia',
            'Gainsboro', 'GhostWhite', 'Gold', 'GoldenRod', 'Gray', 'Grey', 'Green', 'GreenYellow', 'HoneyDew', 'HotPink', 'IndianRed', 'Indigo',
            'Ivory', 'Khaki', 'Lavender', 'LavenderBlush', 'LawnGreen', 'LemonChiffon', 'LightBlue', 'LightCoral', 'LightCyan',
            'LightGoldenRodYellow', 'LightGray', 'LightGrey', 'LightGreen', 'LightPink', 'LightSalmon', 'LightSeaGreen', 'LightSkyBlue',
            'LightSlateGray', 'LightSlateGrey', 'LightSteelBlue', 'LightYellow', 'Lime', 'LimeGreen', 'Linen', 'Magenta', 'Maroon',
            'MediumAquaMarine', 'MediumBlue', 'MediumOrchid', 'MediumPurple', 'MediumSeaGreen', 'MediumSlateBlue', 'MediumSpringGreen',
            'MediumTurquoise', 'MediumVioletRed', 'MidnightBlue', 'MintCream', 'MistyRose', 'Moccasin', 'NavajoWhite', 'Navy', 'OldLace',
            'Olive', 'OliveDrab', 'Orange', 'OrangeRed', 'Orchid', 'PaleGoldenRod', 'PaleGreen', 'PaleTurquoise', 'PaleVioletRed',
            'PapayaWhip', 'PeachPuff', 'Peru', 'Pink', 'Plum', 'PowderBlue', 'Purple', 'RebeccaPurple', 'Red', 'RosyBrown', 'RoyalBlue',
            'SaddleBrown', 'Salmon', 'SandyBrown', 'SeaGreen', 'SeaShell', 'Sienna', 'Silver', 'SkyBlue', 'SlateBlue', 'SlateGray', 'SlateGrey',
            'Snow', 'SpringGreen', 'SteelBlue', 'Tan', 'Teal', 'Thistle', 'Tomato', 'Turquoise', 'Violet', 'Wheat', 'White', 'WhiteSmoke',
            'Yellow', 'YellowGreen'];
    }
    if (x === 'hexs') {
        return ['f0f8ff', 'faebd7', '00ffff', '7fffd4', 'f0ffff', 'f5f5dc', 'ffe4c4', '000000', 'ffebcd', '0000ff', '8a2be2', 'a52a2a', 'deb887',
            '5f9ea0', '7fff00', 'd2691e', 'ff7f50', '6495ed', 'fff8dc', 'dc143c', '00ffff', '00008b', '008b8b', 'b8860b', 'a9a9a9', 'a9a9a9', '006400',
            'bdb76b', '8b008b', '556b2f', 'ff8c00', '9932cc', '8b0000', 'e9967a', '8fbc8f', '483d8b', '2f4f4f', '2f4f4f', '00ced1', '9400d3', 'ff1493',
            '00bfff', '696969', '696969', '1e90ff', 'b22222', 'fffaf0', '228b22', 'ff00ff', 'dcdcdc', 'f8f8ff', 'ffd700', 'daa520', '808080', '808080',
            '008000', 'adff2f', 'f0fff0', 'ff69b4', 'cd5c5c', '4b0082', 'fffff0', 'f0e68c', 'e6e6fa', 'fff0f5', '7cfc00', 'fffacd', 'add8e6', 'f08080',
            'e0ffff', 'fafad2', 'd3d3d3', 'd3d3d3', '90ee90', 'ffb6c1', 'ffa07a', '20b2aa', '87cefa', '778899', '778899', 'b0c4de', 'ffffe0', '00ff00',
            '32cd32', 'faf0e6', 'ff00ff', '800000', '66cdaa', '0000cd', 'ba55d3', '9370db', '3cb371', '7b68ee', '00fa9a', '48d1cc', 'c71585', '191970',
            'f5fffa', 'ffe4e1', 'ffe4b5', 'ffdead', '000080', 'fdf5e6', '808000', '6b8e23', 'ffa500', 'ff4500', 'da70d6', 'eee8aa', '98fb98', 'afeeee',
            'db7093', 'ffefd5', 'ffdab9', 'cd853f', 'ffc0cb', 'dda0dd', 'b0e0e6', '800080', '663399', 'ff0000', 'bc8f8f', '4169e1', '8b4513', 'fa8072',
            'f4a460', '2e8b57', 'fff5ee', 'a0522d', 'c0c0c0', '87ceeb', '6a5acd', '708090', '708090', 'fffafa', '00ff7f', '4682b4', 'd2b48c', '008080',
            'd8bfd8', 'ff6347', '40e0d0', 'ee82ee', 'f5deb3', 'ffffff', 'f5f5f5', 'ffff00', '9acd32'];
    }
    if (x === 'rgbs') {
        return [[240, 248, 255], [250, 235, 215], [0, 255, 255], [127, 255, 212], [240, 255, 255], [245, 245, 220], [255, 228, 196], [0, 0, 0],
            [255, 235, 205], [0, 0, 255], [138, 43, 226], [165, 42, 42], [222, 184, 135], [95, 158, 160], [127, 255, 0], [210, 105, 30], [255, 127, 80],
            [100, 149, 237], [255, 248, 220], [220, 20, 60], [0, 255, 255], [0, 0, 139], [0, 139, 139], [184, 134, 11], [169, 169, 169], [169, 169, 169],
            [0, 100, 0], [189, 183, 107], [139, 0, 139], [85, 107, 47], [255, 140, 0], [153, 50, 204], [139, 0, 0], [233, 150, 122], [143, 188, 143],
            [72, 61, 139], [47, 79, 79], [47, 79, 79], [0, 206, 209], [148, 0, 211], [255, 20, 147], [0, 191, 255], [105, 105, 105], [105, 105, 105],
            [30, 144, 255], [178, 34, 34], [255, 250, 240], [34, 139, 34], [255, 0, 255], [220, 220, 220], [248, 248, 255], [255, 215, 0], [218, 165, 32],
            [128, 128, 128], [128, 128, 128], [0, 128, 0], [173, 255, 47], [240, 255, 240], [255, 105, 180], [205, 92, 92], [75, 0, 130], [255, 255, 240],
            [240, 230, 140], [230, 230, 250], [255, 240, 245], [124, 252, 0], [255, 250, 205], [173, 216, 230], [240, 128, 128], [224, 255, 255],
            [250, 250, 210], [211, 211, 211], [211, 211, 211], [144, 238, 144], [255, 182, 193], [255, 160, 122], [32, 178, 170], [135, 206, 250],
            [119, 136, 153], [119, 136, 153], [176, 196, 222], [255, 255, 224], [0, 255, 0], [50, 205, 50], [250, 240, 230], [255, 0, 255],
            [128, 0, 0], [102, 205, 170], [0, 0, 205], [186, 85, 211], [147, 112, 219], [60, 179, 113], [123, 104, 238], [0, 250, 154],
            [72, 209, 204], [199, 21, 133], [25, 25, 112], [245, 255, 250], [255, 228, 225], [255, 228, 181], [255, 222, 173], [0, 0, 128],
            [253, 245, 230], [128, 128, 0], [107, 142, 35], [255, 165, 0], [255, 69, 0], [218, 112, 214], [238, 232, 170], [152, 251, 152],
            [175, 238, 238], [219, 112, 147], [255, 239, 213], [255, 218, 185], [205, 133, 63], [255, 192, 203], [221, 160, 221], [176, 224, 230],
            [128, 0, 128], [102, 51, 153], [255, 0, 0], [188, 143, 143], [65, 105, 225], [139, 69, 19], [250, 128, 114], [244, 164, 96],
            [46, 139, 87], [255, 245, 238], [160, 82, 45], [192, 192, 192], [135, 206, 235], [106, 90, 205], [112, 128, 144], [112, 128, 144],
            [255, 250, 250], [0, 255, 127], [70, 130, 180], [210, 180, 140], [0, 128, 128], [216, 191, 216], [255, 99, 71], [64, 224, 208],
            [238, 130, 238], [245, 222, 179], [255, 255, 255], [245, 245, 245], [255, 255, 0], [154, 205, 50]];
    }
}
// I don't think this is needed anymore
function roundDecimals(c) {
    c.r = Math.round(c.r);
    c.g = Math.round(c.g);
    c.b = Math.round(c.b);
    return c;
}

function checkUnit() {
    // eslint-disable-next-line no-undef
    if (CSpeedsModel.isImperial) {
        unit = 'mph';
    } else {
        unit = 'kmh';
    }
    log(unit);
    if (getId('CStable')) {
        getId('CStable').innerHTML = '';
        getId('CSroadType').innerHTML = '';
        LoadSettings();
        getId('unitvalue').innerHTML = `(${unit})`;
    }
}

function createToggler() {
    // Layers switcher
    // test with script toggler----------------
    const oldTogglers = document.querySelectorAll('.togglers');
    oldTogglers.forEach((elt, idx) => {
        if (elt.id !== 'toolboxUl') {
            if (oldTogglers[idx].querySelector('.layer-switcher-group_scripts') === null) {
                const newScriptsToggler = document.createElement('li');
                newScriptsToggler.className = 'group';
                newScriptsToggler.innerHTML = '<div class="controls-container main toggler">\
                                                <input class="layer-switcher-group_scripts toggle" id="layer-switcher-group_scripts" type="checkbox">\
                                                <label for="layer-switcher-group_scripts">\
                                                <span class="label-text">Scripts</span>\
                                                </label>\
                                              </div>\
                                              <ul class="children">\
                                              </ul>';
                oldTogglers[idx].appendChild(newScriptsToggler);
            }

            const layerSwitcher = document.createElement('li');
            layerSwitcher.innerHTML = '<div class="controls-container toggler">\
                                        <input class="layer-switcher-item_WME_Color_Speeds toggle" id="layer-switcher-item_WME_Color_Speeds" type="checkbox">\
                                        <label for="layer-switcher-item_WME_Color_Speeds">\
                                          <span class="label-text">Color Speeds</span>\
                                        </label>\
                                      </div>';

            let groupScripts = document.querySelector('.layer-switcher-group_scripts').parentNode.parentNode;
            let newScriptsChildren = getElementsByClassName('children', groupScripts)[0];
            newScriptsChildren.appendChild(layerSwitcher);

            toggler = getId('layer-switcher-item_WME_Color_Speeds');
            groupToggler = getId('layer-switcher-group_scripts');
            groupToggler.checked = (typeof (localStorage.groupScriptsToggler) !== 'undefined'
                ? JSON.parse(localStorage.groupScriptsToggler) : true);

            toggler.checked = WMECSpeeds.togglerChecked;
            toggler.disabled = !groupToggler.checked;

            toggler.addEventListener('click', e => {
                mapLayer.setVisibility(e.target.checked);
                saveOption();
            });

            groupToggler.addEventListener('click', e => {
                toggler.disabled = !e.target.checked;
                mapLayer.setVisibility(toggler.checked ? e.target.checked : toggler.checked);
                localStorage.setItem('groupScriptsToggler', e.target.checked);
            });
        }
    });
}

function changelogLocalizer() {
    let changelog;
    // eslint-disable-next-line no-undef
    CSpeedI18n = I18n.locale;
    // eslint-disable-next-line no-undef
    if (CSpeedI18n === 'fr') {
        changelog = changelogFrench;
    } else {
        changelog = changelogEnglish;
    }
    return changelog;
}

function getTopCountry() {
    // eslint-disable-next-line no-undef
    return CSpeedsModel.getTopCountry();
}

function getTopState() {
    // eslint-disable-next-line no-undef
    return CSpeedsModel.getTopState();
}

function saveOption() {
    WMECSpeeds.togglerChecked = getId('layer-switcher-item_WME_Color_Speeds').checked;
    localStorage.setItem('WMEColorSpeeds', JSON.stringify(WMECSpeeds));
}
function destroyTab() {
    W.userscripts.removeSidebarTab('ColorSpeeds');
    if (debug) log('Sidebar tab removed');
}

// *************
// **  INIT   **
// *************
function counterStart() {
    loadStartTime = performance.now();
    bootstrap();
}

function bootstrap() {
    scriptStartTime = performance.now();
    // eslint-disable-next-line no-undef
    if (WazeWrap?.Ready && W?.userscripts?.state.isReady) {
        log('Starting');
        init();
    } else {
        if (debug) log('WME and WW not ready');
        setTimeout(bootstrap, 500);
    }
}

function showScriptInfoAlert() {
    WazeWrap.Interface.ShowScriptUpdate(
        // eslint-disable-next-line camelcase
        GM_info.script.name,
        // eslint-disable-next-line camelcase
        GM_info.script.version,
        changelogLocalizer(),
        greasyForkUrl,
        forumUrl
    );
}

function loadScriptUpdateMonitor() {
    try {
        const updateMonitor = new WazeWrap.Alerts.ScriptUpdateMonitor(scriptName, currentVersion, downloadUrl, GM_xmlhttpRequest);
        if (debug) log('Checked for update');
        updateMonitor.start();
    } catch (ex) {
        // Report the error, but not a critical failure.
        console.error(scriptName, ex);
    }
}

function init() {
    loadScriptUpdateMonitor();
    showScriptInfoAlert();
    // Waze object needed
    // eslint-disable-next-line no-undef
    CSpeedsWaze = unsafeWindow.W;
    if (typeof (CSpeedsWaze) === 'undefined') {
        if (debug) { console.error('WME ColorSpeeds - CSpeedsWaze : NOK'); }
        window.setTimeout(init, 500);
        return;
    }
    // eslint-disable-next-line no-undef
    CSpeedsMap = CSpeedsWaze.map;
    if (typeof (CSpeedsMap) === 'undefined') {
        if (debug) { console.error('WME ColorSpeeds - CSpeedsmap : NOK'); }
        window.setTimeout(init, 500);
        return;
    }
    // eslint-disable-next-line no-undef
    CSpeedsModel = CSpeedsWaze.model;
    if (typeof (CSpeedsModel) === 'undefined') {
        if (debug) { console.error('WME ColorSpeeds - CSpeedsModel DOM : NOK'); }
        window.setTimeout(init, 500);
        return;
    }

    // eslint-disable-next-line no-undef
    CSpeedsCountries = CSpeedsModel.countries;
    if (typeof (CSpeedsCountries) === 'undefined') {
        if (debug) { console.error('WME ColorSpeeds - CSpeedsCountries DOM : NOK'); }
        window.setTimeout(init, 500);
        return;
    }
    CSpeedsTopCountries = getTopCountry();
    if (typeof (CSpeedsTopCountries) === 'undefined' || getTopCountry() === null) {
        if (debug) { console.error('WME ColorSpeeds - CSpeedsCountries.top DOM : NOK'); }
        window.setTimeout(init, 500);
        return;
    }
    if (typeof (getTopCountry().attributes.name) === 'undefined') {
        if (debug) { console.error('WME ColorSpeeds - CSpeedsCountries.top.name DOM : NOK'); }
        window.setTimeout(init, 500);
        return;
    }
    //    OpenLayers
    CSpeedOpenLayers = unsafeWindow.OpenLayers;
    if (typeof (CSpeedOpenLayers) === 'undefined') {
        if (debug) { console.error('WME ColorSpeeds - OpenLayers : NOK'); }
        window.setTimeout(init, 500);
        return;
    }
    //    Traductions
    CSpeedI18n = I18n.locale;
    if (typeof(CSpeedI18n) === 'undefined') {
        if (debug) { console.error('WME ColorSpeeds - CSpeedI18n : NOK'); }
        setTimeout(init, 500);
        return;
    }

    // Verify localStorage. Init if empty or not correct
    if (typeof (localStorage.WMEColorSpeeds) !== 'undefined' && IsJsonString(localStorage.getItem('WMEColorSpeeds'))) {
        WMECSpeeds = JSON.parse(localStorage.WMEColorSpeeds);
        if (WMECSpeeds.speedColors.Others === undefined) WMECSpeeds.speedColors.Others = '#f00';
        if (WMECSpeeds.speedColors.US === undefined) WMECSpeeds.speedColors.US = cloneObj(colorsUS);
        if (WMECSpeeds.speedColors.Countries === undefined) WMECSpeeds.speedColors.Countries = {};
        if (WMECSpeeds.multiplePalette === undefined) WMECSpeeds.multiplePalette = multiplePalette;
        if (WMECSpeeds.PaletteByCountrie === undefined) WMECSpeeds.PaletteByCountrie = paletteByCountry;
        if (WMECSpeeds.offsetValue === undefined) WMECSpeeds.offsetValue = offsetValue;
        if (WMECSpeeds.opacityValue === undefined) WMECSpeeds.opacityValue = opacityValue;
        if (WMECSpeeds.thicknessValue === undefined) WMECSpeeds.thicknessValue = thicknessValue;
        for (const key in typeOfRoad) {
            if (WMECSpeeds.typeOfRoad.hasOwnProperty(key) === false ) {
                WMECSpeeds.typeOfRoad[key] = cloneObj(typeOfRoad[key]);
            }
        }
        if (WMECSpeeds.togglerChecked === undefined) WMECSpeeds.togglerChecked = WMECSpeeds.visibility;
        /* this if statement is no longer needed with WW
        if (WMECSpeeds.version === undefined) {
            oldScriptVersion = 0;
        } else if (WMECSpeeds.version !== undefined) {
            oldScriptVersion = WMECSpeeds.version;
        }
        */
        WMECSpeeds.MultiplePalette = (getTopCountry().attributes.name === 'United States') ? WMECSpeeds.MultiplePalette : false;
        //        WMECSpeeds.MultiplePalette = (CSpeedsCountries.top.name == "United States")? WMECSpeeds.MultiplePalette : false;

        log('Init ok');
        log('WMECSpeeds = ', WMECSpeeds);
    } else {
        localStorage.setItem('WMEColorSpeeds', JSON.stringify(WMECSpeeds));
        setTimeout(init, 500);
        return;
    }
    // ======================================================

    // Translation
    if (CSpeedI18n === 'fr') {
        CSI18n = CSpeedI18n;
    } else CSI18n = 'en';

    // ======================================================

    checkUnit();

    // WME Layers check
    let layers = CSpeedsMap.getLayersBy('uniqueName', 'WME_Color_Speeds');
    if (layers.length === 0) {
        I18n.translations[CSpeedI18n].layers.name['WME_Color_Speeds'] = 'Color Speeds';

        const colorspeedsStyle = new CSpeedOpenLayers.Style({
            pointRadius: 2,
            fontWeight: 'normal',
            label: '${labelText}',
            fontFamily: 'Tahoma, Courier New',
            labelOutlineColor: '#FFFFFF',
            labelOutlineWidth: 2,
            fontColor: '#000000',
            fontSize: '10px'
        });

        mapLayer = new CSpeedOpenLayers.Layer.Vector(I18n.t('layers.name.WME_Color_Speeds'), {
            displayInLayerSwitcher: true,
            uniqueName: 'WME_Color_Speeds',
            styleMap: new CSpeedOpenLayers.StyleMap(colorspeedsStyle)
        });

        CSpeedsMap.addUniqueLayer(mapLayer);
        mapLayer.setVisibility(WMECSpeeds.visibility);
    }

    createToggler();

    // MTE mode event
    /*
      W.app.modeController.model.bind('change:mode', function(){
      if (W.app.modeController.getState() !== undefined){
        eventUnRegister();
        try { colorspeeds_mapLayer.destroyFeatures();
        }catch(err){log('err destroyFeatures: ',err);}
      }
      if (W.app.modeController.getState() === undefined){
        eventUnRegister();
        createToggler();
        CSpeeds_css();
      }
    });
    */
    // reload after changing WME units
    W.prefs.on('change:isImperial', () => {
        destroyTab();
        eventUnRegister();
        checkUnit();
        createToggler();
        createCSS();
    });

    // log('colorspeeds_mapLayer ',colorspeeds_mapLayer);

    // Then running
    createCSS();
}

function createCSS() {
    let CSpeedsCSS = getId('CSpeedsCSS');
    if (CSpeedsCSS === null) {
        CSpeedsCSS = document.createElement('style');
        CSpeedsCSS.type = 'text/css';
        CSpeedsCSS.id = 'CSpeedsCSS';
    }

    let css = '.CScontent {width:255px; margin-left:10px; box-shadow: 0 4px 10px #aaa;}';
    css += '.divStateChoise {width:250px; margin-left:10px; color:#59899e; font-weight:bold; vertical-align: middle;}';
    css += '.divHeadline {height:26px; font-weight:bold; padding-top:2px; border:2px solid #3d3d3d; background-color:#BEDCE5;}';
    css += '.divContent {clear:both;height:26px; border:2px solid #3d3d3d; border-top:0;}';
    css += '.divContentZoom { clear:both; height:26px; border:2px solid #3d3d3d; border-top:0;}';
    css += '.divc {float:center; text-align:center;}';
    css += '.divl {float:left; text-align:center;}';
    css += '.divll {float:left; text-align:left;}';
    css += '.divr {float:right; text-align:center;}';
    css += '.speed {margin-top:2px; width:65px; height:20px; color:#59899e; font-weight:bold; vertical-align: middle;}';
    css += '.divcolor { width:80px; height:17px; margin:4px 0 0 0; vertical-align: middle;}';
    css += '.CStype {margin-top:2px; margin-left:10px; height:20px; color:#59899e; font-weight:bold; text-align:left; vertical-align: middle;}';
    css += '.CScheckLabel {margin-top:5px; margin-left:10px; height:22px; color:#59899e; font-weight:bold; text-align:left; vertical-align: middle;}';
    css += '.CScheck { float:left; width:22px; height:22px;}';
    css += '.CSzoom {margin-top:2px; height:20px; color:#59899e; font-weight:bold; vertical-align: middle}';
    css += '#newspeed {width:65px; height:26px; font-weight:bold;text-align:center;}';
    css += '#editzoom { display:none;}';
    css += '#newvalzoom {width:45px; height:24px; font-weight:bold;text-align:center;}';
    css += '.CScontentConf {width:280px; margin-left:5px;}';
    css += '.divContentConf {clear:both; line-height:24px; height:28px;}';
    css += '.valColor {color:#59899e; font-weight:bold;}';
    css += '#valRed {width:80px; height:28px; font-weight:bold; color:red;text-align:center;}';
    css += '#valGreen {width:80px; height:28px; font-weight:bold; color:green;text-align:center;}';
    css += '#valBlue {width:80px; height:28px; font-weight:bold; color:blue;text-align:center;}';
    css += '#valOffset {width:80px; height:28px; font-weight:bold;text-align:center;}';
    css += '#valOpacity {width:80px; height:28px; font-weight:bold;text-align:center;}';
    css += '#valThickness {width:80px; height:28px; font-weight:bold;text-align:center;}';
    css += '#ConfColor.dropdown-menu li:hover, #ConfColor+.dropdown-menu li:active, #ConfColor+.dropdown-menu li:focus { cursor: pointer; outline: #3B99FC dotted 1px; }';
    css += '#ConfColor.btn { box-shadow: inset 0px -1px 0px rgba(0,0,0,0.2); border-radius: 4px; border: 1px solid rgba(0,0,0,0.25); height:22px; width:90px; }';
    css += '#nameColor {width:120px; height:22px;}';
    // css +="#ConfDash.dropdown-menu li:hover, #ConfDash+.dropdown-menu li:active, #ConfDash+.dropdown-menu li:focus { cursor: pointer; outline: #3B99FC dotted 1px; }";
    // css +="#ConfDash.btn { box-shadow: inset 0px -1px 0px rgba(0,0,0,0.2); border-radius: 4px; border: 1px solid rgba(0,0,0,0.25); height:22px; width:90px; }";
    CSpeedsCSS.innerHTML = css;
    document.body.appendChild(CSpeedsCSS);
    createTab();
}

function createNewSpeedColorDialog() {
    newspeedColorDialog = getId('newspeedColorDialog');
    if (newspeedColorDialog === null) {
        newspeedColorDialog = document.createElement('div');
        newspeedColorDialog.id = 'newspeedColorDialog';
    }

    // newspeedColorDialog.style.fontSize = '90%';
    newspeedColorDialog.style.display = 'none';
    newspeedColorDialog.style.top = '10px';
    // newspeedColorDialog.style.left = '15px';
    newspeedColorDialog.style.width = '300px';
    newspeedColorDialog.style.height = '500px';
    newspeedColorDialog.style.margin = '10px 10px 10px 0px';
    newspeedColorDialog.style.borderRadius = '10px';
    newspeedColorDialog.style.border = '1px solid #BEDCE5';
    newspeedColorDialog.style.position = 'relative';
    newspeedColorDialog.style.padding = '5px';
    newspeedColorDialog.style.overflow = 'auto';
    newspeedColorDialog.style.background = 'rgba(255, 255, 255, 1)';

    let content = "<div style='clear:both;'></div>";
    content += `<div class='divc' style='width:200px; font-weight:bold;'>${CSlang[2][CSI18n]}</div>`;
    content += "<div style='clear:both; padding-top:10px;'></div>";

    // header table
    content += "<div class='CScontentConf'>";

    // Edit other color
    content += "<div class='divContentConf' id='Conf_Others' style='display:none;'>";
    content += `<div class='divll' style='width:70px;font-weight:bold;'>${CSlang[1][CSI18n]} </div>`;
    content += `<div class='divll' style='width:60px;font-weight:bold;'>${CSlang[7][CSI18n]}</div>`;
    content += "<div class='divl' style='width:45px;'>&nbsp;</div>";
    content += "<div style='clear:both; padding-top:10px;'></div>";
    content += `<div class='divll' style='width:70px;font-weight:bold;'>${CSlang[3][CSI18n]}: </div>`;
    content += '</div>';

    // Edit speed color
    content += "<div class='divContentConf' id='Conf_Color' style='display:none;'>";
    content += `<div class='divll' style='width:75px;font-weight:bold;'>${CSlang[1][CSI18n]} </div>`;
    content += "<div class='divll speed' style='width:60px;'><input type='text' value='' id='newspeed'/></div>";
    content += `<div class='divl' id='unitvalue' style='width:45px;font-size:11px;font-weight:bold;line-height:20px;'>(${unit})</div>`;
    content += "<div style='clear:both; padding-top:10px;'></div>";
    content += `<div class='divll' style='width:75px;font-weight:bold;'>${CSlang[3][CSI18n]} </div>`;
    content += '</div>';

    content += `<div class='divl dropdown' style='width:90px; text-align:left;'><button id='ConfColor' class='btn dropdown-toggle' style='background-color:${WMECSpeeds.speedColors.Others};' type='button' data-toggle='dropdown'></button><ul class='dropdown-menu' style='height: 400px; overflow: auto; margin: 0; padding: 0; min-width: 90px;'>`;
    for (let i = 0; colors[i]; ++i) {
        let test = (colors[i].match(/\(/)) ? true : false;
        switch (test) {
            case true:
                content += "<li style='background-color:rgb" + colors[i] + "'>&nbsp;</li>";
                break;
            case false:
                content += "<li style='background-color:" + colors[i] + "'>&nbsp;</li>";
                break;
        }
    }
    content += '</ul></div>';
    content += "<span class='divl valColor' id=nameColor></span>";
    content += '</div>';
    content += "<div style='clear:both; padding-top:10px;'></div>";

    // Red Value
    content += "<div class='CScontentConf'>";
    content += "<div class='divContentConf'>";
    content += `<div class='divll' style='width:60px;font-weight:bold; color:red;'>${CSlang[11][CSI18n]}</div>`;
    content += "<div style='clear:both; padding-top:2px;'></div>";
    content += "<div class='divl valColor' style='width:80px; height:28px;'><input type='number' max='255' min='0' value='' id='valRed' pattern='[0-9]{3}' /></div>";
    content += "<div class='divr'><input id='sliderRed' type='range' max='255' min='0' style='width:180px;height:24px;'></div>";
    content += '</div>';

    // Green Value
    content += "<div style='clear:both; padding-top:10px;'></div>";
    content += "<div class='divContentConf'>";
    content += `<div class='divll' style='width:60px;font-weight:bold; color:green;'>${CSlang[12][CSI18n]}</div>`;
    content += "<div style='clear:both; padding-top:2px;'></div>";
    content += "<div class='divl valColor' style='width:80px; height:28px;'><input type='number' max='255' min='0' value='' id='valGreen' pattern='[0-9]{3}' /></div>";
    content += "<div class='divr'><input id='sliderGreen' type='range' max='255' min='0' style='width:180px;height:24px;'></div>";
    content += '</div>';
    content += "<div style='clear:both; padding-top:10px;'></div>";

    // Bleu Value
    content += "<div class='divContentConf'>";
    content += `<div class='divll' style='width:60px;font-weight:bold; color:blue;'>${CSlang[13][CSI18n]}</div>`;
    content += "<div style='clear:both; padding-top:2px;'></div>";
    content += "<div class='divl valColor' style='width:80px; height:28px;'><input type='number' max='255' min='0' value='' id='valBlue' pattern='[0-9]{3}' /></div>";
    content += "<div class='divr'><input id='sliderBlue' type='range' max='255' min='0' style='width:180px;height:24px;'></div>";
    content += '</div>';

    content += "<div style='clear:both; padding-top:10px;'></div>";
    content += `<div class='divr' style='width:40px; height:40x'><a href='#'><img id='cancel' style='width:20px;' title='${CSlang[6][CSI18n]}' src='data:image/png;base64,${iconUndo}' /></a></div>`;
    content += `<div class='divr' style='width:40px; height:40x;'><a href='#'><img id='submit' style='width:20px;' title='${CSlang[14][CSI18n]}' src='data:image/png;base64,${iconSubmit}' /></a></div>`;
    // content += "<div class='divc' style='width:270px; font-weight:bold;'><button id='OkButton'>Ok</button></div>";
    content += '</div>';

    newspeedColorDialog.innerHTML = content;
    // document.body.appendChild(newspeedColorDialog);
    // CSpeedshandleClass2.appendChild(newspeedColorDialog);
    getId('tab-colorspeeds').appendChild(newspeedColorDialog);
}

// *************
// **  HTML   **
// *************

async function createTab() {
    const { tabLabel, tabPane } = W.userscripts.registerSidebarTab('ColorSpeeds');
    if (debug) log('Starting tab creation');
    const labelText = $('<div>').append(
        $('<span>', {
            id: 'cspeedstablabel',
            class: 'fa fa-dashboard',
            title: `${CSlang[32][CSI18n]}`
        })
    ).html();

    tabLabel.innerHTML = labelText;

    // colorspeeds header
    let content = `<div style='float:left; margin-left:5px;'><b><a href='https://greasyfork.org/scripts/14044-wme-color-speeds' target='_blank'><u>WME Color Speeds</u></a></b> v${currentVersion}</div>`;
    content += "<div id='colorspeedsDiv'>";

    // Countries pallete
    content += "<div style='clear:both; padding-top:10px;'></div>";
    content += `<div class='divStateChoise' id='countrieChoise' style='display:block;'><input type='checkbox' class='CScheck' id='cbPaletteByCountrie'><div class='divl CScheckLabel' style='width:210px;'>${CSlang[19][CSI18n]}</div>`;
    content += "<div style='clear:both; padding-top:10px;'></div>"; // Couleurs pour </div>";
    content += "<select id='selectCountrie' style='height:22px; width:250px; active:none;'>";
    Object.keys(WMECSpeeds.speedColors.Countries).forEach(countrie => {
        content += `<option value='${countrie}'>${countrie.replace(/_/g, ' ')}</option>`;
    });
    content += '</select></div>';

    // Mutiple pallete
    content += "<div style='clear:both; padding-top:10px;'></div>";
    content += `<div class='divStateChoise' id='stateChoise' style='display:block;'><input type='checkbox' class='CScheck' id='cbMultiplePalette'><div class='divl CScheckLabel' style='width:210px;'>${CSlang[20][CSI18n]}</div>`;
    content += "<div style='clear:both; padding-top:20px;'></div>"; // Couleurs pour </div>";
    content += "<select id='selectState' style='height:22px; active:none;'>";
    Object.keys(WMECSpeeds.speedColors.US).forEach(state => {
        content += `<option value='${state}'>${state.replace(/_/g, ' ')}</option>`;
    });
    content += '</select></div>';

    // Speed table header
    content += "<div style='clear: both; padding-top:10px;'></div><div class='CScontent'>";
    content += `<div class='divHeadline'><div class='divl' style='width:60px;'>${CSlang[32][CSI18n]}</div><div class='divr' id='unitvalue' style='width:45px;font-size:11px;line-height:20px;'>(${unit})</div><div class='divr' style='width:130px;'>${CSlang[33][CSI18n]}</div></div>`;

    // Speed table
    content += `<div class='divContent'><div class='divl speed' style='width:60px;'>${CSlang[7][CSI18n]}</div>`;
    content += "<div class='divr' style='width:20px;'>&nbsp;</div>";
    content += `<div class='divr' style='width:20px;'><a href='#'><img id='edit_others' style='width:16px;' title='${CSlang[8][CSI18n]}' src='data:image/png;base64,${iconEdit}' /></a></div>`;
    content += `<div class='divr' style='width:120px;'><div id='color_others' class='divcolor' style='background-color:${WMECSpeeds.speedColors.Others};'>&nbsp;</div></div></div>`;
    content += "<div id='CStable'></div></div><div id='divadd'></div>";

    // Road type header
    content += "<br><div style='clear:both; padding-top:10px;'></div><div class='CScontent'>";
    content += `<div class='divHeadline'><div class='divl' style='width:120px;'>${CSlang[9][CSI18n]}</div><div class='divr' style='width:60px; margin-right:20px;'>${CSlang[10][CSI18n]}</div></div>`;
    // edit zoom
    content += "<div class='divContent' id='editzoom'><div class='divl speed' style='width:110px;'><span id='texttype'></span></div>";
    content += `<div class='divr' style='width:20px;'><a href='#'><img id='cancelZoom' style='width:20px;' title='${CSlang[6][CSI18n]}' src='data:image/png;base64,${iconUndo}' /></a></div>`;
    content += `<div class='divr' style='width:20px;'><a href='#'><img id='submitZoom' style='width:20px;' title='${CSlang[14][CSI18n]}' src='data:image/png;base64,${iconSubmit}' /></a></div>`;
    content += "<div class='divr speed' style='width:60px;'><input type='text' value='' id='newvalzoom'/></div>";
    content += '</div>';
    content += "<div id='CSroadType'></div></div>";

    // Offset Value
    content += "<br><div style='clear:both; padding-top:10px;'></div>";
    content += "<div class='divContentConf'>";
    content += `<div class='divll' style='width:65px;font-weight:bold;color:#59899e;'>${CSlang[15][CSI18n]}</div>`;
    content += "<div style='clear:both; padding-top:2px;'></div>";
    content += "<div class='divl valColor' style='width:80px; height:28px;'><input type='number' id='valOffset' min='1' max='10' value='' pattern='[0-9]{2}'/></div>";
    content += "<div class='divr'><input id='sliderOffset' type='range' max='10' min='1' step='1' style='width:180px;height:24px;margin-right:20px;'></div>";
    content += '</div>';

    // Opacity Value
    content += "<div style='clear:both; padding-top:10px;'></div>";
    content += "<div class='divContentConf'>";
    content += `<div class='divll' style='width:65px;font-weight:bold;color:#59899e;'>${CSlang[16][CSI18n]}</div>`;
    content += "<div style='clear:both; padding-top:2px;'></div>";
    content += "<div class='divl valColor' style='width:80px; height:28px;'><input type='number' id='valOpacity' min='20' max='100' value='' pattern='[0-9]{3}'/></div>";
    content += "<div class='divr'><input id='sliderOpacity' type='range' max='100' min='20'  step='1' style='width:180px;height:24px;margin-right:20px;'></div>";
    content += '</div>';

    // Thickness Value
    content += "<div style='clear:both; padding-top:10px;'></div>";
    content += "<div class='divContentConf'>";
    content += `<div class='divll' style='width:65px;font-weight:bold;color:#59899e;'>${CSlang[17][CSI18n]}</div>`;
    content += "<div style='clear:both; padding-top:2px;'></div>";
    content += "<div class='divl valColor' style='width:80px; height:28px;'><input type='number' id='valThickness' min='2' max='10' value='' pattern='[0-9]{2}'/></div>";
    content += "<div class='divr'><input id='sliderThickness' type='range' max='10' min='2' step='1' style='width:180px;height:24px;margin-right:20px;'></div>";
    content += '</div>';

    /*
    // 2023-09-26 SS28 I haven't taken the time to see what is wrong here. Maybe we can resurrect it
    // Dash Style
    content += "<div class='divContentConf'>";
    content += "<div style='clear:both; padding-top:10px;'></div>";
    content += "<div class='divll' style='width:140px;font-weight:bold;color:#59899e;'>Dash Style:</div>";
    content += "<div class='divl dropdown' style='width:90px; text-align:left;'><button id='ConfDash' class='btn dropdown-toggle' style='background-color:rgb(255,255,255);' type='button' data-toggle='dropdown'></button><ul class='dropdown-menu' style='height: 400px; overflow: scroll; margin: 0; padding: 0; min-width: 90px;'>";
    for (let i = 0; i <= dashStyles.length; ++i) {
        content += `<li>&nbsp;${dashStyles[i]}&nbsp;</li>`;
    }
    content += '</ul></div>';
    content += '</div>';
    */

    tabPane.innerHTML = content;
    tabPane.id = 'tab-colorspeeds';

    // Fix tab content div spacing.
    // $(tabPane).parent().css({ width: 'auto', padding: '4px' });

    await W.userscripts.waitForElementConnected(tabPane);
    if (debug) log('Tab loaded');

    createNewSpeedColorDialog();

    getId('divadd').innerHTML += (`<br/><center><input type='button' id='addbutton' name='add' value='${CSlang[4][CSI18n]}' /></center>`);

    getId('addbutton').onclick = (() => {
        getId('Conf_Others').style.display = 'none';
        getId('Conf_Color').style.display = 'block';
        getId('colorspeedsDiv').style.display = 'none';
        getId('newspeed').value = '';
        getId('ConfColor').style.backgroundColor = '#fff';
        newspeedColorDialog.style.display = 'block';
        let c = getId('ConfColor').style.backgroundColor;
        c = color2Rgb(c);
        actualiseColorRGB(c);
    });

    if (debug) log(`Country = ${getTopCountry().attributes.name}`);

    getId('cbPaletteByCountrie').checked = WMECSpeeds.PaletteByCountrie;
    getId('selectCountrie').style.display = (WMECSpeeds.PaletteByCountrie) ? 'block' : 'none';

    getId('stateChoise').style.display = (getTopCountry().attributes.name === 'United States') ? 'block' : 'none';

    if (WMECSpeeds.MultiplePalette === true) {
        let index = 0;
        const stateToSelect = getTopState().attributes.name.replace(/ /g, '_');
        for (index; getId('selectState').options[index].value !== stateToSelect; index++) { /* empty */ }
        getId('selectState').options[index].selected = true;
    }

    getId('valOffset').value = WMECSpeeds.offsetValue;
    getId('sliderOffset').value = WMECSpeeds.offsetValue;

    getId('valOpacity').value = Number(WMECSpeeds.opacityValue * 100).toFixed(0);
    getId('sliderOpacity').value = Number(WMECSpeeds.opacityValue * 100).toFixed(0);

    getId('valThickness').value = WMECSpeeds.thicknessValue;
    getId('sliderThickness').value = WMECSpeeds.thicknessValue;

    LoadSettings();

    eventRegister();

    SCColor();
}

function eventRegister() {
    CSpeedsWaze.selectionManager.events.register('selectionchanged', null, SCColor);
    CSpeedsModel.actionManager.events.register('afterclearactions', null, SCColor);
    CSpeedsModel.actionManager.events.register('afterundoaction', null, SCColor);
    CSpeedsMap.olMap.events.register('zoomend', null, SCColor);
    CSpeedsMap.olMap.events.register('moveend', null, SCColor);

    CSpeedsModel.events.register('mergeend', null, SCColor);
    window.addEventListener('beforeunload', saveOption, false);
}

function eventUnRegister() {
    CSpeedsWaze.selectionManager.events.unregister('selectionchanged', null, SCColor);
    CSpeedsModel.actionManager.events.unregister('afterclearactions', null, SCColor);
    CSpeedsModel.actionManager.events.unregister('afterundoaction', null, SCColor);
    CSpeedsMap.olMap.events.unregister('zoomend', null, SCColor);
    CSpeedsMap.olMap.events.unregister('moveend', null, SCColor);
    CSpeedsModel.events.unregister('mergeend', null, SCColor);
    window.removeEventListener('beforeunload', saveOption, false);
}

function LoadSettings() {
    getId('cbPaletteByCountrie').checked = WMECSpeeds.PaletteByCountrie;
    getId('selectCountrie').style.display = (WMECSpeeds.PaletteByCountrie) ? 'block' : 'none';

    getId('cbMultiplePalette').checked = WMECSpeeds.MultiplePalette;
    getId('selectState').style.display = (WMECSpeeds.MultiplePalette) ? 'block' : 'none';

    if (WMECSpeeds.MultiplePalette === false && WMECSpeeds.PaletteByCountrie === false) {
        Object.keys(WMECSpeeds.speedColors[unit]).forEach(valSpeed => {
            const color = WMECSpeeds.speedColors[unit][valSpeed];
            const div = document.createElement('div');
            div.className = 'divContent';

            const divspeed = document.createElement('div');
            divspeed.className = 'divl speed';
            divspeed.style.width = '60px';
            divspeed.innerHTML = valSpeed;
            div.appendChild(divspeed);

            const divsuppr = document.createElement('div');
            divsuppr.className = 'divr';
            divsuppr.style.width = '20px';

            const divsuppra = document.createElement('a');
            divsuppra.innerHTML = `<img style='width:20px;' title='${CSlang[5][CSI18n]}' src='data:image/png;base64,${iconDelete}' />`;
            divsuppra.href = '#';
            divsuppra.className = 'delSpeed';
            divsuppra.id = `delSpeed_${valSpeed}`;
            divsuppr.appendChild(divsuppra);
            div.appendChild(divsuppr);

            const divedit = document.createElement('div');
            divedit.className = 'divr';
            divedit.style.width = '20px';

            const divedita = document.createElement('a');
            divedita.innerHTML = `<img style='width:16px;' title='${CSlang[8][CSI18n]}' src='data:image/png;base64,${iconEdit}' />`;
            divedita.href = '#';
            divedita.onclick = getFunctionWithArgs(CSModifCouleur, [unit, valSpeed, color, null]);
            divedit.appendChild(divedita);
            div.appendChild(divedit);

            const divcolor = document.createElement('div');
            divcolor.className = 'divr';
            divcolor.style.width = '120px';
            divcolor.innerHTML = `<div class='divcolor' style='background-color:${color};'>&nbsp;</div>`;
            div.appendChild(divcolor);

            getId('CStable').appendChild(div);
        });

    // log("LoadSettings WMECSpeeds.speedColors."+unit+" = ",WMECSpeeds.speedColors[unit]);
    }
    if (WMECSpeeds.MultiplePalette === true && WMECSpeeds.PaletteByCountrie === false) {
        selectedState = getId('selectState').options[getId('selectState').selectedIndex].value;
        if (debug) log('selectedState = ', selectedState);

        if (WMECSpeeds.speedColors.US[selectedState][unit] === undefined) {
            WMECSpeeds.speedColors.US[selectedState][unit] = cloneObj(WMECSpeeds.speedColors[unit]);
        }

        Object.keys(WMECSpeeds.speedColors.US[selectedState][unit]).forEach(valSpeed => {
            const color = WMECSpeeds.speedColors.US[selectedState][unit][valSpeed];
            const div = document.createElement('div'); div.className = 'divContent';
            const divspeed = document.createElement('div'); divspeed.className = 'divl speed'; divspeed.style.width = '60px'; divspeed.innerHTML = valSpeed;
            div.appendChild(divspeed);

            const divsuppr = document.createElement('div'); divsuppr.className = 'divr'; divsuppr.style.width = '20px';
            const divsuppra = document.createElement('a');
            divsuppra.innerHTML = `<img style='width:20px;' title='${CSlang[5][CSI18n]}' src='data:image/png;base64,${iconDelete}' />`;
            divsuppra.href = '#'; divsuppra.className = 'delSpeed'; divsuppra.id = `delSpeed_${valSpeed}`;
            divsuppr.appendChild(divsuppra);
            div.appendChild(divsuppr);

            const divedit = document.createElement('div'); divedit.className = 'divr'; divedit.style.width = '20px';
            const divedita = document.createElement('a');
            divedita.innerHTML = `<img style='width:16px;' title='${CSlang[8][CSI18n]}' src='data:image/png;base64,${iconEdit}' />`;
            divedita.href = '#';
            divedita.onclick = getFunctionWithArgs(CSModifCouleur, [unit, valSpeed, color, selectedState]);
            divedit.appendChild(divedita);
            div.appendChild(divedit);

            const divcolor = document.createElement('div'); divcolor.className = 'divr'; divcolor.style.width = '120px';
            divcolor.innerHTML = `<div class='divcolor' style='background-color:${color};'>&nbsp;</div>`;
            div.appendChild(divcolor);
            getId('CStable').appendChild(div);
        });
        if (debug) log(`LoadSettings WMECSpeeds.speedColors.US.${selectedState}.${unit} = `, WMECSpeeds.speedColors.US[selectedState][unit]);
    }

    if (WMECSpeeds.PaletteByCountrie === true && WMECSpeeds.MultiplePalette === false) {
        if (getId('selectCountrie').options[getId('selectCountrie').selectedIndex] !== undefined) {
            selectedCountry = getId('selectCountrie').options[getId('selectCountrie').selectedIndex].value;
        } else selectedCountry = getTopCountry().attributes.name.replace(/ /g, '_');

        log('selectCountrie = ', selectedCountry);

        if (WMECSpeeds.speedColors.Countries[selectedCountry] === undefined || WMECSpeeds.speedColors.Countries[selectedCountry][unit] === undefined) {
            WMECSpeeds.speedColors.Countries[selectedCountry] = {};
            WMECSpeeds.speedColors.Countries[selectedCountry][unit] = cloneObj(WMECSpeeds.speedColors[unit]);
            updateCountrieList();
            // log("LoadSettings création WMECSpeeds.speedColors.Countries."+selectedCountrie+"."+unit+" = ",WMECSpeeds.speedColors.Countries[selectedCountrie][unit]);
        }

        Object.keys(WMECSpeeds.speedColors.Countries[selectedCountry][unit]).forEach(valSpeed => {
            const color = WMECSpeeds.speedColors.Countries[selectedCountry][unit][valSpeed];
            const div = document.createElement('div'); div.className = 'divContent';
            const divspeed = document.createElement('div'); divspeed.className = 'divl speed'; divspeed.style.width = '60px'; divspeed.innerHTML = valSpeed;
            div.appendChild(divspeed);

            const divsuppr = document.createElement('div'); divsuppr.className = 'divr'; divsuppr.style.width = '20px';
            const divsuppra = document.createElement('a');

            divsuppra.innerHTML = `<img style='width:20px;' title='${CSlang[5][CSI18n]}' src='data:image/png;base64,${iconDelete}' />`;
            divsuppra.href = '#'; divsuppra.className = 'delSpeed'; divsuppra.id = `delSpeed_${valSpeed}`;
            divsuppr.appendChild(divsuppra);
            div.appendChild(divsuppr);

            const divedit = document.createElement('div'); divedit.className = 'divr'; divedit.style.width = '20px';
            const divedita = document.createElement('a');
            divedita.innerHTML = `<img style='width:16px;' title='${CSlang[8][CSI18n]}' src='data:image/png;base64,${iconEdit}' />`;
            divedita.href = '#';
            divedita.onclick = getFunctionWithArgs(CSModifCouleur, [unit, valSpeed, color, selectedCountry]);
            divedit.appendChild(divedita);
            div.appendChild(divedit);

            const divcolor = document.createElement('div'); divcolor.className = 'divr'; divcolor.style.width = '120px';
            divcolor.innerHTML = `<div class='divcolor' style='background-color:${color};'>&nbsp;</div>`;
            div.appendChild(divcolor);
            getId('CStable').appendChild(div);
        });

        // log("LoadSettings WMECSpeeds.speedColors.Countries."+selectedCountrie+"."+unit+" = ",WMECSpeeds.speedColors.Countries[selectedCountrie][unit]);
    }

    for (let i = 0; i < RoadToScan.length; ++i) {
        const type = RoadToScan[i];
        const div = document.createElement('div'); div.className = 'divContentZoom';

        const divcheck = document.createElement('div'); divcheck.className = 'divl';
        divcheck.innerHTML = `<input type="checkbox" style="margin:1px 1px;" class="CScheck" id="cbRoad${type}">`;
        div.appendChild(divcheck);

        const divtype = document.createElement('div');
        divtype.className = 'divl CStype';
        divtype.style.width = '130px';

        const divedit = document.createElement('div');
        divedit.className = 'divr';
        divedit.style.width = '20px';
        const divedita = document.createElement('a');
        divedita.innerHTML = `<img style='width:16px;' title='${CSlang[8][CSI18n]}' src='data:image/png;base64,${iconEdit}' />`;
        divedita.href = '#';
        divedita.className = 'modifyZoom';
        divedita.id = `zoom_${type}`;
        divedit.appendChild(divedita);

        const divzoom = document.createElement('div');
        divzoom.className = 'divr CSzoom';
        divzoom.style.width = '60px';
        divzoom.innerHTML = WMECSpeeds.typeOfRoad[type].zoom;
        divzoom.title = `${roadTypeZoomInfo[type][CSI18n]}`;

        if (type === 3) {
            divtype.innerHTML = CSlang[22][CSI18n];
            div.appendChild(divtype);
            div.appendChild(divedit);
            div.appendChild(divzoom);
        } else if (type === 6) {
            divtype.innerHTML = CSlang[23][CSI18n];
            div.appendChild(divtype);
            div.appendChild(divedit);
            div.appendChild(divzoom);
        } else if (type === 7) {
            divtype.innerHTML = CSlang[24][CSI18n];
            div.appendChild(divtype);
            div.appendChild(divedit);
            div.appendChild(divzoom);
        } else if (type === 4) {
            divtype.innerHTML = CSlang[25][CSI18n];
            div.appendChild(divtype);
            div.appendChild(divedit);
            div.appendChild(divzoom);
        } else if (type === 2) {
            divtype.innerHTML = CSlang[26][CSI18n];
            div.appendChild(divtype);
            div.appendChild(divedit);
            div.appendChild(divzoom);
        } else if (type === 1) {
            divtype.innerHTML = CSlang[27][CSI18n];
            div.appendChild(divtype);
            div.appendChild(divedit);
            div.appendChild(divzoom);
        } else if (type === 22) {
            divtype.innerHTML = CSlang[28][CSI18n];
            div.appendChild(divtype);
            div.appendChild(divedit);
            div.appendChild(divzoom);
        } else if (type === 20) {
            divtype.innerHTML = CSlang[29][CSI18n];
            div.appendChild(divtype);
            div.appendChild(divedit);
            div.appendChild(divzoom);
        } else if (type === 17) {
            divtype.innerHTML = CSlang[30][CSI18n];
            div.appendChild(divtype);
            div.appendChild(divedit);
            div.appendChild(divzoom);
        } else if (type === 8) {
            divtype.innerHTML = CSlang[31][CSI18n];
            div.appendChild(divtype);
            div.appendChild(divedit);
            div.appendChild(divzoom);
        } else if (type === 999) {
            divtype.innerHTML = CSlang[18][CSI18n];
            div.appendChild(divtype);
        }

        getId('CSroadType').appendChild(div);
        getId(`cbRoad${type}`).checked = WMECSpeeds.typeOfRoad[type].checked;
        // getId(`cbRoad${type}`).style.marginLeft = '2px';
        // getId(`cbRoad${type}`).style.marginTop = '2px';
        // getId(`cbRoad${type}`).style.width = '15px';
        // getId(`cbRoad${type}`).style.height = '15px';

        getId(`cbRoad${type}`).onclick = (() => {
            SCColor();
        });
    }
    if (debug) log('Settings Loaded');
    setupHandler();
}

function setupHandler() {
    let rgb = {
        r: 0, g: 0, b: 0, name: null
    };
    const listeDelSpeed = getId('CStable');
    const btnDelSpeed = getElementsByClassName('delSpeed', listeDelSpeed);

    for (let i = 0; i < btnDelSpeed.length; i++) {
        const target = btnDelSpeed[i];
        const index = target.id.split('_')[1];
        target.onclick = getFunctionWithArgs(SCSpeeds, [unit, index, selectedState, selectedCountry]);
    }

    const listeEditZoom = getId('CSroadType');
    const btnEditZoom = getElementsByClassName('modifyZoom', listeEditZoom);

    for (let i = 0; i < btnEditZoom.length; i++) {
        const target = btnEditZoom[i];
        const index = target.id.split('_')[1];
        const val = WMECSpeeds.typeOfRoad[parseInt(index, 10)].zoom;
        target.onclick = getFunctionWithArgs(SCEditZoom, [index, val]);
    }

    getId('cbPaletteByCountrie').onclick = (() => {
        getId('selectCountrie').style.display = (getId('cbPaletteByCountrie').checked) ? 'block' : 'none';
        WMECSpeeds.PaletteByCountrie = getId('cbPaletteByCountrie').checked;
        WMECSpeeds.MultiplePalette = false;
        updateCountrieList();
        getId('CStable').innerHTML = '';
        getId('CSroadType').innerHTML = '';
        LoadSettings();
        SCColor();
    });
    getId('selectCountrie').onclick = (() => {
        updateCountrieList();
        getId('CStable').innerHTML = '';
        getId('CSroadType').innerHTML = '';
        LoadSettings();
    });

    getId('cbMultiplePalette').onclick = (() => {
        getId('selectState').style.display = (getId('cbMultiplePalette').checked) ? 'block' : 'none';
        WMECSpeeds.MultiplePalette = getId('cbMultiplePalette').checked;
        WMECSpeeds.PaletteByCountrie = false;
        if (WMECSpeeds.MultiplePalette === true) {
            const stateToSelect = getTopState().attributes.name.replace(/ /g, '_');
            let index;
            for (index = 0; getId('selectState').options[index].value !== stateToSelect; index++) { /* empty */ }
            getId('selectState').options[index].selected = true;
        }
        getId('CStable').innerHTML = '';
        getId('CSroadType').innerHTML = '';
        LoadSettings();
        SCColor();
    });

    getId('selectState').onclick = (() => {
        getId('CStable').innerHTML = '';
        getId('CSroadType').innerHTML = '';
        LoadSettings();
    });

    getId('edit_others').onclick = (() => {
        getId('Conf_Others').style.display = 'block';
        getId('Conf_Color').style.display = 'none';
        getId('colorspeedsDiv').style.display = 'none';
        getId('newspeed').value = null;
        getId('ConfColor').style.backgroundColor = WMECSpeeds.speedColors.Others;
        getId('newspeedColorDialog').style.display = 'block';
        rgb = color2Rgb(WMECSpeeds.speedColors.Others);
        actualiseColorRGB(rgb);
    });

    getId('cancel').onclick = (() => {
        getId('Conf_Others').style.display = 'none';
        getId('Conf_Color').style.display = 'none';
        getId('newspeedColorDialog').style.display = 'none';
        getId('colorspeedsDiv').style.display = 'block';
        getId('newspeed').value = '';
    });

    getId('submit').onclick = (() => {
        let newSpeed = getId('newspeed').value;
        let newColor = getId('ConfColor').style.backgroundColor;
        // log("newSpeed = ", newSpeed);log("newColor = ", newColor);
        if (getId('Conf_Color').style.display === 'block' && newSpeed && newColor) {
            if (WMECSpeeds.MultiplePalette === true) {
                WMECSpeeds.speedColors.US[selectedState][unit][newSpeed] = newColor;
            } else if (WMECSpeeds.PaletteByCountrie === true) {
                WMECSpeeds.speedColors.Countries[selectedCountry][unit][newSpeed] = newColor;
            } else if (WMECSpeeds.MultiplePalette === false && WMECSpeeds.PaletteByCountrie === false) {
                WMECSpeeds.speedColors[unit][newSpeed] = newColor;
            }
        }
        if (getId('Conf_Others').style.display === 'block' && newColor) {
            WMECSpeeds.speedColors.Others = newColor;
            getId('color_others').style.backgroundColor = WMECSpeeds.speedColors.Others;
        }
        getId('newspeed').value = '';
        newSpeed = null;
        newColor = null;
        getId('CStable').innerHTML = '';
        getId('CSroadType').innerHTML = '';
        getId('Conf_Others').style.display = 'none';
        getId('Conf_Color').style.display = 'none';
        getId('newspeedColorDialog').style.display = 'none';
        getId('colorspeedsDiv').style.display = 'block';
        LoadSettings();
        SCColor();
    });

    $('#ConfColor.dropdown-toggle').dropdown();
    $('#ConfColor+.dropdown-menu li').click(function() {
        getId('ConfColor').style.backgroundColor = this.style.backgroundColor;
        rgb = color2Rgb(this.style.backgroundColor);
        actualiseColorRGB(rgb);
    });
    /*
  $("#ConfDash.dropdown-toggle").dropdown();
  $('#ConfDash+.dropdown-menu li').click(function(){
      getId('ConfDash').text=this.text;
  });
  */
    getId('sliderRed').onmousemove = () => {
        getId('valRed').value = getId('sliderRed').value;
        rgb.r = getId('valRed').value;
        rgb.g = getId('valGreen').value;
        rgb.b = getId('valBlue').value;
        rgb = color2Rgb(Rgb2String(rgb));
        actualiseColorRGB(rgb);
    };
    getId('sliderGreen').onmousemove = () => {
        getId('valGreen').value = getId('sliderGreen').value;
        rgb.r = getId('valRed').value;
        rgb.g = getId('valGreen').value;
        rgb.b = getId('valBlue').value;
        rgb = color2Rgb(Rgb2String(rgb));
        actualiseColorRGB(rgb);
    };
    getId('sliderBlue').onmousemove = () => {
        getId('valBlue').value = getId('sliderBlue').value;
        rgb.r = getId('valRed').value;
        rgb.g = getId('valGreen').value;
        rgb.b = getId('valBlue').value;
        rgb = color2Rgb(Rgb2String(rgb));
        actualiseColorRGB(rgb);
    };
    getId('sliderOffset').onmousemove = () => {
        WMECSpeeds.offsetValue = getId('sliderOffset').value;
        getId('valOffset').value = getId('sliderOffset').value;
        SCColor();
    };
    getId('sliderOpacity').onmousemove = () => {
        WMECSpeeds.opacityValue = Number(getId('sliderOpacity').value / 100).toFixed(2);
        getId('valOpacity').value = getId('sliderOpacity').value;
        SCColor();
    };
    getId('sliderThickness').onmousemove = () => {
        WMECSpeeds.thicknessValue = getId('sliderThickness').value;
        getId('valThickness').value = getId('sliderThickness').value;
        SCColor();
    };

    getId('valRed').onchange = () => {
        const R = parseInt(getId('valRed').value, 10);
        if ((R >= 0) && (R <= 255)) {
            getId('sliderRed').value = getId('valRed').value;
            rgb.r = getId('valRed').value;
            rgb.g = getId('valGreen').value;
            rgb.b = getId('valBlue').value;
            rgb = color2Rgb(Rgb2String(rgb));
            actualiseColorRGB(rgb);
        } else {
            getId('valRed').value = getId('sliderRed').value;
        }
    };

    getId('valGreen').onchange = () => {
        const G = parseInt(getId('valGreen').value, 10);
        if ((G >= 0) && (G <= 255)) {
            getId('sliderGreen').value = getId('valGreen').value;
            rgb.r = getId('valRed').value;
            rgb.g = getId('valGreen').value;
            rgb.b = getId('valBlue').value;
            rgb = color2Rgb(Rgb2String(rgb));
            actualiseColorRGB(rgb);
        } else {
            getId('valGreen').value = getId('sliderGreen').value;
        }
    };
    getId('valBlue').onchange = () => {
        const B = parseInt(getId('valBlue').value, 10);
        if ((B >= 0) && (B <= 255)) {
            getId('sliderBlue').value = getId('valBlue').value;
            rgb.r = getId('valRed').value;
            rgb.g = getId('valGreen').value;
            rgb.b = getId('valBlue').value;
            rgb = color2Rgb(Rgb2String(rgb));
            actualiseColorRGB(rgb);
        } else {
            getId('valBlue').value = getId('sliderBlue').value;
        }
    };
    getId('valOffset').onchange = () => {
        const R = parseInt(getId('valOffset').value, 10);
        if ((R >= 1) && (R <= 10)) {
            getId('sliderOffset').value = getId('valOffset').value;
            WMECSpeeds.offsetValue = getId('valOffset').value;
            SCColor();
        } else {
            getId('valOffset').value = getId('sliderOffset').value;
        }
    };
    getId('valOpacity').onchange = () => {
        const R = parseInt(getId('valOpacity').value, 10);
        if ((R >= 0) && (R <= 100)) {
            getId('sliderOpacity').value = getId('valOpacity').value;
            WMECSpeeds.opacityValue = Number(getId('valOpacity').value / 100).toFixed(2);
            SCColor();
        } else {
            getId('valOpacity').value = getId('sliderOpacity').value;
        }
    };
    getId('valThickness').onchange = () => {
        const R = parseInt(getId('valThickness').value, 10);
        if ((R >= 2) && (R <= 10)) {
            getId('sliderThickness').value = getId('valThickness').value;
            WMECSpeeds.thicknessValue = getId('valThickness').value;
            SCColor();
        } else {
            getId('valThickness').value = getId('sliderThickness').value;
        }
    };
}

function updateCountrieList() {
    const selectCountrie = getId('selectCountrie');
    let current = null;
    if (selectCountrie.selectedIndex >= 0) current = selectCountrie.options[selectCountrie.selectedIndex].value;
    if (current === null) current = getTopCountry().attributes.name.replace(/ /g, '_');

    selectCountrie.options.length = 0;

    for (var countrie in WMECSpeeds.speedColors.Countries) {
        // create option in select menu
        if (countrie === undefined) countrie = getTopCountry().attributes.name.replace(/ /g, '_');
        var countrieOption = document.createElement('option');
        var countrieText = document.createTextNode(countrie.replace(/_/g, ' '));

        if (current !== null && countrie == current)
            countrieOption.setAttribute('selected', true);
        countrieOption.setAttribute('value', countrie);
        countrieOption.appendChild(countrieText);
        selectCountrie.appendChild(countrieOption);

    }
}

function CSModifCouleur(unit, id, color, state) {
    getId('Conf_Others').style.display = 'none';
    getId('Conf_Color').style.display = 'block';
    getId('colorspeedsDiv').style.display = 'none';
    getId('newspeed').value = id;
    getId('ConfColor').style.backgroundColor = color;
    newspeedColorDialog.style.display = 'block';
    const c = color2Rgb(color);
    actualiseColorRGB(c);
}

function actualiseColorRGB(c) {
    log('color: ', c);
    getId('valRed').value = c.r;
    getId('valGreen').value = c.g;
    getId('valBlue').value = c.b;

    getId('sliderRed').value = c.r;
    getId('sliderGreen').value = c.g;
    getId('sliderBlue').value = c.b;
    getId('ConfColor').style.backgroundColor = Rgb2String(c);
    getId('nameColor').innerHTML = c.name;
}

function SCSpeeds(unit, idx, state, contrie){
    if (WMECSpeeds.MultiplePalette === true){
        var answer = window.confirm(CSlang[5][CSI18n] + ' ' + idx + ' ' + unit + ' ' + CSlang[21][CSI18n] + ' ' + state + ' ?');
    }else if (WMECSpeeds.PaletteByCountrie === true){
        var answer = window.confirm(CSlang[5][CSI18n] + ' ' + idx + ' ' + unit + ' ' + CSlang[21][CSI18n] + ' ' + contrie + ' ?');
    }else{var answer = window.confirm(CSlang[5][CSI18n] + ' ' + idx + ' ' + unit + ' ?');}

    if (answer){
        if (WMECSpeeds.MultiplePalette === true){
            delete WMECSpeeds.speedColors.US[state][unit][idx];
        }else if (WMECSpeeds.PaletteByCountrie === true){
            delete WMECSpeeds.speedColors.Countries[contrie][unit][idx];
        }else {delete WMECSpeeds.speedColors[unit][idx];}

        getId('CStable').innerHTML = '';
        getId('CSroadType').innerHTML = '';
        LoadSettings();
    }
}

function SCEditZoom(idx, val){
    getId('editzoom').style.display = 'block';
    getId('newvalzoom').value = val;
    getId('texttype').textContent = WMECSpeeds.typeOfRoad[idx].name;

    getId('submitZoom').onclick = (function(){
        var newValZoom = getId('newvalzoom').value;
        if (newValZoom) {
            WMECSpeeds.typeOfRoad[idx].zoom = newValZoom;
        }
        getId('editzoom').style.display = 'none';
        getId('newvalzoom').value = '';
        getId('CStable').innerHTML = '';
        getId('CSroadType').innerHTML = '';
        LoadSettings();
    });
    getId('cancelZoom').onclick = (function(){
        getId('editzoom').style.display = 'none';
        getId('newvalzoom').value = '';
        getId('CStable').innerHTML = '';
        getId('CSroadType').innerHTML = '';
        LoadSettings();
    });
}

function shiftGeometry(d, line, trigo) // d=distance to shift, line=collection of OL points, trigo=boolean: true=left(trigo=CCW) false=right(CW) : fwd is CW, rev is trigo
{
    if (!trigo)
        d = -d;

    function getOrthoVector(p1, p2)
    {
        return [p1.y - p2.y, p2.x - p1.x];
    }

    function normalizeVector(v)
    {
        if (v[0] * v[0] + v[1] * v[1] == 0)
            return v;
        var l = Math.sqrt(v[0] * v[0] + v[1] * v[1]);
        return [v[0] / l, v[1] / l];
    }

    var points = [];
    for (var i = 0; i < line.length; i++)
    {
        var vcount = 0;
        // compute orthogonal vectors:
        var prevVector = [0, 0];
        var nextVector = [0, 0];
        if (i > 0) // can compute prev
        {
            var p1 = line[i - 1];
            var p2 = line[i];
            prevVector = getOrthoVector(p1, p2);
            prevVector = normalizeVector(prevVector);
            vcount++;
        }
        if (i < line.length - 1) // can compute next
        {
            var p1 = line[i];
            var p2 = line[i + 1];
            nextVector = getOrthoVector(p1, p2);
            nextVector = normalizeVector(nextVector);
            vcount++;
        }
        // sum vectors and normalize
        var v = [0, 0];
        if (vcount != 0)
            v = [(prevVector[0] + nextVector[0]) / vcount, (prevVector[1] + nextVector[1]) / vcount];
        //v=normalizeVector(v);
        points.push(new CSpeedOpenLayers.Geometry.Point(line[i].x + v[0] * d, line[i].y + v[1] * d));
    }
    return points;
}

function SCColor() {
    function getByID(obj, id){
        if (typeof(obj.getObjectById) == 'function'){
            return obj.getObjectById(id);
        }else if (typeof(obj.getObjectById) == 'undefined'){
            return obj.get(id);
        }
    }
    //log('SCColor');
    try { mapLayer.destroyFeatures();
    }catch(err){log('err destroyFeatures: ', err);}

    if (getTopCountry() === null) return;

    if ( CSpeedsCountries !== undefined && /*CSpeedsCountries.top*/getTopCountry() !== undefined){
        getId('stateChoise').style.display = (/*CSpeedsCountries.top*/getTopCountry().attributes.name == 'United States') ? 'block' : 'none';
    }
    var lineFeature = [];

    for (var i = 0; i < RoadToScan.length; ++i){
        var type = RoadToScan[i];
        WMECSpeeds.typeOfRoad[type].checked = getId('cbRoad' + type).checked;
    }

    for (var seg in CSpeedsModel.segments.objects) {
        var segment = getByID(CSpeedsModel.segments, seg);
        var attributes = segment.attributes;
        var roadType = attributes.roadType;
        var roundabout = (attributes.junctionID === null) ? false : true;
        var line = getId(segment.getOLGeometry().id);
        var fwdspeed = attributes.fwdMaxSpeed;
        var revspeed = attributes.revMaxSpeed;
        var fwdspeedUnverified = attributes.fwdMaxSpeedUnverified;
        var revspeedUnverified = attributes.revMaxSpeedUnverified;
        var fwddir = attributes.fwdDirection;
        var revdir = attributes.revDirection;
        //var fwdID = "",revID="";
        var isSelected = (segment.selected == true) ? true : false;
        var isModified = (segment.state == 'Update') ? true : false;

        if (attributes.primaryStreetID === null || attributes.primaryStreetID === undefined) continue;

        if (getByID(CSpeedsModel.streets, attributes.primaryStreetID) === null || getByID(CSpeedsModel.streets, attributes.primaryStreetID) === undefined){
            if (debug) log('CSpeedsModel.streets.get(' + attributes.primaryStreetID + ') =', getByID(CSpeedsModel.streets, attributes.primaryStreetID));
            continue;
        }

        var cid = getByID(CSpeedsModel.streets, attributes.primaryStreetID).attributes.cityID;
        var stateID = null;
        var countryID = null;

        if (getByID(CSpeedsModel.cities, cid) === null || getByID(CSpeedsModel.cities, cid) === undefined){
            if (debug) log('CSpeedsModel.cities.get(' + cid + ') =', getByID(CSpeedsModel.cities, cid));
            continue;
        }

        stateID = getByID(CSpeedsModel.cities, cid).attributes.stateID;
        countryID = getByID(CSpeedsModel.cities, cid).attributes.countryID;

        var state = getByID(CSpeedsModel.states, stateID).attributes.name.replace(/ /g, '_');
        var countrie = getByID(CSpeedsModel.countries, countryID).attributes.name.replace(/ /g, '_');

        if (WMECSpeeds.PaletteByCountrie == true && WMECSpeeds.speedColors.Countries[countrie] === undefined){
            WMECSpeeds.speedColors.Countries[countrie] = {};
            WMECSpeeds.speedColors.Countries[countrie][unit] = cloneObj(WMECSpeeds.speedColors[unit]);
            updateCountrieList();
            LoadSettings();
            log('SCColor WMECSpeeds.speedColors.Countries.' + countrie + '.' + unit + ' = ', WMECSpeeds.speedColors.Countries[countrie][unit]);
        }

        if (WMECSpeeds.MultiplePalette == true && WMECSpeeds.speedColors.US[state] !== undefined && WMECSpeeds.speedColors.US[state][unit] === undefined){
            WMECSpeeds.speedColors.US[state][unit] = cloneObj(WMECSpeeds.speedColors[unit]);
            //log("SCColor WMECSpeeds.speedColors.US."+state+"."+unit+" = ",WMECSpeeds.speedColors.US[state][unit]);
        }

        // check that WME hasn't highlighted this segment
        if (isSelected || isModified) continue;

        if (zoom != CSpeedsMap.olMap.zoom) {
            zoom = CSpeedsMap.olMap.zoom;
            //log('zoom = ' + zoom + 'W.map.getResolution() = '+W.map.getResolution());
        }
        var shiftValue = WMECSpeeds.offsetValue * W.map.getResolution();

        if (RoadToScan.indexOf(roadType) == -1 ) continue;
        if ((roundabout != false) && (WMECSpeeds.typeOfRoad['999'].checked == false)) continue;

        if (unit == 'mph'){
            fwdspeed = (fwdspeed != null) ? (Math.trunc(fwdspeed * 0.625)) : null;
            revspeed = (revspeed != null) ? (Math.trunc(revspeed * 0.625)) : null;
        }
        //log("fwdspeed= "+ fwdspeed + " " + unit + " ;  revspeed= " + revspeed + " " + unit);

        // turn off highlights when roads are no longer visible

        if ((zoom < WMECSpeeds.typeOfRoad[roadType].zoom) || !WMECSpeeds.typeOfRoad[roadType].checked) {
            continue;
        }
        WMECSpeeds.visibility = mapLayer.visibility;

        if (fwdspeed && WMECSpeeds.visibility) {
            //Color for forward speed
            var newWidth = '', newColor = '', newDashes = '', newOpacity = '';

            if (WMECSpeeds.MultiplePalette === false && WMECSpeeds.PaletteByCountrie === false){
                if (WMECSpeeds.speedColors[unit].hasOwnProperty(fwdspeed)) newColor = WMECSpeeds.speedColors[unit][fwdspeed];
            }else if (WMECSpeeds.PaletteByCountrie === true){
                if (WMECSpeeds.speedColors.Countries[countrie][unit].hasOwnProperty(fwdspeed)) newColor = WMECSpeeds.speedColors.Countries[countrie][unit][fwdspeed];
            }else if (WMECSpeeds.MultiplePalette === true && WMECSpeeds.speedColors.US[state] !== undefined){
                if (WMECSpeeds.speedColors.US[state][unit].hasOwnProperty(fwdspeed)) newColor = WMECSpeeds.speedColors.US[state][unit][fwdspeed];
            }
            /*
          if (newColor!=""){
            //Dashes
            if (fwddir==true && fwdspeed && !fwdspeedUnverified) { newWidth = 6; newOpacity = 0.8; newDashes = "5 10"; } // verified speed
            else if (fwddir==true && fwdspeed && fwdspeedUnverified) { newColor = WMECSpeeds.speedColors.Others; newWidth = 4; newOpacity = 0.8; newDashes = "2 10";} // unverified speed
          }else if (fwddir==true && fwdspeed) { newWidth = 4; newColor = WMECSpeeds.speedColors.Others; newOpacity = 0.9; newDashes = "5 5"; } // other
          */
            if (newColor != ''){
            //Dashes
                if (fwddir == true && fwdspeed && !fwdspeedUnverified) { newWidth = WMECSpeeds.thicknessValue; newOpacity = WMECSpeeds.opacityValue; newDashes = '5 10'; } // verified speed
                else if (fwddir == true && fwdspeed && fwdspeedUnverified) { newColor = WMECSpeeds.speedColors.Others; newWidth = WMECSpeeds.thicknessValue; newOpacity = 0.8; newDashes = '2 10';} // unverified speed
            }else if (fwddir == true && fwdspeed) { newWidth = WMECSpeeds.thicknessValue; newColor = WMECSpeeds.speedColors.Others; newOpacity = WMECSpeeds.opacityValue; newDashes = '5 5'; } // other

            if (newColor != ''){
                var style = {
                    strokeColor: newColor,
                    strokeOpacity: newOpacity,
                    strokeWidth: newWidth,
                    strokeDashstyle: newDashes
                };

                var points = [];
                var segID = attributes.id;
                points = shiftGeometry(shiftValue, segment.getOLGeometry().getVertices(), CSpeedsModel.getTopCountry().getAttribute('leftHandTraffic'));

                var newline = new CSpeedOpenLayers.Geometry.LineString(points);

                lineFeature.push(new CSpeedOpenLayers.Feature.Vector(newline, null, style));
            //log("segment id: " + attributes.id + ' newColor: '+ newColor + ' segment.CSpeedsFwd.fwdColor: ' + segment.CSpeedsFwd.fwdColor + ' lineFeature: ',lineFeature);
            }
        }
        if (revspeed && WMECSpeeds.visibility) {
            //Color for reverse speed
            var newWidth = '', newColor = '', newDashes = '', newOpacity = '', newDashOffset = '';

            if (WMECSpeeds.MultiplePalette === false && WMECSpeeds.PaletteByCountrie === false){
                if (WMECSpeeds.speedColors[unit].hasOwnProperty(revspeed)) newColor = WMECSpeeds.speedColors[unit][revspeed];
            }else if (WMECSpeeds.PaletteByCountrie === true){
                if (WMECSpeeds.speedColors.Countries[countrie][unit].hasOwnProperty(revspeed)) newColor = WMECSpeeds.speedColors.Countries[countrie][unit][revspeed];
            }else if (WMECSpeeds.MultiplePalette === true && WMECSpeeds.speedColors.US[state] !== undefined){
                if (WMECSpeeds.speedColors.US[state][unit].hasOwnProperty(revspeed)) newColor = WMECSpeeds.speedColors.US[state][unit][revspeed];
            }
            /*
            if (newColor!=""){
                //Dashes
                if (revdir==true && revspeed && !revspeedUnverified) { newWidth = 6; newOpacity = 0.8; newDashes = "5 10"; } // verified speed
                else if (revdir==true && revspeed && revspeedUnverified) { newColor = WMECSpeeds.speedColors.Others; newWidth = 4; newOpacity = 0.8; newDashes = "2 10";} // unverified speed
            }else if (revdir==true && revspeed) { newWidth = 4; newColor = WMECSpeeds.speedColors.Others; newOpacity = 0.9; newDashes = "5 5"; } // other
            */
            if (newColor != ''){
                //Dashes
                if (revdir == true && revspeed && !revspeedUnverified) { newWidth = WMECSpeeds.thicknessValue; newOpacity = WMECSpeeds.opacityValue; newDashes = '5 10'; } // verified speed
                else if (revdir == true && revspeed && revspeedUnverified) { newColor = WMECSpeeds.speedColors.Others; newWidth = WMECSpeeds.thicknessValue; newOpacity = WMECSpeeds.opacityValue; newDashes = '2 10';} // unverified speed
            }else if (revdir == true && revspeed) { newWidth = WMECSpeeds.thicknessValue; newColor = WMECSpeeds.speedColors.Others; newOpacity = WMECSpeeds.opacityValue; newDashes = '5 5'; } // other

            if (newColor != ''){
                var style = {
                    strokeColor: newColor,
                    strokeOpacity: newOpacity,
                    strokeWidth: newWidth,
                    strokeDashstyle: newDashes,
                };

                var points = [];
                var segID = attributes.id;

                points = shiftGeometry(shiftValue, segment.getOLGeometry().getVertices(), !CSpeedsModel.getTopCountry().getAttribute('leftHandTraffic'));

                var newline = new CSpeedOpenLayers.Geometry.LineString(points);

                lineFeature.push(new CSpeedOpenLayers.Feature.Vector(newline, null, style));
            }
        }

    }

    // log("lineFeature = ",lineFeature);
    // Display new array of segments
    try {
        mapLayer.addFeatures(lineFeature);
    } catch (err) { log('err addFeatures: ', err); }
    if (debug) log(`Total load time without WW of ${Math.round(performance.now() - scriptStartTime)} ms.`);
    if (debug) log(`Total load time with WW of ${Math.round(performance.now() - loadStartTime)} ms.`);
}

/* begin running the code! */
counterStart();