// ==UserScript==
// @name UROverview Plus (URO+)
// @namespace http://greasemonkey.chizzum.com
// @description Adds filtering and pop-up infobox for UR, MP and camera markers
// @include https://www.waze.com/*/editor/*
// @include https://www.waze.com/editor/*
// @include https://editor-beta.waze.com/*
// @include https://beta.waze.com/*
// @exclude https://www.waze.com/user/*editor/*
// @exclude https://www.waze.com/*/user/*editor/*
// @grant none
// @version 3.90
// ==/UserScript==
/*
TO-DO ITEMS
=======================================================================================================================
Bug fixes - MUST BE CLEARED BEFORE RELEASE
=======================================================================================================================
=======================================================================================================================
Things to be checked
=======================================================================================================================
=======================================================================================================================
Proposed functionality
=======================================================================================================================
***HIGH PRIORITY***
Convert camera XHR code to async operation
***OTHER STUFF***
"Hide All" button for feed - automatically clicks the trashcan on all visible feed entries
Allow custom alert box to be used as a confirm() replacement as well
Improve reliability of yellow/green comment marker choice
Implement some sort of UR "hotspot" marking to highlight areas of the map with significant clustering of URs
Flush settings to localStorage whenever a change is made, or at least before opening a new tab via a popup
User-defined setting presets
Extend unstacking to cameras
Place filtering
- by last user to edit
More localisation
First-run information
- show quickstart guide to URO features if no existing settings are present (i.e. new installation)
=======================================================================================================================
New functionality in progress
=======================================================================================================================
Addition of segment and place watchlist functionality
*/
/* JSHint Directives */
/* globals $: */
/* globals W: true */
/* globals I18n: */
/* globals OL: true */
/* globals OpenLayers: true */
/* globals Waze: true */
/* globals require: */
/* jshint bitwise: false */
/* jshint eqnull: true */
var uroVersion = "3.90";
var uroReleaseDate = "20160912";
// list of changes affecting all users
var uroChanges =
[
'Adding a comment to a UR no longer throws an error',
'Places locked by staff can now be filtered',
'Fix for latest fiddling Waze have done to the layer definitions',
'MP filtering by closing/not-closing editor, which I managed to break back in 3.54 without anyone noticing, now works again...'
];
// list of changes affecting only WME Beta users (at least until the next production release including these parts of the beta code...)
var uroBetaChanges =
[
];
// true enables debug output during script startup
var uroShowDebugOutput = true;
// true keeps debug output enabled after script startup
var uroPersistentDebugOutput = false;
/*
var uroRecentDebug = [];
*/
var uroCtrlsHidden = false;
var uroCurrentTab = 1;
var uroFID = -1;
var uroShownFID = -1;
var uroShownPopupType = null;
var uroInhibitSave = true;
var uroPopupTimer = -2;
var uroPopupDwellTimer = -1;
var uroPopupShown = false;
var uroPopupSuppressed = false;
var uroSetupListeners = true;
var uroRootContainer = null;
var uroPlacesRoot = null;
var uroMaskLayer = null;
var uroConfirmIntercepted = false;
var uroCustomMarkerList = [];
var uroPendingURSessionIDs = [];
var uroRequestedURSessionIDs = [];
var uroPlacesGroupsCollapsed = [];
var uroMouseInPopup = false;
var uroURControlsIdx = null;
var uroProblemControlsIdx = null;
var uroTurnsLayerIdx = null;
var uroNullCamLayer = false;
var uroNullOpenLayers = false;
var uroNullURLayer = false;
var uroNullProblemLayer = false;
var uroNullMapViewport = false;
var uroURDialogIsOpen = false;
var uroHoveredURID = null;
var uroSelectedURID = null;
var uroURReclickAttempts = 0;
var uroPendingCommentDataRefresh = false;
var uroWaitingCommentDataRefresh = false;
var uroExpectedCommentCount = null;
var uroCachedLastCommentID = null;
var uroPlaceSelected = false;
var uroAutoCentreDisabledOn = [];
var uroMouseIsDown = false;
var uroBackfilling = false;
var uroHidePopupOnPanelOpen = false;
var uroUserID = -1;
var uroURIDInURL = null;
var uroDOMHasTurnProblems = false;
var uroBetaEditor = false;
var uroWazeBitsPresent = 0;
var uroMTEMode = false;
var uroFinalisingListenerSetup = false;
var uroInitialised = false;
var uroOWL = null;
var uroDiv = null;
var uroAlerts = null;
var uroControls = null;
var uroCtrlURs = null;
var uroCtrlMPs = null;
var uroCtrlPlaces = null;
var uroCtrlCameras = null;
var uroCtrlMisc = null;
var uroCtrlHides = null;
var uroAMList = [];
var uroCWLGroups = [];
var uroCamWatchObjects = [];
var uroSegWatchObjects = [];
var uroPlaceWatchObjects = [];
var uroFriendlyAreaNames = [];
var uroAreaNameHoverTime = -1;
var uroAreaNameHoverObj = null;
var uroAreaNameOverlayShown = false;
var uroANEditHovered = false;
var uroANEditBox = null;
var uroPrevMouseX = -1;
var uroPrevMouseY = -1;
var dteControlsIdx = -1;
var dteOldestFullDrive = new Date(0);
var dteEpoch = new Date(0);
var dteTopID = '';
var dteClearHighlightsOnPanelClose = false;
var dteArmClearHighlightsOnPanelClose = false;
var dteOffset = 0;
var uroUserTabId = '';
var uroShowFeedFilter = false;
var uroTBRObj = null;
var uroBackfillQueue = [];
var uroUnstackedMasterID = null;
var uroStackList = [];
var uroStackType = null;
var uroAlertBoxStack = [];
var uroAlertBoxTickAction = null;
var uroAlertBoxCrossAction = null;
var uroAlertBoxInUse = false;
var uroNativeMarkerImage = 'problems-sc703e224cf.png';
var uroCustomURTags = ['[ROADWORKS]','[CONSTRUCTION]','[CLOSURE]','[EVENT]','[NOTE]','[WSLM]','[BOG]','[DIFFICULT]'];
var uroAltMarkers =
[
// 0 = closure
"url('data:image/png;base64,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')",
// 1 = cone
"url('data:image/png;base64,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')",
// 2 = custom text
"url('data:image/png;base64,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')",
// 3 = editor note
"url('data:image/png;base64,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')",
// 4 = event
"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAKrCAYAAAB/UOT4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AQYFgk1JWfIOgAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAABmJLR0QA/wD/AP+gvaeTAAAZj0lEQVR42u1aCXiNZ/b/kNCipWRfSi0jGlnuzc0idu3on6Gj/6ldUUWrm5R2zIzWdFq1TFHM0DJKFbETRBIhCZGb1ZI9sssiZDUJ2ZN75pw3371yIyFMwvP8/+f3PO/z5X7LOec973nf7/1++UkSg8FgMBgMBoPBYDAYDAaDwWAwGAwGg8FgMBgMBoPBYDAYDAaDwWAwGAwGg8FgMBgMBoPBYDAYDAaDwWAwGAwGg8FgMBgMBoPBYDAYDAaDwWAwGAwGg8FgMBgMBoPBYDAYDAaDwWAwGAwGg8FgMBgMBoPBYDAYDAaDwWAwGAwGg8FgMBgMBoPBYDAYDAaDwWAwGAwGg8FgMBgMBoPBYDAYDAaDwWgHdMTWafTo0QZOTk6G2ka/6bx8vc3RgQyTk759+z6Hx+7Dhw9/CR0bubu7mwwZMsSUjvSbztN1+T4DOaAO/7Vz6qWpqWm3oUOH9sJmib/7Ozs726pUKsWwYcNUeM6FjvSbztN1uo/up+fo+ScNpgP1BA09T8awhy9jb4d4eHiMj4qK2pifnx9cXl5+s76+vhoQdKTfdJ6u0310Pz0nB/+8nJlWB9KBosfevYBHczc3t8Hffvvt5OzsbF90VgsPQUX1PZCDqqX76Tl6nuzI9gxbE4gIwNXV9cWRI0daowFlaGjoxrq6usp6TT08Duh+eo6eJztkj+w+KhAxBBQxpXHcuHGumZmZZ1rlUaMBDR7qSpKgJnId1PrMBs2JSVDrvwBqrx+G1PSMM2SP7JL9hw1NJ7kALanQMAAfjUYjO3lErymAtFNQ7zcP4Nxi0JydA3B6GsCJCQAHh0HNyYmQkprkIxeyJfmRp7N+FsaPH9+FpppSqbQPCQnZonVQVV0N1cUFUF1yp9lYKNDavAjQBC4BCP4LQMifAYI8APwXApyZApqjrwPsd4PaU2/BJbV6C9knP+RPLxvywtMDoxywYsWKGTiWVTXVVVCyYyfkuLlCtosKMga/CumvWEFZVBQVHmiw1dbhuGuqQYO9r1d/CZqov0N95N9BE4J/B34KGp+ZAF4TQXNgOMDPA6EixbuK7JMf8icPi2496GJra2uGJ1U3btwIqCorh7y3/wAFs2ZA/vRpcHvSm5A7agykOthDurklbNh5HEb458BgnwxwPp0IAec2QWXkatBEbwOI/idoQr8BuLAUwG8uDskkAAxC88tgqMbhIvvkh/yRX202OsnTp//SpUun1GCKCz/6GO4sXgylny2B0k8/geJ5c+H2m2/BFQxm2vlseOviLZh04Ta8FngTVL4Z0N8rGRxORABcWw+aKxsA1H8VmQDfdwCOU124AfwyCOr2KyiLdeSH/JFfURuUEhcXl94jRoywV6vV2+8GBcGd9xfBvS+/guo1a6Hi66/hDgaSN3MmvKMugMURxfBhRAnMDy2EP1y6DWMDcsDeOw3MjyWBzWE1BoB1cWEZFuhCqPeeijUxDjT7XAB2/Qbq9rwq6oj8kD/yqx2SLrSY4ImhOTk5kcXffgOlS5ZA5Zo1oNm+AyrWrYEyj6XwwfkM+OxyKayMLYe/xd6DZZeLYW54EUzErLj4ZsIrJ5Lh+QNxsOH0dqg+vwA03jQ7JgIcGgmaPXYNQRwZDeVVd4H8kD/yK4aEllSs1j6jRo0ac/fu3YLCOe/AnQ8/hIqVX0PV2rVQjpko+XQJzA8rgRXXymFzcjVsSa6FldH34H3MyOTgfHA/ewP6n0yF7gdjobfnNdCcxllBw3BoNMA+J9Ds/g0AtrrgP4pMkB/yR37Jv4SLSDf5pfMGjlfNrclvQeHcuVD68UdQ9tlScQz8ci28G1YMy6/dhXVJFbA+sQr+gn8vDC+BN4MLYKjfDXjFKwW6HYyDrp4xAEdGiPVBs1+JGRgksqDZ2Qdqcy9ol/Ua8kd+yT/VRHdcTgfi0jqebrg1axbcmvh7KJw+HYpmzYTCaVNh38rNMC0kHxZH3oHlV8tg+ZW7WBfFMB3P/TYoD5RYnFZYE88diIEunrGg+fVVbDgEuweKACgLVYfdofHCT/7IL/kXQWAbQCdxfagpxJrIcR8KOWPHQN5vX4OcMaPAd9Z7MCEgF6YF34J5oUUwV12If+fDhKBcGHo2GwadzoBeR+LAcH8MZuIaOh0gOx8oGmWhpuCaLgDyQ/7IrwiC0oFrej98wYwrLS29XRYaCqkvW0PGEDvItMN1wXYwpA3sD25n0uE1/2wYH5gD/4NTc8y5bHDFAAZ7Z4D5iRQsykQwxCwYe4ZDrS4IHIZdA6AuZgfU1t9fb8kP+SO/YjioMOjFgm10RkZGeEVNBaSrnOG6iTEkm5lCirExXO/xIgw6kgh2J9PACZ0qsQ3B3g/AZnY8GbofSgQDz3jo5JkAS/euaShECmLXQKhN+hXqGu0AqtA+vpfCyJ+833heN0UxPa6+vr4/ieqNi4VYSYJ4Q0NINOwMCQYGsH3YRDDDQKyOJolmhlOyx5Ek6HywIQCDAwnQ9VACQO1dqLgZDameC6H8XiGmvkb3jtGC/JA/3RSVd1C0+7GbMWPG7Nra2iq6sXjvXogXgRiIIBINDKHXzjDosi8WuhxMAEO599QMMYCOeFxxNQd7XYcvu2S4EekFdTVVDwRA9skP+SO/2sWqo7x57Yer2GvR0dF+4mbclJQcOwYxGEiC3K4MHQ6GB5Nw7DEI2bnBAQxkfzw4+CZjxd1Pe9r12AcCIJB98kP+RFHKu3PxAqNdM+2A5syZM7+ysrJM+1BNbS1kffIxXJ0zTfy+WlgGXbEIO1AN4FHaFw9j/NNBU1en5ywlLuqB135VVVUZ2Sc/5K/xC0z3EpOzMXbv3r2bNHIXamtroDwgAK6fPipe3+IkFtq6uBwYeSgcDqbcemDXQ49Wlt9rek5DdtHPGPKje3k12d5TgRrRth2X09/5+Ph4bd68WWekuCAPV7r7vY0pqYQ9WVVwMSm5yS5HHnt5aCggHAI4d+7cMbIrfxYYNc2C7ssKL3bFcTLDGx3xgd97eXkdxR1QwwJTq8FW80Cv829lNYlBA1lp8WLjg4sSLF++HPr165dvY2OzAO0ryD75aelLTWx0qVjkjxcFtokbEfPmzavctm0blJQUQJM6g4K8bF1YYgSxpSTGwHfffUfO67ET3rg8T5LtWcortMEjd9x0I81hmkY4fq9PmDDhvWXLloUtWjBPU11drZf527dz8Y/7b4XKygpYvWa1ZsqUKXFvvPHGInqe7JC91gSgFwilDIvU2NHRkV5urlhIb+JS+9Hnny+7ia9i0WtqJYW3dVkoKiqCjz9YdA+deuCzkzEDbvQ82ZGH+vG+wuQv7+fQSE80ZqXNikqlnL9mzZr82NjYhiCwYOlYUVEBRYWF92bPnPk5vZyorrBZ0/NkR54JjxWACIK+lmhtp50xZsKCvi+dnVXjpk2b5lFWVlZKzgtxOKgIsdV/+83XGzHQSRQABU4B0PO4qe3ciDZ49FDgWNLNXegDhT7baGml7wQyisHYoJPhLi7O07///vutGER9RlaSGI7z58+fdXJSzsV7x1KwtGuiBYn2ka+//jp14oVGAbUYjK4W6EF5CGifMZg2pejbCWvCnV7B2NMZWCYeOPeDykrvQHpqcubw4cOW471z0dkEbCMwCGd8xoHWBbT3G7zWl7b5lFX5w6djSwxMF5kK6EcpRefDaJ2nMabCxMD+gNdm4j1fOCkVa/HvbWFh6qypU6fsUzg6bMDrX+G19/CZt2mdocUJz43Dc6MoKOoQDevDvtA7yZteE7xpEFU2FSKNMTlHw9MxC7PQ0Dz8vdJJqVyvdFJudXF23o4B/Ijjv0mlUq3C65+ijXfQ1gx8dgrNEuoEPjtSXgT7YMZ7thSEyARRPrTZkJdvZzm1Y6lHZIx6R1nBv/93qJvbFPx7usrJaSoFSr2nBY7uo40sZRHbKNreUwA0XalOcFjo7dnsdBVFSdOJxo1uJk7B3t7+FXlMB1Ng1OTp6qBUKBzxA1ehVDg60m+qnYYZ5GyLf79Kz9GOmnpPw0C1RgE0Ks6H81REfskLTHf547UnZUneAPUigzhde2MgvXFoetNv7TVqND3lqf2CTDmImfE4C5Z2rRB0oZwhPcpQ2+zthhhiNh44r6UU5SnfsS2YPOYxmcdkHvPJeExtJkoL4FZiEGSGHYCMS79AVsQRKM6KgbS09DbgMR/JpWrgTm4COj0EOVEnxPGG2hMygndBasCPkEbH1JQn5zFramqg6m4ZVJdXtBjA3aIsyL1yCm7F+MKtWF+4efU05EQegxuh+yAtaAekntsK6Zf2ANl9PB4TneeoQyHqhx8gcuNGCF27FtRf/xXuZGU18JjonLb09MVNvc+L9YP8pCC4nXRB/J17xQtuhHmKYUk9/yMkeX8PhVnxj8FjVlRC3O7dkLBvLyTs2QOxO3fC1X9uA/W6daBesQJO+wXBlsDLsNYvFNb7hUB4mB/cTAiAwtQwKEoNhdvx5yEv2lsMS0awHITvBsgIP9Q6HrMOe5iMH8KpR45AutcJSDt+HK57emIgP0MIfnvsCYmBXepY2Ilt24WrsP5cOPzN+xKs8g6EgpRgKEgOhttx/iITIoiLVBdbIcnne7h+dlPreMyilBQRQJavL+QFBkLO2bMikPhffwXPiEQ4ejVFtINR12F3aBxsDboiMvKn0yHw1akAURN517xxiI5BZuh+SL/wL0g++w8RRKLP+tbxmJnoNP3ECbiJH8FF4eGQGxQIGV4n4WBoLJyMTge/xGzwx3YyOhU8MZB/YWZ+OBcBX58JgQ9OhoJ3sB9kRh7R1UNa4E8iAxRESsBPreMxk/bvh1Qcjmy/syIT2f7+kIpBHYhKBt/4LLiUdgvUGfngl5ANR66mwq7QeNgUEAnfYBAfnVTDEq9LYlbQ9EwL3AEp57aIAKjlRvu0jseM3bULKBAagoxTp8RRfeyUSL933A0ISrkJF1LywCf+Bhy+kgI/45BsOh8pMvEhZmIxBkJrA7Vk/81iVoih8F4LpfnpreMxaexj/rUTEvGYtLdhdvge8oI94Qmi52fiMsE79oaoCzr3U3C0KM4vvUNg0elQWHgyTMwE7RDo2vmteqzNQ3nMdKyJy5s2wZWtW+HaTz/i8R/gv+Nn2B58DfaExYFn5HXYH5GEfyeIc5sCLsNqLMzPvNXwHgbw/im1vnM5C3dLbraexyzJyICQlSvF4hRG68KaNRCyahX84B8hZgI5pt7T3z+cjxIzY8UZNXx4qiELS05ehATvdfcDOPN3KEgNFwtcq3nMyupyCF+/HtRffAEhf/oTqJcvh1APD1h1OhjW+uLidDZcNPr7O181/Bkz8DEGsOBUuGj7vI/oZaEo87JYWR+bxyzNuwnhc+ZA2MKFEL5oEYQvWABHvloNy09dEmNPjZx7YA0skp1To8Ksq62CsqJciA7whIryMl0AT8Rj5kZGQsTcuSIAbfvo6EWR8vdPhek5p3PzT4bD6egkkfby0nzIvH5Nppf+Cx6TjN2KiREZiXj3XdEurN8gnJNTbdMGsu6sGjSNiLXc7Bttx2NSOhNwGQ/dvVP8zi4qEWl/91SEcD73ZAT8MzBSr/DEfZlpbcdjUhDFycmQejVK1yvqsX98Cmw8HQiXM7Kb3WOgw7bnMUv/fUevt7klZXA5uwCSMjOb3ew0Lsg24zG1vGRTFBcXPnDuVl5O+/GYZWX/fsBhSXGR3jCIesi60X485uLFH+jxmCKIkiK9GUC1sHp1O/OYX3zxhR6PSbXSmMdc8skn7c9jYr3o8ZgUhJbHLC4uvjd79uynwWM66/GYVBNaHnPVqm+fHo+Jf+t4zOy8dB2PiV/mT4/HxOsz8LzgMfFrHNLT0zLx+jPgMZ2cBI8ZHh6WNXXq1H1KheLp85gqldN6NLQVe7ldoVD8qHhmPObQoQ08pkr1DHlMpbKBx8TjM+QxnXtjAL3x+rPlMR0c7JnHZB6TeUzWY7Iek/WYrMdkPSbrMVmPyXpM1mOyHpP1mKzHZD0m6zFZj8l6TNZjsh6TeUzmMZnHZD0m6zFZj8l6TNZjsh6T9Zisx2Q9JusxWY/JekzWY7Iek/WYrMdkPSbrMZnHZB6T9Zisx2Q9JusxWY/JekzWY7Iek/WYrMdkPSbrMVmPyXpM1mOyHpP1mKzHZB6TeUzmMVmPyXpM1mOyHpP1mKzHZD0m6zFZj8l6TNZjsh6T9Zisx2Q9JusxWY/5/1OP2XdYXwNzB3NDbaPf7c5jkpOe1j2fe9n95e7WLtYvmdmbGVk6W5oY2xib0pF+03m6TvfJQbUNj0m97GbcrZulyrKXhcrC0tTetL+Zo5mtqYOpwsLZQmWO39J0pN/iPF6n++h+eo6ef2Iek3pipbJ6noxZuli+jI6G2C+0Hz/Se+TGIVFDgk1iTG4axhtWS4kS0JF+03m6TvfR/fQcPU925My0/gVG0Vu5WL2AKTbHng52/qPzZKVa6dspvlMtOW2xxTQc6T66n56j58kO2ZOz0qFVAVgoLV60drO2NnMyUw4/MXxjl/gulVLCQ5w31/B+eo6eJztkj+w+KpCGIcCIKY0vj3rZVXlJeaa1DsUxXHpAjymdkUBxUXmG7JFdsv+woelEhURFRYWmuKTw0RlvTRbOSg/VYzoGOfiQXbJPfprlMQe8NqALTTUTOxN792PuW/TGOayhly1m4aLUKj2m+3H3LWSf/JA/vWxQerB4emCUAxw/dZzROb5zFTlvTo8pHUan8XKLawiitXrMzr4GVWSf/JA/eVjuf/gYDTIys3K3Utlfsg+QoqR202OSffJD/vR4TCoWWmTs3rebQiluTz1mx/iOdeSH/JFfURuUEguFRW9LV0t7t+Nu26VfpHbVY1InyQ/5I7/aIelCi4mpo+nQQepB7a7HlKIlID/kj/yKIRFLs7NlH4uhFmN6Xe3V7npMygT5IX/kl/xL/Uf370bjY+pk+oZBvEG76jGloIZpTX7IH/kl/xK9es2V5gNNlabjxbyfKLWbHrPx+kL+yC/5F0FYu1sPoJMGcQY10qdSu+gxpZD7AZAf8kd+RRCUDlzT+1m4WYwzumJ0W/KU2lyPKZ2QFzc5CPJD/sivGA5RmPhiMXcxHz3owqBwKRZvHCK1mR5T8tYPgOzbXLQJI3/ihUaFqZ2iZkozV9Wvqp/EjSelJ9ZjiqX8giT0mNIVeWlv8hIkP+RPN0VpsaDdj7nK3K7f5H6zxXuDbl4nPbYeUzom95pedocbet00ALJPfsgf+dUuVh2pOGh8zF3NX7PzsfPTPbgZ22PoMXW9pnam+W0A2Sc/5E8UZWMek3bNtAPq/3b/+d2iu5XpHiTDsyShxxS/1VKzeky9AOQhbfra7xbTrYzskx/y9wCPKe+oKBtjFZsUm7AHGl0Qu7Fta1Rg8Q1OSI8p+bawx7j6wDkN2TV3Nh9DfnQvr6Y8Jn070LbdTGX2O9vdtl7SXxoZCWlS5TTuAVJD9Te31WtckDhF7fbZHSO7wj76aZHHxE1oVxwnM3y5OJqqTH9vu8P2qDSikdG4Znod3PxWT7fpWSBBR+uO+T0G9FhgYm+iIPvkp0UekyqVioX2gVi9ClzfJ9qutN3Y6a1OldJKufdN95sXm2QhQc6OBzZrqb7nqJ7eJgqTSWSP7JL9R32D6AIR3xw4jXBRed1qrNV7RguMwqS3sU5imgRxqUlg17B9Jmm6j+8eZzHaYhE9T3bIXmsC0AuEUmblamVsYmsyUCwszmZvmriafNR1fteb0uVGvVY3ykIovhemGdwzcjLywCcmmynM3Oh5skP2HvsrTP7yfs7U1rQnvu2stFnp7dBrftelXfMlL9lxyP3Z0DW0672+k/t8Ti8nqitzR3Nrep7sPDGPKT4HcW2nnTFOKwv6vjRxMB7X580+Ht0vdy8Vzi81FGGH+A71NssGbTRzMZskAsDA24XHxE2IjYWLxXBjR+PpNitstnZI6FAvpikOh80+m7O97XvPxWk4loJ9KnpMI2Vvj4F7BwZJkRKYnTPLNHI2Wm6sNJ6LtfN09ZgvqV7aZnTYKMvkdyb7erz64oZeil6sx2Q9JusxWY/57PWYreUx20yP2VY85hPpMduLx3wiPeZj8Zjahi+zpnpMessqLjTwmK3SY7bIY7aGTA2SHqrHdAxyFDxmq/WYejwmfcpdbuY7IlF/W9caPSbZbbUeU3yPkvP90gN6TLGJiZedxzX83Vo9ZucAQ8FjPlKPKXhM7HV76THJ/iP1mNTD9tRjEo/5UD2m4DHx27I99ZhaHrNFPSbxi+2tx9TymC3qMYlfbG89ppbHbFGPSfxie+oxtQwe+WlRj0k3tKces/Hi16Iek/jF9tJjNv6nDflpUY8peEx/qc31mJLfgzxmi3pMwWPi67gt9ZjSuSbkisxjtqjH1PGYF6Un1mMKh/guIT2meN+0wGO2qMfU4zEPS0+kxxRpj5QpxLiWecyH6jF1PGZ8A+H1OHpMPWIt8OE85kP1mM3xmFo9pviNqW5Oj6kXALVzLfOYrdZj6vGYPpLQY+p6hQ61ekyaTc3uMaJb5jEfW4+pMxLRDI8Z2HyPW+Ix/ys9pq5GmuMxw5o5d1Gfx2xTPSb90/ahQWiHK+BBHrPN9JjS9GZ4zKYEa7QIQPCYbarH1OMx32vCY0Y04TFnGbSvHpN4TCMHI30eM6IRjxne9enoMU0cTPR5zLD7POZT12PqeMyL93nMZ6LHFDwmDoNZgNmz1WMaHTFiPSbrMf9v6jH/A4NUfSRgyto9AAAAAElFTkSuQmCC')",
// 5 = wslm & native SL URs
"url('data:image/png;base64,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')",
// 6 = Elgin
"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAKrCAYAAAB/UOT4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AQYFhAJkQgdpQAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAABmJLR0QA/wD/AP+gvaeTAAAji0lEQVR42u17B1iUx/qvYkyOmFiS6/VYo/dETxKNxwhKXcqy9F6l9yaiiKBSBOl1YWHpRZbeayjSkY6VogRbiBrEQlGiwkJk586soJRdyknOufd5/vN7nnkWd+eb9523zXxvflmxAgMDAwMDAwMDAwMDA4MlOOBYJSIi8gkXF9fq6YH+jb6f+v0vx0q0MBLCRxTnVNLRW6+gZ7RZVFl9K1FRdRuvlNx2CXXNbeKqGlvlNbQ2qesZrBcSl+ScUmrlX6IASU5h9Y+CwutUjEy3GJ913mfu7idi4k1W1XIP1Fe94G+k6ORlpH7B31DXzV/bwitQydrDT9jKyXWfwfGTW3bv2csJrbTq31YG7mQVUVKKU8PYbIu+veNBQzc/ReeEdNfElptNMW23B/3qbky4VF5lOFS0Affa6wxqc9d4RvudF3lXu5q8k7Ocdc+5Smods/5WRlX9Kz4+vk9NzcyW5yao/ScS8orrVUwtv9F39pT0zyryTWjp6A1s7GCcK78CrArqgVFuLdDLqfkwTPLqwIniRuBScQVEtt5mlHTdue0em2SrbG4tIK2itl1KQfFzuC7HUhVYJaWsukHH9ux+Azc/rYTLV+uCGzsm7UpbgFn+ZWCQUwt0s2vYDn34uzlU8nxlG0hrv/uu4HJzjsYJO2lNE/O9MhpaG4wsLFct5gIOGANfaFjb7rcICDWmtXbcv1BzDRwrrGcuvpBwVspYFjYAckohqCqr7jR08tBStT59QEHfeB2UwzZGVm7evHmNlLrmbnX786qpVzp7LlRfY+5+OcLnDuQmh+AEEBMU1atm66Qtb3Jsz/d8gp+xVEBaWno1SUZui4zJMSKttrkssKGdadZFhUAldbIWnmOUWwfO+0cBrwt+9TIWNtLSWnr/C8rjmOcGGAvrpDW0fnCOSnCJv9r9zqakCRjkLuyC529GAYJj5ZVFlbWALvV0D5o8HRzhIqdn9K2gGGmeNVbv27dvs7yROSnrStcd16qrTDMu5vNJBoOpRMX938DV356DEfo4GBqlg+xbv4CjGVWz5qOAtk8sAGUdP99SO2YjwiMsum5m/VgpICCwho8g/I2Nd8DxlPa7wPqnxiUFok1JM8i73QtmovaXJ6Dz6SCIvtLNwhoNIKP9HsMuIMRCXFH57+ISkhzTrlh55MiRdZJKKlw5l5sLYDoCs4KlBaN2VjW48+IlmAu7slZwBVpGZ858Q+hev8s3QH5Da5qSls4/pOTkV384kGA8fElSO0rMv/nzI4fy1kVjYXpoQSUev3oNGFNumQbtxh1wb/AV0JjjEjTsy5pB450HHUr6RtwCQsJrdn799coVsKSu4ufn3yxnekyF2tRBt4ImQxVwKUqgnd56NgRKeh6C28+HZylysrhpniXQOAldXdT9y7DGsROSIuKSX0L5HCskJCRWcR85sk3K9Li+W801hvEiATlXibsDr0BY6y1mfMxEYEMHy2dQ2ufd/uWd8jEbHUGSxA4o/9MVzCOaQNghaX7SBBUnlNMsBcJagKonEjb9nWZmFXj48jWwgrt7+PJ3pvDe4RHm56V7j1mug+ItEbpL2eqUmaiM3D+hfE7maSkmK79d5ridpWfNdQa71LS71MJc/NXYOFSomqmUR+11Zloeh0og/DHJYAbr24k/mBZCSs5TAha37K77kypWp8xlVNS+g/I/R+7gIMoqbFWxP29GbWofO140PyZQuo798e6Dqf+YnASldx8BMswkZDnvupvM75FbkHJVsG4gOLMoYugELui6/1bHxt5QUkFxL5S/FgUmh4Sy2qajZ130Epo7njiWt8w6KdHOIlpvz0vDobd0ZnagOZTmLuZ30zvXg+POwPvUdYKKaE/NQ+M0rMT13fcf6B63UReXltkN5a9hFitxFY2NR+2cFEJKaxv8Lt9kngczfcgK4+/efShoqDAhaM0QhgS3PX7O/N73cjvThWi+F3RhTm1jmZqunpigsPA2KP99+ZZUUeNUtzkjYBYUGRLR0jWJKqYeMxirQOmdRyyVeAdrgyk6vOC8xJt3wQR00cwdM+tIZjVoeNgPWh4/A9rQSibQdWkddydPevg6KahpcEErbJy6i65YoaCtuxoqsVfTxds6rKb1/nloQlSwzl5qBQvhPDxjUDy8gAfZ6B9/zFMC7R5liwWMA1Qtz8FCWNN+q1PD1EIVVsvdUIE16urq70v3hs1bVkrqGG5UPe0obhYUFRHW1DlhBQPUGD6I6ga7gcxrwLzm1cJ4qGZd2uH3Bigg4XrFP/eOWzm7OUgrKHH/eIhr49QrwkeoWJ74DN589qidcTH2zimp9oY13uRPXmimB3JbeEsXiMsvzpY7qi0rKkbaAQ/NT1lebMQ1dNYrWp7kV7Zztg0pqek0S/kJLKeCzh16zMCG983iBpDX1NamYGCsJyIusR+eVV+wfUkSlpb7VNHIfJuMoZmoos3Z08FFFe2nCuHlNrt62QqgNLcqagRBsJYEJab9TlLTdBSXk+eVkJHdjN7YFr7oSsuslVA7ukvB2IJo6U0+5ZtVVKsTkzFpkFW15N2bwrRGQX0uJY8Rk1d044Srh5mihia/mKT0TlSmkZwF37hQGYfvCeskNbR22Xn5EU74U8xc4lMjzidm95+DCy902UHvIlZF9SCkqQMEZOQPuEddJB93dNGQVlDk4uHj24pKNErJCxcuLPpGhhT5REBEdK3ZqdNbLc85/Wjj7iNn6OhmY+0bFOV6MWUkAF6CdVlcWAJgUfJLzaYHp2WnOAZSbNQNjCSESeLfEQiETdAFS3s/ham/csZLMHrz/puIlMxXksqqu/WsTvAb29pr6ducdnYmU4Zm3sSRArbwdC25dX/UPSw6QEPfUFNeVY1XlCS+6+DBgxvQOmg9aAGO5byFM5VAAYRqO58gYYOmgdFOFS3tQ4qa2kp6tme8Sm4/GEUvNyh70AUms/M+4wI1KlFMQUlDgCB0iIeHZztSAD0PL9GfzmgbLO4KWMHQ5M/gi9BauNA6uMiX8Ob1v9GiPPz83xNl5IiiiqqmzuGxuXFXf2YE1F8DCdd7QGp5TStBStZSgEAQg/P3w/H1/v37N8P761ckEmk9rAtfzFCIrTIrpxofnOhBJBQ+9A0vLy/y6QFBQUEuISEhfmGimBS8ERkSNXQ8Q4uresrgkZ59tWtATEnNE1rMGAqTgYMAlTgMn/nX4cOH98H19sJ1dkEF/g7XXw9ffD5jVyfQl5+hncOH/w98+CAUDjdGEIMLSMOFFaBiqvA3bX4hYQc+IokiqqCcVNt27YmWsWkOryAhFP7uAp83gc+oQSUU4ZCF30nA74SRUmhDcJ2tyCpTtWKeNVYhcyHTw0n/hA/zQoEkOOSRcLiwJrSEDlzIEP50AaZcENfhw5HwM5b78OFouGgINze3F/z9JFxDD66lBZ9Vh88poU3AZ4XQxpCboMU3sFOCaQn44EY4diIzIu2nTEtEO0KLod0hq8C/VaaEaMK/NZCiaPdQuByaBz8lkRXhEIbu4EMKQOxBcQLd8jmUxTJdmUGJ0gn5DU2Gyu84cODA7imffocUQwMK+GHK3wfh7n9En+jfKHZQUKI58O/v0XNwrX+g3SM3oFhDCswITvZNMmSqXbt2/W2qwKAOy3pkQmQlFDNooAXnjunf0EDpiZ5D/keZNp0Zy2moTdcKZrtwykKzWoaLjemW4lTKcyy1RiyrjxkQEPCJi4vL6umB/v0f72MiIZ5kCmdMUsr6qJT0zYExF7eSo+O2eVAjtodcpG2jxCVsjUygbbqYkrrejxLKOaXUX9PHDI6IWu3s478uNj1rS0Zpxb6s6nqRzLpGVVp1o35cVYNRdHmt0cWqBsPk6gbt7NpGpfyaeuG88sp9qXmFWyysT3JCK/37fUy4k1XkUCpnQkbWltSSSwfTqusVK27ecm3ve9Z07cnAYP3DpxOVvf2Msl+egOqHTxmtfS/G4cvxi57+F011Hd3OyaWVkrTc/G/D4i5+5enp+WlWVtby3AS1/yQkMnp9bFbON6kVtZIN3Xd9b/Y97218/JxR+qAf5PU8Auk/PwQp3b9+GJnwzbwAvn9W/tIPrvQNMO69GLpdfb3DNiYrX4AaG7+dGhX9OVyXY6kKrKLGxG1IKirdn1pdr3XzUX9d8+Pnk8X3+0AWFJ7a/RAkQ6HsBvodzavofQK6ng2963nUl5NQUCxNy8zaG5ZA25CenbNqMRdwwBj4IiG/aH92Q4txe9/z+1W/9oPcO4sLZ6VMzp3HoLHzDuh98GtnWnmNVlz+TweiUjPWQTns+5hHjx5dQ71I232xpEK1q/95D1IA7Wo5wucO5Kay5pvgWtPV3viicu3IzNw9dp4+rPuYVCp1dXBYxJawzFxi+8O+skb46rYUBTLhnKRF5qD4qWi4Cmqr6uvDsgulqbSU/wXlccxzA4yFddQE2g8VV2+63OgfeFd47zeQ+vPCLkB9CGZDpLd/UWWzoUtrq5smf2q+4hKRkv6tT1Dw/D6mvb395sj0LFJ3/4s7MPWYZlzM59MNs1+Gfwf9v79lvqmjPkb3wEtAu9U7b35Jew948HzwVnxuoYi7f+DsPqa3t/caT1//bwrrGo53PhsC+TDVlhKIhff6QM/A7BYiah+hTu+1/gEW1ngMbj0bZhQ3tFhQomP+TgkJ5Zh2xUo3N7d1oTGxXN2P+gpgOi45GBPhQB3cuSh+0Me0zNxYSYPurX/0FPQ87kuLoSX9gxoR+bGPCePhy+B4GrHn2eCjMrjAYrEwPWhwjNAn5vUx258OgWGoXMIcl6BRAtd/PPSyIyY1ndvbz3+NsanpyhWwpK7y8vLaHJGVq9L623N6HjRZyhLTD+104M0YuDc0AgbezrYICuwkli58DO4OvBxOyC2QDKCEfunh4cGxIiQkZJWLm9s2alaefvWv/YyMnqUXpaQpd7T1DTDjYyZgiWf5DHI1jKN3MbmFOj7BITuCg4M/XcE8on19d4RmFZqg4pTOxhVIIPodCfvgjtu9THfkwd2hViLCy6nPB8MjbJVA7oIvymaBYRH/9PHx4Vzh7++/Kig8cntYXrFl7a9PGexSEwUbAh2mYdKUUjUPnzLTEimBgP7TAwpW1L9CFkJKslKi+8XwZGxekTk8o76D7vh8BYVC4SCHR22NLakwa/3t2Vje3fkxgdL13eTH4EPC7sM4QCZHlqt7+Iz5PXILUq53+H13t4JFEUMncM+L4bdJhSWGIZFRe6ESa9GpyUGJjttEK63Ug8f1k0soO2bUCLQzeDTPS8OxiXfM7EBzmvtevO/uT+08ZUbqlkNFEmco8RMM2EcDww+S8wrVySGhu21sbN73MYOi4zfSissVWu4/bKh/9Ix5Hsw0H7sW4rSyqDAxlZhTQ56MvGV+fxmumTRl0Vrowu6Hj8vikpLFLnh4fOxjkiOiOOMLSgSymq6EXOl7MYkqZgrT771Ms7MCqg1ZU4dXO6yy0/Ewq47c/hU8HnkD+uBIhFbKhK7rej40WVhz2Sky7iKXg4PDRnNz8/d9zMDwyNVxBSV7aZV11m2/9t1HvkQFq/RB34J9TDQPxcMoPMhQvzuRRUahbMmGyqZNrffrs4HOhKxs1aBQ6u6zZ8+usbS0fF+6+UmSK8nxiRtji8rEs5quRrT99nwCBWgGfBDVDXYDmTeVec17yNw1y9J+G7kBBiRc797gy/G8imoHamQ0t80p2/l9zGBaymfROQV74ksrjeu671XXwRqf+ScvNDPjqg0G7/Wee9nhCTRZb1+/HadOnWLdx3QPjVgfmZXPH1NcYdty79fOrM57YDkVdO5ImVKgAsZYz29P2uDVTs+XHLT/+PHj7PuYlqfPfBp8MWlbaEqmaHRh6enmu7+0FzHvl8tXALkKuaAJ1pKm9q7f4QHpSKaG8cJDa7O2tjb7Pqa8vDyH9SnbtZ4U6q6ItExiTl3jqcvdd2uTrt2aTO3uXdbuURCWdvYwrvXcvZFfUW0WGX+R38PHdycMRE4FBYWF+5hwwqrjdmfWuQeH7iqsqiPk1zeZVd7oiqho7+4vnVPIWN0l8+4+Ai2/PQcNt3oGqq7cIOeWVWhQwsK5Ttvbb9XX1/9cXFx8aX1MWVnZT47q6q2NpCVuTckv/DGvskYutazKJv9yU1Tlzc6RBngJTmZxYWmARam+q5ve1Hk7payhySY2OUXC3cf3OxgDm2RkZP69PqaamtrfzG1sv7rgF7A7Li2THyqklZxf6FzR2Dw08/aFFCiCp+vdF0OjVa1XA2A11CRTqby29md2KSoqbiCRSH+ujykmJrZGSVV9g5uP307vQPKh4MgopYTcQq+7z4dGUQVMg7GSD4O36+kg41JTa6J7AFnDxvb0IU1NTdT920AgEP66PqaQkNB2MQmJ77WNTYlGNnam8YWlueX3f2PkdP8CKnv7QPWNzlZdCytLNQ0NMej3/cLCwv/ZPqaYnIKhvJG5Z/yl2p7Ke49A/s3bA1LqWp4EEVFjKBz3MXEfE/cx/9/3MTEfE/MxMR8T8zExHxPzMTEfE/MxMR8T8zExHxPzMTEfE/MxMR8T8zExHxPzMXEfE/cxMR8T8zExHxPzMTEfE/MxMR8T8zExHxPzMTEfE/MxMR8T8zExHxPzMTEfE/MxcR8T9zFxHxPzMTEfE/MxMR8T8zExHxPzMTEfE/MxMR8T8zExHxPzMTEfE/MxMR8T8zExHxP3MXEfE/MxMR8T8zExHxPzMTEfE/MxMR8T8zExHxPzMTEfE/MxMR8T8zExHxPzMTEfE/cxcR8T9zH/R/IxuWQPc8qayqwXPy6xmceAdyu/ruC2Axr/2k4wImwjGBC2ShpIb1IyVV7PLyfw1/IxhVVFVn8vsW+d9AnpLRp+R/epxxwVUUxSVBVJJerzpvIaHabxGAmkEAwlEqW01S8eVdKPNBI29DPap3lWc8vX33395/mYwrLCnIonlLYo+yoflItXULSosnD1f+Lf5DLiNmj+ympC85UOQ+mVEtAb0WPYjZwdD3kV8iLuCa3JruqMsyxFTlL5rNK34jri7/mY5qbL52MS1cTWS9pJfiMXqSh5pvmcr/dzv16r308wFEdUgcggCXAP8oIfhn74MI4M8gPiMBEcfakDzr12YiS/SL5tW2RvS3KSFCBpk7aLq4ovj48ppiW2QcFLYb/sRXktv4dBdSdGTk3KvlQEfEME8OPQYbB/+Ee248AwF+AfFgIawxog8HXwu9SO9BwpD2lp5RMqe8WMSBv0rfUX52PCGPhC+oL0fpV0FWO/Z373tUa0gNAgkbn4QsJZKSPwUhg4NfiB4kt1nYphalokD/EDJGvxxfmYIoYiu0VDxVQpTyk9WiN6zN0vR/jcgdxkVnQO+PrSekWDJLSFzxH37BbfzZ6PKaIkukXAUZBIvkMuOzZygmnWRYUM84N9Q/9acA7XEA+wSfMAzj5B9bweAtLCFiLs+ZiiRqI/WBVau7iPeL2TGJZZ1P/oRoiG8ojyosqiDTmHhU0aZZi4EK3FvuWT4mXNxxS1I5Ii+2PvaL7SZZpxMZ9PKzE9DMz0P/y9Z+j7WfPRhjSvG4L0/vRbki4yIockuObzMY8Qeb8xjjY+7vfGD6aaxJICkfRKap4iM8fc+ShQKa/DGeYJFhbCR4X/TpISn83HJGoSuRK6EgtgOsJg5FtS0H0/eIClcOkReebn3FhB1oBFDiTfTk2TNZL9h4SSxGw+pqCRADH2RfwjlWH1RWNhenwHixQrJbze+LB0CRryQ/Kg4ll5h5SVFDefKP+anbt2fuRjCjkIqdi9PEsXHhJjVsClKIF2ys4VYi8lWWaN+JA0iP89fljWUVaSICs8g4/Jw7WNx4VXX/eVLuPwEl0xUwm713bz4gOWeLZZEvE24h3RVUyHR5bnIx+TV5hnB7fHERNUnFBOsxOIqicSNv3dt4P7mQKFX4otKTDRQPHm9cYXEN3EzARVBD/yMYVUhLYf8eO1NHxlwmCXmrIvZZkL65sZQIUOfrCCq48rEBkmfRA8M1iRkvOVIICw12GTYhfEzcW1JD7yMQXVhLYSQoXNzgydGRMdEp8XE6xqwvRAljP+3ezDv2fGifpLzXlKoBM4ZiTuraK7kiFJVewjH1NYR2QTKYSk5/084InaoNqs7EA7g0czSwW+m1LW4rHVrJ3/MHTowxy1V5rMNabXk4bZUfLs0gNVRzV1MXmxj3xMgoHwRgmypIJj9/kGsxFL5nkw04fsrDBd0OYqNbeGmLy2YLoQzTd8ZQpo7YllysZKYoKiAh/7mEQdUU5xb3EB+QL5EIdXzpOoYqLd7BvYB2hjSWyV4BkSmGX+mTueW0f2DfyLeRQEvg6cNA43cZLRlp3Nx5QykVwNldhLjCdaOz08f//oS22mSxRfqi5YltVhtsyMh7lKoN2j71Favl9PEfzU+1OnwikFVVgtZ/MxP9/5xUqBE4IbRcgi4nKFChH2r85NoKJ1eIAPoLrBbiDzosXR597hfWxL+8FBboDWo72mjRsEGjlIqElyH+T+cX4fU9xZ/DN489kjQiUan7x+qtr4lfGs2PgzA7nt7CsHQKkLyRY3kpAVkRBlz8fkNxdcL+Iqyi8YImTrfMulU/iuGFhOBZ07UFzxDgsC7T5DkPxzYpu4NUmPIE1YmI/Jp8r/Kem0xDaCHUFUMEDwtGO7Y7vUMzlw6MWRZSuA3IQqKTqV3Ys8fuc3FnAkKovykhRIi/MxReVF1woZCu0i2osRNRKOnjrdYl97+MbhyUPPjix59zywgKGg1m3TZQTVBN0wCTI1k9WT4xeRIy6djwnfE9YJGQvtOhZmRdBN1DWzKreOMKu36kcLL3TZQe8iIoMi4NSrU8DhstOAXc5ZsrGPqYaEigQXD/+R5fMxeUm8aw0dDbYaeBr8aEo1l1MKUbXRTdCNOllmPXJsxJql+Y+N2IBzVefobuVuKSdjT9ooWihKCEoJ/nk+poCi4FeiWqK71c+o82u5aGmpn1dzPh1jOzTzJo4UkIQHXPJwyujZVIcAZTNlTRlNGV5hSeG/jo/JI8yzQc1cfaeivsIhGUMZJWV3Za/EV8mj6M6IsgddYELeUBl2KfaJhKMEDX4Rgf8gH1PwyPcEZQKRV5ff1Dr7ZO6F1x6ME4NWwPO1D4i5Ett6RIXHUkCI/z/PxySIE6TgjcjwiCWP5/kO157k0WQQ2R89IKBH8IQW++/xMXmJvA7cMtwUPi2+pPKuiidqVmo5R0SO/Jf7mHx8F2DKBXEdORQJP2O5j3DjPibuY/7/0cf09/f/5Pz586udnZ2Zw9fX97/Dx3QJd+UMzwpbT8kL2eye6rHVK9ln27kEx+2+6b7bfFN9t4akUjdFZ8as9wz34kRK/mV9TP+4gNV2IfbrqAXULQn1tH0Xr9FEojuiVQO6yPoeXR5Gru3uRt6dvoYh7VTtizdpSqlX0oXT6tP30UppW0xtTf88H9M/3J8zuiBmS8zlmIMRN6IUs3uzXRteNzRVjlcPZtHzJmj0JEYMPQakjKcwisdLx1voLS+uv25vKu4tdQ5vjpCMKY35lpJE+ff5mOT4oPWhxaHfRFyJliztK/Wte1vfmzdewIgejwMBo8HAZdQDnB07+2G4jXoBMp0MoGKgdKKc0THacbvoboltcHmoQHBi8HZKHGV5fMwgWtCGqNqo/eE3I7XqR5rqCsaLJsPp0cBzzBc4j7mCM3RntuMc3QV40f1AAj0BNE40v+t6fiuHWkOVjimI3RuUHrwhNT91cT4mjIEvqFXU/bG3Yo3r39Tfp43TgN8ombn4QsJZKeNN9wflj+vBvQcPO6Pb4rWCaygHgvMpi/MxA9ICdge2BKk2v2nuoY2nMHe/HOFzB3JT1t1ScPlye29gU4i2fyl5jwXFgj0fMyAmcIv3JR9i41BjWe54AdOsiwqhewH7MccF57iMuYPCrhpQcbmp3qPGW9o/O4A9HzMwPfCHvDv5LtXjte9C6GGL+n/69S9mPGZRZdGGKtraJtNvZbqQ84O+9aR6sOZjBhaTSVfeXL9DoyczzbiYz+e+m6ZmpX7423rMbtZ8tCHa0zRw682tW6GVYSLnQ1zm8zHdyB7fZFzLOF4/UQ9TLWRJgRhMpy74wjx3PgrU5ok2RtbNbAt/mv/fg6mU2XxMMo3MdfNFewFMRxiMnksKOrvRcyyFU8cjmZ9zYwVZAxY50DHQlRaeHv6PkJiQ2XxMn3Rv4vXRG49i6RcXjYXpYQuLFCslaicus3QJGpFjkeCXNw86qHlUbs9ArzXGZsYf+Zh+ZX4qxfRSuv9YELMCLkUJtFN2rgiih7LMGsoYFdwYvzEcfilc0jfc/0sof4qP6e6yzb3SQz+ZnsxwXaIrZipRPFE8Lz5giWebJVcmrrwjVwbpuIe774Dy3/MxPfzdd7jUuJmg4oRymp1AVD2RsOnvTo2eYQr0pwctKTDRQPGG3EWuDjLzifX5J5TPyTwt/WL9trvVe1im0TMZ7FIznB7+IQ3tx5w+WKHyciUIoAd/EDwzWJGS85XwBW0TbZNBVRRzCi3kOyj/c+QODp94v62+Lf5mpWOlY4FjlHkxwaomTA9kuYzxrA//nhknF+m0eUqgE/ja+PW30dUxhsFxQXuh/LUoMDn8kwI2BbcE69W9bXgSPxo/KzvQzuDRzFIB2ylls0fyZu387Nj5D3PioSJojen1qDA77r158CDuUrx6UGTQbij/fR/TN9V/Y0hjqMKlgYqGrPEc5nkw04fsrDBd0OYqNbeGZE5kM12I5qfRs0D7s/aymIwYMZ9A7xl8zKRATkodRSCyJzKkjF4xiSom2o39qD1of9fBVgn3Me9Z5p+547l1xH7UkXkUNE40Tma0ZTqFJYZzQStsnLqLrlhBzQxdDZXYS75Bti4fqbhPoycyXRJNj1uwLF+E2TIzHuYqgXbP/I8wMC3frxcN7r281xlVFKUKq+VuqMCauLi496Vb1Ji00rvAZ2NAY4B4xJ2oiBJ66QQqWq6jngDVDXYDmRctjj5P0u3ZlnanUReA1mufaB9PbUx3CIkP5XZ0cZrfx6RUUD6DN589Aa1k48KnRdUZ9IxZsfFnBnJbKb0MND9syaakh8j6UwJ2eHh4sO5jemX5rA+oDOT3afGzrRio7PQfCgLLqaBzB4orD7oPSHydBjoG29so+cF6PlSf/U5OTuz7mB6xnp8G/xSyzbfYV9Snwef0pWeX2qlvIsD5UbdlK4DchCopOpWr79b87pXh7RgYE8AbEBaw2czMjH0fE94rOPzD/NfCt6ld5JIgYsJN2qmf+kpqXZ+6Tp5/47bk3bvDAoaCOvlJMqPp16YbmU1ZZuEpEfw+oX47z507x6mvr79wHxOdqoEJget80nx25bTmEpLbk83yHuRHZD3K60cLL3TZQe8iAaMBoIheBMoelQ8Ud5eSMy5naQRFBXE5nnfY6ujo+LmBgcEnPj4+izfPHBwcPnHycVqbXJy0NaU65cfMlky5mJY4m+SbyVGFD/JHcsfzWZo/d7wQlPaW0qsfVKcUXCuwicyMlLgQeOE7+MK86dixY5wmJibL72OeOHHib45BTl/5xvvujiuO40+oSNCKL49zLrpaOIQOovcHmRMzBUPGwkD7WMdoSWdpQHhquKZ/pD/vGdczu6DgDWgdtB7z/+X4d/qYcnJya3SMdTb4RvntJMcEHgpOClaKrIj0ujF6c9Rj1Ac4vb0AfN4GgFp6HSOjNTPRLshOw+KE5SFDQ8Pt8D1mg56e3pqp/6zw5/uYUJntR3U1vjewNyBaBB4zjWu+mJszms+IG4kGmaPZoPxuRaueo76lkamhGPT7fh0dna9FRUU3w/HX9zHlNeSlFE0VDdV9NDxj78f1VIxWgMKBnwZ0XfU9NfQ1jFVUVGSUlJT+e31MkimJ2cc0PGuYIyAuEAp/w31M3Mf8n93HxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA+Ij/CxB7lpcU6cDrAAAAAElFTkSuQmCC')",
// 7 = TrafficCast
"url('data:image/png;base64,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')",
// 8 = TrafficMaster
"url('data:image/png;base64,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')",
// 9 = CalTrans
"url('data:image/png;base64,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')",
// 10 = TfL
"url('data:image/png;base64,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')",
// 11 = boots on ground
"url('data:image/png;base64,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')",
// 12 = difficult turn
"url('data:image/png;base64,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')",
];
var uroMarkers =
[
// 0 = comment count circle
["data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAaCAYAAAA5WTUBAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB90LCxYGJyle3m4AAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAAv1JREFUSMfFls1r3EYYxn+zo9XsqjuSxpBQU5OCDy0Y3JODs2Z36W6P/YBCk159s+/5F9Z/QsHkUAruZZ344Jx7KPTSa2/NwSdDE1ISf8SWI63k6UVLN8ZuZFnQ56IZDYwevR/P+wguh7jieXF9Gewla3vJWeELAfA8b9ZxnFWl1P0kST7NsswDkFJGrus+i+P4cZqmP0VR9JyKIWq12owx5kff95PBYBCPRiN7EaPRyA4Gg9j3/cQY80hK6VdFwFFK3TXGvOx0OoktiE6nExtjXjSbzYUb/T3QqNfrvSAITofDob0uhsOhDcPwTVkiAmgCC8aYV2UITBMxxrwok5oGcEdr/XR5eXlsb4g8NY+uVQPAh0KIr7XW6f7+vq0Cvu8nnufNvu/jtak03FZKfbe4uGjn5uYqqe6lpSXrOM5qERIS8IEZz/O66+vrTlUttra25iql7hfSImAB+DIIgrd7e3u2KhwcHNggCE6LREIBGlBZlqn5+fnK1C4MQybqWiQdKi/O/wWTwpSAkFLGWZZVdnkURUgpoyIk/t3Uas93dnYqI7G9vY3rus+KkLBABtgoin7f3NxMqyKxtbWVxHH8uIhUG+AT4CMhxK1Wq/XD8fGxrIJEEATjNE0/ft+IrwEx8AaIrbWH1tpfV1ZWbhyNbrc7llL+XMRjyDwdTt6mzSRJ/jw5Ofkiy7JGr9crRWBjY4Pd3d3XR0dH31hrz4pOTw18BnwFPBBCPPR9/6zsKA+C4FQpdbeoc3tngAErwLfA90KIh2EYHrbb7cITtd1uj40xr+r1eq+s7jSAO0A3J/IAWG21Wr9ordN+vz++yt71+/2x1jrVWj/NR0DjukbmHVcF3ALmgJl8L4UQoeu6n3ued+/8/Hw2yzKVG91YSvlXFEW/xXH8xFr7B/A38PYqZ13EbYtcwkPgdk7kgylZF1PWPc076xR4DbwEDvN3tmwkLtZIMx/xwWTA5d1ELm6T1j4CjoGznFgpX/lfZxJwpwhMR2JCJJkobllN+QeQNNGuneopoQAAAABJRU5ErkJggg=="],
// 1 = green comment marker
["data:image/png;base64,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"],
// 2 = yellow (own) comment marker
["data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAaCAYAAAA5WTUBAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB90HAxYNAG/kdyAAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAABXpJREFUSMetl/9vVeUdx1/P+XrvOfXctmlpGBSuhA00TmSJ0NLWtSztSifoErrFL1tg+AMap/5o9A/wN7MERLJAnWbJYCDbYi0FnbgMnZsigkqmEaztVhdrv1167j3fH3/oKetM670le345zzlP8pz3+byfz/v9PoKFh1jk+vX5QkMuMJcLrFW8IQC3bnCWO06yq74+7PW8YF0QSAvAMEQxkzE+GhvTjxUKym8uXih8zv95iPp6o7azy+7r3kZwqE/4kRQyki0ylvfIWN4jI9kiIynkoT7hd28j6Oyyf71iRcZZ8osWea6tW29v/PZa7+XunqR674OtumBtGQ4+4eCzZ4NTg8rk0JC19f2LVy9dLwgBmPl8dtNNN3snDxyU1qrG3Uv6quGR53j4ITEzPFy1uVIgytcAZLJZZc0t3/X/cOCgtBpX7loyh6sad7P/gKzK54uvVUqNOm+eAZZtaTGf7vlReEtz8/3K9HSA58VIKYkiycxMiO/HKIpAVZVFN83lNjI5dd6YmDAbrlwOX6q0EhpQnctpG0zT6/nZz5u1QiGgo/0kP+w6TakUMznp09V5iq0dg0hZbtuEvQ+2Gqrq7rp1g7O8EhACyALL8jeqO3fchYzCPJtuf4nJyYAXT2xlZiakZ9srxLFk4GQnsiwKBcFadvYK6ThJWU61lBIHqF29Om7b8wBa44oTjI/7fDrUi5SwtWMQ1w05crQDIQSGoRJFybUK6bqCpilIKfG8GMfRMU3Jrt0YL/eHvcBT5SphADnADsP4W667GV1XUBTB+nUnCIKYqamAYjHmgT1nKRQCisUIz4u5bcMfaW7qp6vzFB9/PM2W5n7aWgfYeNuf+PLLAr7fhOcF6yqhwwRuAMwgkKZgJbatYVkqhqFw0/oTlEoRUkquXg3Z1n2aIEgIwwRFEYRhwsiIy47trzIxEeC6IePjHq0tfwbZyJy6lgOhpkC0WSlWeOXVbqqrTbJZlZoak3Pv3kVNjUmSzHaJYSiYpsrJwS4cRydJJLqucORoO4ahEoYSz0sQorK21tKDqQLCMISftf5t1tWt4cNLP8Z1I3RdQQh4/4O7SRKoqtJQ1dkWra01OXS4lZ/+5AyOo9PQkOX5F9q4796/YFkKivovDEMUF/Gt/wHxX9FQ1c+F+FvetmdptO3ZZbHAJwXBrH488su3aGys4ujv23HdiMce/TsNDRlOnW4jivrJZMyPwC9LhwRiQA4NKW/1HSa6JqFCLAhgbrS1DmCaKsdf7MCyNJ584hymqXLm9R5yOZsjvxPB2Jh+rBLvqAG+A6ywbaW+pTV5ZmCwTS1nWHGc4PsJUZRgGApSwsxMhK4LLMtHN/7DnT1vhKOjzupyFq8wW6urgO+6yVTRNV/fv+9sNKd8i+q9qmBZGo5jkMloZLMadXUm1dUhhlHFwWffDOPY/m0lGUNN6dDSNs2Ojib/BPGD1rbzmVzue0vLBWISuIHhkefZ9yt14tw7ckexGJcqBSFTA7OTBMbHlffOv8sdbd8/r+VyGyuEUACqGB55gYf2iuLly9mu4WHvylJcNJkHJFsqSXdyQn3n4gWxeXz8PW3T5ipFUFsm1Iywf19/9Mw+ZerSh5ntlz8pvv2NfC4SajLAMmA1UAfomiaspibjfsv223f2CvmLPWiwBcGq9MXDwJv0HSY6fkwKz8sMvP2P4PFSKbkCeNeTrEQKpB5YCdSm96ptK9U3rtHa8/mkKY7j5UEgzTTo+rqujn72mfrXoU/j49PT0QVgLAUgrwfEtXgHVKdVqQXsebIu5kX3KO0sF5gAvgCm0mdySQf6G5Q0m1p8bs7g5p2heF5rT6enspQCW3qsL7OmplY/B2B+JeaABHOKe73/Fl8BjX42io/HNJkAAAAASUVORK5CYII="]
];
/*
function uroAddDebug(debugtext)
{
var ts = Math.round(performance.now());
if(uroRecentDebug.length == 100)
{
uroRecentDebug.shift();
}
uroRecentDebug.push(ts+': '+debugtext);
console.debug('URO+DBG '+ts+':'+debugtext);
}
function uroDumpDebug()
{
if(uroRecentDebug.length > 0)
{
document.getElementById('WazeMap').innerHTML = '<textarea id="uroDbgOutput" style="width:100%;height:100%">';
var dbgOutput = '';
for(var i=0; i<uroRecentDebug.length; i++)
{
dbgOutput += uroRecentDebug[i]+'\n';
}
document.getElementById('uroDbgOutput').textContent = dbgOutput;
}
}
*/
function uroAddLog(logtext)
{
if(uroShowDebugOutput) console.log('URO+: '+logtext);
}
function uroGetCBChecked(cbID)
{
try
{
return(document.getElementById(cbID).checked);
}
catch(err)
{
return null;
}
}
function uroSetCBChecked(cbID, state)
{
try
{
document.getElementById(cbID).checked = state;
}
catch(err)
{
}
}
function uroGetElmValue(elmID)
{
try
{
return(document.getElementById(elmID).value);
}
catch(err)
{
return null;
}
}
function uroSetStyleDisplay(elm,style)
{
try
{
document.getElementById(elm).style.display = style;
}
catch(err)
{
}
}
function uroSetOnClick(elm,fn)
{
try
{
document.getElementById(elm).onclick = fn;
}
catch(err)
{
}
}
function uroAddEventListener(elm,eventType,eventFn,eventBool)
{
try
{
document.getElementById(elm).addEventListener(eventType, eventFn, eventBool);
}
catch(err)
{
}
}
function uroGetVisibilityBitmask()
{
if(W.map.mapState.getLayerVisibilityBitmask === undefined)
{
return W.map.mapState._getLayerVisibilityBitmask();
}
else return W.map.mapState.getLayerVisibilityBitmask();
}
function uroAlertBoxObj(headericon, title, content, hasCross, tickText, crossText, tickAction, crossAction)
{
this.headericon = headericon;
this.title = title;
this.content = content;
this.hasCross = hasCross;
this.tickText = tickText;
this.crossText = crossText;
this.tickAction = tickAction;
this.crossAction = crossAction;
}
function uroCloseAlertBox()
{
document.getElementById('uroAlerts').childNodes[0].innerHTML = '';
document.getElementById('uroAlerts').childNodes[1].innerHTML = '';
document.getElementById('uroAlertTickBtnCaption').innerHTML = '';
document.getElementById('uroAlertCrossBtnCaption').innerHTML = '';
uroAlertBoxTickAction = null;
uroAlertBoxCrossAction = null;
document.getElementById('uroAlerts').style.visibility = "hidden";
document.getElementById('uroAlertCrossBtn').style.visibility = "hidden";
uroAlertBoxInUse = false;
if(uroAlertBoxStack.length > 0)
{
uroBuildAlertBoxFromStack();
}
}
function uroCloseAlertBoxWithTick()
{
if(typeof uroAlertBoxTickAction === 'function')
{
uroAlertBoxTickAction();
}
uroCloseAlertBox();
}
function uroCloseAlertBoxWithCross()
{
if(typeof uroAlertBoxCrossAction === 'function')
{
uroAlertBoxCrossAction();
}
uroCloseAlertBox();
}
function uroShowAlertBox(headericon, title, content, hasCross, tickText, crossText, tickAction, crossAction)
{
uroAlertBoxStack.push(new uroAlertBoxObj(headericon, title, content, hasCross, tickText, crossText, tickAction, crossAction));
if(uroAlertBoxInUse === false)
{
uroBuildAlertBoxFromStack();
}
}
function uroBuildAlertBoxFromStack()
{
uroAlertBoxInUse = true;
uroAlertBoxTickAction = null;
uroAlertBoxCrossAction = null;
var titleContent = '<span style="font-size:14px;padding:2px;">';
titleContent += '<i class="fa '+uroAlertBoxStack[0].headericon+'"> </i> ';
titleContent += uroAlertBoxStack[0].title;
titleContent += '</span>';
document.getElementById('uroAlerts').childNodes[0].innerHTML = titleContent;
document.getElementById('uroAlerts').childNodes[1].innerHTML = uroAlertBoxStack[0].content;
document.getElementById('uroAlertTickBtnCaption').innerHTML = uroAlertBoxStack[0].tickText;
if(uroAlertBoxStack[0].hasCross)
{
document.getElementById('uroAlertCrossBtnCaption').innerHTML = uroAlertBoxStack[0].crossText;
document.getElementById('uroAlertCrossBtn').style.visibility = "visible";
if(typeof uroAlertBoxStack[0].crossAction === "function")
{
uroAlertBoxCrossAction = uroAlertBoxStack[0].crossAction;
}
}
else
{
document.getElementById('uroAlertCrossBtn').style.visibility = "hidden";
}
if(typeof uroAlertBoxStack[0].tickAction === "function")
{
uroAlertBoxTickAction = uroAlertBoxStack[0].tickAction;
}
document.getElementById('uroAlerts').style.visibility = "";
uroAlertBoxStack.shift();
}
function uroFirstTimerWelcomePack()
{
uroAddLog('welcome new users to Club URO...');
// for now, just show the update notes...
uroShowUpdateNotes();
}
function uroShowUpdateNotes()
{
uroAddLog('let existing users know what\'s new in this release');
var releaseNotes = '';
releaseNotes += '<p>Thanks for upgrading to URO+ '+uroVersion+' ('+uroReleaseDate+'). What\'s changed?</p>';
var loop;
if(uroChanges.length > 0)
{
releaseNotes += '<ul>';
for(loop=0; loop < uroChanges.length; loop++)
{
releaseNotes += '<li>'+uroChanges[loop];
}
releaseNotes += '</ul>';
}
if((uroBetaEditor) && (uroBetaChanges.length > 0))
{
releaseNotes += '<p>For WME Beta:<p>';
releaseNotes += '<ul>';
for(loop=0; loop < uroBetaChanges.length; loop++)
{
releaseNotes += '<li>'+uroBetaChanges[loop];
}
releaseNotes += '</ul>';
}
uroShowAlertBox('fa-info-circle', 'URO+ Release Notes', releaseNotes, false, "OK", "", null, null);
}
function uroAdvertiseCustomIcons()
{
uroAddLog('advertise the benefits of custom UR icons...');
var confirmMsg = '';
confirmMsg += '<p>Hi there. One of the features of URO+ that a lot of users find useful is the ability to use a custom marker for URs and MPs which have been tagged with a specific keyword in their description text.</p>';
confirmMsg += '<p>Markers are defined for <b>[ROADWORKS]</b>, <b>[CONSTRUCTION]</b>, <b>[CLOSURE]</b>, <b>[EVENT]</b>, <b>[NOTE]</b>, <b>[WSLM]</b>, <b>[BOG]</b> and <b>[DIFFICULT]</b> tags in URs, and <b>[TfL Open Data]</b>, <b>[Elgin]</b>, <b>[TM]</b>, <b>[TrafficCast]</b> and <b>[Caltrans]</b> in MPs.</p>';
confirmMsg += '<div style="background-image:'+uroAltMarkers[1]+';background-position:0 -523px;visibility:visible;height:40px;width:33px;float:left;"></div>';
confirmMsg += '<div style="background-image:'+uroAltMarkers[0]+';background-position:0 -523px;visibility:visible;height:40px;width:33px;float:left;"></div>';
confirmMsg += '<div style="background-image:'+uroAltMarkers[4]+';background-position:0 -523px;visibility:visible;height:40px;width:33px;float:left;"></div>';
confirmMsg += '<div style="background-image:'+uroAltMarkers[3]+';background-position:0 -523px;visibility:visible;height:40px;width:33px;float:left;"></div>';
confirmMsg += '<div style="background-image:'+uroAltMarkers[5]+';background-position:0 -523px;visibility:visible;height:40px;width:33px;float:left;"></div>';
confirmMsg += '<div style="background-image:'+uroAltMarkers[11]+';background-position:0 -523px;visibility:visible;height:40px;width:33px;float:left;"></div>';
confirmMsg += '<div style="background-image:'+uroAltMarkers[12]+';background-position:0 -523px;visibility:visible;height:40px;width:33px;float:left;"></div>';
confirmMsg += '<div style="background-image:'+uroAltMarkers[10]+';background-position:0 -25px;visibility:visible;height:40px;width:33px;float:left;"></div>';
confirmMsg += '<div style="background-image:'+uroAltMarkers[6]+';background-position:0 -25px;visibility:visible;height:40px;width:33px;float:left;"></div>';
confirmMsg += '<div style="background-image:'+uroAltMarkers[8]+';background-position:0 -25px;visibility:visible;height:40px;width:33px;float:left;"></div>';
confirmMsg += '<div style="background-image:'+uroAltMarkers[7]+';background-position:0 -25px;visibility:visible;height:40px;width:33px;float:left;"></div>';
confirmMsg += '<div style="background-image:'+uroAltMarkers[9]+';background-position:0 -25px;visibility:visible;height:40px;width:33px;float:left;"></div>';
confirmMsg += '<p style="clear:left;">Would you like me to automatically enable these custom markers?</p>';
confirmMsg += '<p>If you change your mind later on, they can be enabled/disabled via the Misc tab within the URO+ settings</p>';
uroShowAlertBox('fa-info-circle', 'URO+ Message to Users', confirmMsg, true, 'Yes please', 'No thanks', uroSetMarkerCBs, null);
}
function uroSetMarkerCBs()
{
uroSetCBChecked('_cbCustomRoadworksMarkers', true);
uroSetCBChecked('_cbCustomConstructionMarkers', true);
uroSetCBChecked('_cbCustomClosuresMarkers', true);
uroSetCBChecked('_cbCustomEventsMarkers', true);
uroSetCBChecked('_cbCustomNotesMarkers', true);
uroSetCBChecked('_cbCustomBOGMarkers', true);
uroSetCBChecked('_cbCustomDifficultMarkers', true);
uroSetCBChecked('_cbCustomWSLMMarkers', true);
uroSetCBChecked('_cbCustomNativeSLMarkers', true);
uroSetCBChecked('_cbCustomElginMarkers', true);
uroSetCBChecked('_cbCustomTrafficMasterMarkers', true);
uroSetCBChecked('_cbCustomTrafficCastMarkers', true);
uroSetCBChecked('_cbCustomCaltransMarkers', true);
uroSetCBChecked('_cbCustomTFLMarkers', true);
}
function uroGatherSettings(container)
{
var options = '';
var urOptions = document.getElementById(container).getElementsByTagName('input');
for (var optIdx=0;optIdx<urOptions.length;optIdx++)
{
var id = urOptions[optIdx].id;
if((id.indexOf('_cb') === 0)||(id.indexOf('_text') === 0)||(id.indexOf('_input') === 0))
{
options += ':' + id;
if(urOptions[optIdx].type == 'checkbox') options += ',' + urOptions[optIdx].checked.toString();
else if((urOptions[optIdx].type == 'text')||(urOptions[optIdx].type == 'number')) options += ',' + urOptions[optIdx].value.toString();
}
}
return options;
}
function uroGatherCamWatchList()
{
var liststr = '';
for(var loop=0;loop<uroCamWatchObjects.length;loop++)
{
var camObj = uroCamWatchObjects[loop];
if((camObj.fid != null) && (camObj.persistent === true))
{
if(loop > 0) liststr += ':';
liststr += camObj.fid+',';
liststr += camObj.watch.lon+',';
liststr += camObj.watch.lat+',';
liststr += camObj.watch.type+',';
liststr += camObj.watch.azymuth+',';
liststr += camObj.watch.speed+',';
liststr += camObj.watch.validated+',';
liststr += camObj.groupID+',';
liststr += camObj.server;
}
}
return liststr;
}
function uroGatherSegWatchList()
{
var liststr = '';
for(var loop=0;loop<uroSegWatchObjects.length;loop++)
{
var segObj = uroSegWatchObjects[loop];
if((segObj.fid != null) && (segObj.persistent === true))
{
if(loop > 0) liststr += ':';
liststr += segObj.fid+',';
liststr += segObj.watch.left+',';
liststr += segObj.watch.right+',';
liststr += segObj.watch.bottom+',';
liststr += segObj.watch.top+',';
liststr += segObj.watch.fromNode+',';
liststr += segObj.watch.toNode+',';
liststr += segObj.watch.fwdDir+',';
liststr += segObj.watch.revDir+',';
liststr += segObj.watch.length+',';
liststr += segObj.watch.level+',';
liststr += segObj.watch.rank+',';
liststr += segObj.watch.roadType+',';
liststr += segObj.watch.updatedOn+',';
liststr += segObj.groupID+',';
liststr += segObj.server;
}
}
return liststr;
}
function uroGatherPlaceWatchList()
{
var liststr = '';
for(var loop=0;loop<uroPlaceWatchObjects.length;loop++)
{
var placeObj = uroPlaceWatchObjects[loop];
if((placeObj.fid != null) && (placeObj.persistent === true))
{
if(loop > 0) liststr += ':';
liststr += placeObj.fid+',';
liststr += placeObj.watch.left+',';
liststr += placeObj.watch.right+',';
liststr += placeObj.watch.bottom+',';
liststr += placeObj.watch.top+',';
liststr += placeObj.watch.name+',';
liststr += placeObj.watch.imageCount+',';
liststr += placeObj.watch.residential+',';
liststr += placeObj.watch.updatedOn+',';
liststr += placeObj.groupID+',';
liststr += placeObj.server;
}
}
return liststr;
}
function uroGatherCWLGroups()
{
var liststr = '';
for(var loop=0;loop<uroCWLGroups.length;loop++)
{
var groupObj = uroCWLGroups[loop];
if(groupObj.groupID != -1)
{
if(loop > 0) liststr += ':';
liststr += groupObj.groupID+',';
liststr += groupObj.groupName+',';
liststr += groupObj.groupCollapsed;
}
}
return liststr;
}
function uroGatherPlacesGroups()
{
var liststr = '';
for(var loop=0;loop<uroPlacesGroupsCollapsed.length;loop++)
{
if(loop > 0) liststr += ':';
liststr += uroPlacesGroupsCollapsed[loop];
}
return liststr;
}
function uroGatherFriendlyAreaNames()
{
var liststr = '';
for(var loop=0;loop<uroFriendlyAreaNames.length;loop++)
{
var fnObj = uroFriendlyAreaNames[loop];
if(loop > 0) liststr += ':';
liststr += fnObj.fName+',';
liststr += fnObj.area+',';
liststr += fnObj.server;
}
return liststr;
}
function uroSaveSettings()
{
if(uroInhibitSave)
{
uroAddLog('save inhibited');
return;
}
if (localStorage)
{
localStorage.UROverviewUROptions = uroGatherSettings('uroCtrlURs');
localStorage.UROverviewMPOptions = uroGatherSettings('uroCtrlMPs');
localStorage.UROverviewCameraOptions = uroGatherSettings('uroCtrlCameras');
localStorage.UROverviewMiscOptions = uroGatherSettings('uroCtrlMisc');
localStorage.UROverviewPlacesOptions = uroGatherSettings('uroCtrlPlaces');
localStorage.UROverviewCamWatchList = uroGatherCamWatchList();
localStorage.UROverviewSegWatchList = uroGatherSegWatchList();
localStorage.UROverviewPlaceWatchList = uroGatherPlaceWatchList();
localStorage.UROverviewCWLGroups = uroGatherCWLGroups();
localStorage.UROverviewFriendlyAreaNames = uroGatherFriendlyAreaNames();
localStorage.UROverviewPlacesGroups = uroGatherPlacesGroups();
localStorage.UROverviewMasterEnable = uroGetCBChecked('_cbMasterEnable');
localStorage.UROverviewCurrentVersion = uroVersion;
uroAddLog('save complete');
}
else
{
uroAddLog('no localStorage, save blocked');
}
}
function uroApplySettings(settings)
{
var options = settings.split(':');
for(var optIdx=0;optIdx<options.length;optIdx++)
{
var fields = options[optIdx].split(',');
if(fields[0].indexOf('_cb') === 0)
{
if(document.getElementById(fields[0]) !== null)
{
uroSetCBChecked(fields[0], (fields[1] == 'true'));
}
}
else if((fields[0].indexOf('_input') === 0)||(fields[0].indexOf('_text') === 0))
{
if(document.getElementById(fields[0]) !== null) document.getElementById(fields[0]).value = fields[1];
}
}
}
function uroApplyCamWatchList()
{
var objects = localStorage.UROverviewCamWatchList.split(':');
uroCamWatchObjects = [];
if(objects.length > 0)
{
for(var objIdx=0;objIdx<objects.length;objIdx++)
{
var fields = objects[objIdx].split(',');
if(fields.length >= 7)
{
// following two bits of code add in blank fields if the user has updated their copy of URO+ from an
// older version which didn't include support for either of these field types
// add default groupID field
if(fields.length == 7)
{
fields.push(0);
}
// set default groupID value to 0 (no group)
if(fields[7] == -1)
{
fields[7] = 0;
}
// add default server field
if(fields.length == 8)
{
fields.push('??');
}
// set default server value to unknown
if(fields[8] === 0)
{
fields[8] = '??';
}
uroCamWatchObjects.push(new uroCamWatchObj(true,fields[0],fields[1],fields[2],fields[3],fields[4],fields[5],fields[6],fields[7],fields[8]));
}
}
}
}
/*
function uroApplySegWatchList()
{
var objects = localStorage.UROverviewSegWatchList.split(':');
uroSegWatchObjects = [];
for(var objIdx=0;objIdx<objects.length;objIdx++)
{
var fields = objects[objIdx].split(',');
uroSegWatchObjects.push(new uroSegWatchObj(true,fields[0],fields[1],fields[2],fields[3],fields[4],fields[5],fields[6],fields[7],fields[8],fields[9],fields[10],fields[11],fields[12],fields[13],fields[14],fields[15]));
}
}
function uroApplyPlaceWatchList()
{
var objects = localStorage.UROverviewPlaceWatchList.split(':');
uroPlaceWatchObjects = [];
for(var objIdx=0;objIdx<objects.length;objIdx++)
{
var fields = objects[objIdx].split(',');
uroPlaceWatchObjects.push(new uroPlaceWatchObj(true,fields[0],fields[1],fields[2],fields[3],fields[4],fields[5],fields[6],fields[7],fields[8],fields[9],fields[10]));
}
}
*/
function uroApplyCWLGroups()
{
var objects = localStorage.UROverviewCWLGroups.split(':');
uroCWLGroups = [];
if(objects.length === 0)
{
uroCWLGroups.push(new uroOWLGroupObj(0,'No group',false));
}
else
{
for(var objIdx=0;objIdx<objects.length;objIdx++)
{
var fields = objects[objIdx].split(',');
if(fields.length < 2)
{
fields.push(false);
}
uroCWLGroups.push(new uroOWLGroupObj(fields[0],fields[1],(fields[2] == 'true')));
}
}
}
/*
function uroApplyPlacesGroups()
{
var t = localStorage.UROverviewPlacesGroups.split(':');
for(var i=0;i<t.length;i++)
{
uroPlacesGroupsCollapsed[i] = (t[i] == "true");
}
}
*/
function uroApplyFriendlyAreaNames()
{
var objects = localStorage.UROverviewFriendlyAreaNames.split(':');
uroFriendlyAreaNames = [];
for(var objIdx=0;objIdx<objects.length;objIdx++)
{
var fields = objects[objIdx].split(',');
uroFriendlyAreaNames.push(new uroAFNObj(fields[0],parseFloat(fields[1]),fields[2]));
}
uroReplaceAreaNames(true);
}
function uroLoadSettings()
{
var isNewInstall = true;
var isUpgradeInstall = true;
var notifyAboutCustomIcons = true;
uroAddLog('loadSettings()');
if (localStorage.UROverviewUROptions != null)
{
uroAddLog('recover UR tab settings');
uroApplySettings(localStorage.UROverviewUROptions);
isNewInstall = false;
}
if (localStorage.UROverviewCameraOptions != null)
{
uroAddLog('recover camera tab settings');
uroApplySettings(localStorage.UROverviewCameraOptions);
isNewInstall = false;
}
if (localStorage.UROverviewMPOptions != null)
{
uroAddLog('recover MP tab settings');
uroApplySettings(localStorage.UROverviewMPOptions);
isNewInstall = false;
}
if (localStorage.UROverviewPlacesOptions != null)
{
uroAddLog('recover Places tab settings');
uroApplySettings(localStorage.UROverviewPlacesOptions);
isNewInstall = false;
}
if (localStorage.UROverviewMiscOptions != null)
{
uroAddLog('recover misc tab settings');
uroApplySettings(localStorage.UROverviewMiscOptions);
isNewInstall = false;
if(localStorage.UROverviewCurrentVersion != null)
{
notifyAboutCustomIcons = false;
}
else
{
if(uroGetCBChecked('_cbCustomRoadworksMarkers') === true) notifyAboutCustomIcons = false;
if(uroGetCBChecked('_cbCustomConstructionMarkers')=== true) notifyAboutCustomIcons = false;
if(uroGetCBChecked('_cbCustomClosuresMarkers') === true) notifyAboutCustomIcons = false;
if(uroGetCBChecked('_cbCustomEventsMarkers') === true) notifyAboutCustomIcons = false;
if(uroGetCBChecked('_cbCustomNotesMarkers') === true) notifyAboutCustomIcons = false;
if(uroGetCBChecked('_cbCustomWSLMMarkers') === true) notifyAboutCustomIcons = false;
if(uroGetCBChecked('_cbCustomBOGMarkers') === true) notifyAboutCustomIcons = false;
if(uroGetCBChecked('_cbCustomDifficultMarkers') === true) notifyAboutCustomIcons = false;
if(uroGetCBChecked('_cbCustomNativeSLMarkers') === true) notifyAboutCustomIcons = false;
}
}
if(localStorage.UROverviewCWLGroups != null)
{
uroAddLog('recover CWL groups');
uroApplyCWLGroups();
isNewInstall = false;
}
else
{
uroAddLog('set default CWL group');
uroCWLGroups.push(new uroOWLGroupObj(0,'No group',false));
}
if(localStorage.UROverviewCamWatchList != null)
{
uroAddLog('recover camera watchlist');
uroApplyCamWatchList();
uroGetCurrentCamWatchListObjects();
isNewInstall = false;
}
/*
if(localStorage.UROverviewSegWatchList != null)
{
uroAddLog('recover segment watchlist');
uroApplySegWatchList();
uroGetCurrentSegWatchListObjects();
isNewInstall = false;
}
if(localStorage.UROverviewPlaceWatchList != null)
{
uroAddLog('recover places watchlist');
uroApplyPlaceWatchList();
//uroGetCurrentPlaceWatchListObjects();
isNewInstall = false;
}
if(localStorage.UROverviewPlacesGroups != null)
{
uroAddLog('recover places groups');
uroApplyPlacesGroups();
isNewInstall = false;
}
*/
if(localStorage.UROverviewCurrentVersion != null)
{
uroAddLog('comparing install versions');
if(localStorage.UROverviewCurrentVersion == uroVersion)
{
isUpgradeInstall = false;
}
}
if(localStorage.UROverviewFriendlyAreaNames != null)
{
uroAddLog('recover friendly area names');
uroApplyFriendlyAreaNames();
isNewInstall = false;
}
if(localStorage.UROverviewMasterEnable != null)
{
uroAddLog('recover master enable state');
document.getElementById('_cbMasterEnable').checked = (localStorage.UROverviewMasterEnable == "true");
}
if(isNewInstall)
{
uroFirstTimerWelcomePack();
}
else if(isUpgradeInstall)
{
uroShowUpdateNotes();
}
if(notifyAboutCustomIcons)
{
uroAdvertiseCustomIcons();
}
uroInhibitSave = false;
}
function uroDefaultSettings()
{
uroShowAlertBox("fa-warning", "URO+ Warning", "Resetting URO+ settings <b>cannot</b> be undone.<br>Are you <i>sure</i> you want to do this?", true, "Reset settings", "Keep settings", uroDefaultSettingsAction, null);
}
function uroDefaultSettingsAction()
{
var defaultSettings = '';
defaultSettings += '[UROverviewMPOptions][len=628]:_cbMPFilterMissingJunction,false:_cbMPFilterMissingRoad,false:_cbMPFilterCrossroadsJunctionMissing,false:_cbMPFilterDrivingDirectionMismatch,false:_cbMPFilterRoadTypeMismatch,false:_cbMPFilterRestrictedTurn,false:_cbMPFilterRoadClosureProblem,false:_cbMPFilterUnknownProblem,false:_cbMPFilterTurnProblem,false:_cbMPFilterReopenedProblem,false:_cbInvertMPFilter,false:_cbMPFilterOutsideArea,false:_cbMPFilterClosed,false:_cbMPFilterSolved,false:_cbMPFilterUnidentified,false:_cbMPClosedUserIDFilter,false:_cbMPNotClosedUserIDFilter,false:_cbMPFilterLowSeverity,false:_cbMPFilterMediumSeverity,false:_cbMPFilterHighSeverity,false[END]';
defaultSettings += '[UROverviewPlaceWatchList][len=0][END]';
defaultSettings += '[UROverviewSegWatchList][len=0][END]';
defaultSettings += '[UROverviewPlacesGroups][len=59]false:false:false:false:false:false:false:false:false:false[END]';
defaultSettings += '[UROverviewMasterEnable][len=4]true[END]';
defaultSettings += '[UROverviewFriendlyAreaNames][len=0][END]';
defaultSettings += '[UROverviewMiscOptions][len=1222]:_cbNativeConvoMarkers,true:_cbNativeBetaConvoMarkers,true:_cbCommentCount,false:_cbURBackfill,false:_inputUnstackSensitivity,15:_inputUnstackZoomLevel,3:_cbCustomRoadworksMarkers,false:_cbCustomConstructionMarkers,false:_cbCustomClosuresMarkers,false:_cbCustomEventsMarkers,false:_cbCustomNotesMarkers,false:_cbCustomWSLMMarkers,false:_cbCustomKeywordMarkers,false:_textCustomKeyword,:_cbCustomElginMarkers,false:_cbCustomTrafficMasterMarkers,false:_cbCustomTrafficCastMarkers,false:_cbCustomCaltransMarkers,false:_inputPopupDwellTimeout,2:_inputPopupEntryTimeout,2:_inputMaxJitter,2:_cbInhibitURPopup,false:_cbInhibitMPPopup,false:_cbInhibitCamPopup,false:_cbInhibitSegPopup,false:_cbInhibitSegGenericPopup,false:_cbInhibitTurnsPopup,false:_cbInhibitLandmarkPopup,false:_cbInhibitPUPopup,false:_cbDateFmtDDMMYY,true:_cbDateFmtMMDDYY,false:_cbDateFmtYYMMDD,false:_cbTimeFmt24H,true:_cbTimeFmt12H,false:_cbWhiteBackground,false:_inputCustomBackgroundRed,255:_inputCustomBackgroundGreen,255:_inputCustomBackgroundBlue,255:_cbInhibitNURButton,false:_cbInhibitNMPButton,false:_cbInhibitNPURButton,false:_cbHideAMLayer,false:_cbDisablePlacesFiltering,false:_cbDisableTabStyling,false:_cbHideEditorInfo,false:_cbEnableDTE,false[END]';
defaultSettings += '[UROverviewUROptions][len=1685]:_cbURFilterOutsideArea,false:_cbNoFilterForURInURL,false:_cbFilterWazeAuto,false:_cbFilterIncorrectTurn,false:_cbFilterIncorrectAddress,false:_cbFilterIncorrectRoute,false:_cbFilterMissingRoundabout,false:_cbFilterGeneralError,false:_cbFilterTurnNotAllowed,false:_cbFilterIncorrectJunction,false:_cbFilterMissingBridgeOverpass,false:_cbFilterWrongDrivingDirection,false:_cbFilterMissingExit,false:_cbFilterMissingRoad,false:_cbFilterBlockedRoad,false:_cbFilterMissingLandmark,false:_cbFilterUndefined,false:_cbFilterRoadworks,false:_cbFilterConstruction,false:_cbFilterClosure,false:_cbFilterEvent,false:_cbFilterNote,false:_cbFilterWSLM,false:_cbInvertURFilter,false:_cbFilterOpenUR,false:_cbFilterClosedUR,false:_cbFilterSolved,false:_cbFilterUnidentified,false:_cbEnableMinAgeFilter,false:_inputFilterMinDays,:_cbEnableMaxAgeFilter,false:_inputFilterMaxDays,:_cbHideMyFollowed,false:_cbHideMyUnfollowed,false:_cbURDescriptionMustBePresent,false:_cbURDescriptionMustBeAbsent,false:_cbEnableKeywordMustBePresent,false:_textKeywordPresent,:_cbEnableKeywordMustBeAbsent,false:_textKeywordAbsent,:_cbCaseInsensitive,false:_cbHideMyComments,false:_cbHideAnyComments,false:_cbHideIfLastCommenter,false:_cbHideIfNotLastCommenter,false:_cbHideIfReporterLastCommenter,false:_cbHideIfReporterNotLastCommenter,false:_cbEnableMinCommentsFilter,false:_inputFilterMinComments,:_cbEnableMaxCommentsFilter,false:_inputFilterMaxComments,:_cbEnableCommentAgeFilter2,false:_inputFilterCommentDays2,:_cbEnableCommentAgeFilter,false:_inputFilterCommentDays,:_cbIgnoreOtherEditorComments,false:_cbURUserIDFilter,false:_cbURResolverIDFilter,false:_cbInvertURStateFilter,false:_cbNoFilterForTaggedURs,false[END]';
defaultSettings += '[UROverviewCameraOptions][len=878]:_cbShowWorldCams,true:_cbShowUSACams,true:_cbShowNonWorldCams,true:_cbShowOnlyCamsCreatedBy,false:_cbShowOnlyCamsEditedBy,false:_textCameraEditor,:_cbShowOnlyMyCams,false:_cbShowApprovedCams,true:_cbShowNonApprovedCams,true:_cbShowOlderCreatedNonApproved,false:_inputCameraMinCreatedDays,:_cbShowOlderUpdatedNonApproved,false:_inputCameraMinUpdatedDays,:_cbShowSpeedCams,true:_cbShowIfSpeedSet,true:_cbShowIfNoSpeedSet,true:_cbShowRedLightCams,true:_cbShowDummyCams,true:_cbHideCreatedByMe,false:_cbHideCreatedByRank0,false:_cbHideCreatedByRank1,false:_cbHideCreatedByRank2,false:_cbHideCreatedByRank3,false:_cbHideCreatedByRank4,false:_cbHideCreatedByRank5,false:_cbHideUpdatedByMe,false:_cbHideUpdatedByRank0,false:_cbHideUpdatedByRank1,false:_cbHideUpdatedByRank2,false:_cbHideUpdatedByRank3,false:_cbHideUpdatedByRank4,false:_cbHideUpdatedByRank5,false:_cbHideCWLCams,false[END]';
defaultSettings += '[UROverviewCamWatchList][len=0][END]';
defaultSettings += '[UROverviewPlacesOptions][len=5312]:_cbFilterUneditablePlaceUpdates,false:_cbFilterLockRankedPlaceUpdates,false:_cbFilterNewPlacePUR,false:_cbFilterUpdatedDetailsPUR,false:_cbFilterNewPhotoPUR,false:_cbFilterFlaggedPUR,false:_cbLeavePURGeos,false:_cbInvertPURFilters,false:_cbPURFilterLowSeverity,false:_cbPURFilterMediumSeverity,false:_cbPURFilterHighSeverity,false:_cbEnablePURMinAgeFilter,false:_inputPURFilterMinDays,:_cbEnablePURMaxAgeFilter,false:_inputPURFilterMaxDays,:_cbPlaceFilterEditedLessThan,false:_inputFilterPlaceEditMinDays,:_cbPlaceFilterEditedMoreThan,false:_inputFilterPlaceEditMaxDays,:_cbHidePlacesL0,false:_cbHidePlacesL1,false:_cbHidePlacesL2,false:_cbHidePlacesL3,false:_cbHidePlacesL4,false:_cbHidePlacesL5,false:_cbHidePlacesAdLocked,false:_cbHideAreaPlaces,false:_cbHidePointPlaces,false:_cbHidePhotoPlaces,false:_cbHideNoPhotoPlaces,false:_cbHideLinkedPlaces,false:_cbHideNoLinkedPlaces,false:_cbHideKeywordPlaces,false:_cbHideNoKeywordPlaces,false:_textKeywordPlace,:_cbPlacesFilter-CAR_SERVICES,false:_cbPlacesFilter-GAS_STATION,false:_cbPlacesFilter-PARKING_LOT,false:_cbPlacesFilter-GARAGE_AUTOMOTIVE_SHOP,false:_cbPlacesFilter-CAR_WASH,false:_cbPlacesFilter-CHARGING_STATION,false:_cbPlacesFilter-TRANSPORTATION,false:_cbPlacesFilter-AIRPORT,false:_cbPlacesFilter-BUS_STATION,false:_cbPlacesFilter-FERRY_PIER,false:_cbPlacesFilter-SEAPORT_MARINA_HARBOR,false:_cbPlacesFilter-SUBWAY_STATION,false:_cbPlacesFilter-TRAIN_STATION,false:_cbPlacesFilter-BRIDGE,false:_cbPlacesFilter-TUNNEL,false:_cbPlacesFilter-TAXI_STATION,false:_cbPlacesFilter-JUNCTION_INTERCHANGE,false:_cbPlacesFilter-PROFESSIONAL_AND_PUBLIC,false:_cbPlacesFilter-COLLEGE_UNIVERSITY,false:_cbPlacesFilter-SCHOOL,false:_cbPlacesFilter-CONVENTIONS_EVENT_CENTER,false:_cbPlacesFilter-GOVERNMENT,false:_cbPlacesFilter-LIBRARY,false:_cbPlacesFilter-CITY_HALL,false:_cbPlacesFilter-ORGANIZATION_OR_ASSOCIATION,false:_cbPlacesFilter-PRISON_CORRECTIONAL_FACILITY,false:_cbPlacesFilter-COURTHOUSE,false:_cbPlacesFilter-CEMETERY,false:_cbPlacesFilter-FIRE_DEPARTMENT,false:_cbPlacesFilter-POLICE_STATION,false:_cbPlacesFilter-MILITARY,false:_cbPlacesFilter-HOSPITAL_MEDICAL_CARE,false:_cbPlacesFilter-OFFICES,false:_cbPlacesFilter-POST_OFFICE,false:_cbPlacesFilter-RELIGIOUS_CENTER,false:_cbPlacesFilter-KINDERGARDEN,false:_cbPlacesFilter-FACTORY_INDUSTRIAL,false:_cbPlacesFilter-EMBASSY_CONSULATE,false:_cbPlacesFilter-INFORMATION_POINT,false:_cbPlacesFilter-SHOPPING_AND_SERVICES,false:_cbPlacesFilter-ARTS_AND_CRAFTS,false:_cbPlacesFilter-BANK_FINANCIAL,false:_cbPlacesFilter-SPORTING_GOODS,false:_cbPlacesFilter-BOOKSTORE,false:_cbPlacesFilter-PHOTOGRAPHY,false:_cbPlacesFilter-CAR_DEALERSHIP,false:_cbPlacesFilter-FASHION_AND_CLOTHING,false:_cbPlacesFilter-CONVENIENCE_STORE,false:_cbPlacesFilter-PERSONAL_CARE,false:_cbPlacesFilter-DEPARTMENT_STORE,false:_cbPlacesFilter-PHARMACY,false:_cbPlacesFilter-ELECTRONICS,false:_cbPlacesFilter-FLOWERS,false:_cbPlacesFilter-FURNITURE_HOME_STORE,false:_cbPlacesFilter-GIFTS,false:_cbPlacesFilter-GYM_FITNESS,false:_cbPlacesFilter-SWIMMING_POOL,false:_cbPlacesFilter-HARDWARE_STORE,false:_cbPlacesFilter-MARKET,false:_cbPlacesFilter-SUPERMARKET_GROCERY,false:_cbPlacesFilter-JEWELRY,false:_cbPlacesFilter-LAUNDRY_DRY_CLEAN,false:_cbPlacesFilter-SHOPPING_CENTER,false:_cbPlacesFilter-MUSIC_STORE,false:_cbPlacesFilter-PET_STORE_VETERINARIAN_SERVICES,false:_cbPlacesFilter-TOY_STORE,false:_cbPlacesFilter-TRAVEL_AGENCY,false:_cbPlacesFilter-ATM,false:_cbPlacesFilter-CURRENCY_EXCHANGE,false:_cbPlacesFilter-CAR_RENTAL,false:_cbPlacesFilter-FOOD_AND_DRINK,false:_cbPlacesFilter-RESTAURANT,false:_cbPlacesFilter-BAKERY,false:_cbPlacesFilter-DESSERT,false:_cbPlacesFilter-CAFE,false:_cbPlacesFilter-FAST_FOOD,false:_cbPlacesFilter-FOOD_COURT,false:_cbPlacesFilter-BAR,false:_cbPlacesFilter-ICE_CREAM,false:_cbPlacesFilter-CULTURE_AND_ENTERTAINEMENT,false:_cbPlacesFilter-ART_GALLERY,false:_cbPlacesFilter-CASINO,false:_cbPlacesFilter-CLUB,false:_cbPlacesFilter-TOURIST_ATTRACTION_HISTORIC_SITE,false:_cbPlacesFilter-MOVIE_THEATER,false:_cbPlacesFilter-MUSEUM,false:_cbPlacesFilter-MUSIC_VENUE,false:_cbPlacesFilter-PERFORMING_ARTS_VENUE,false:_cbPlacesFilter-GAME_CLUB,false:_cbPlacesFilter-STADIUM_ARENA,false:_cbPlacesFilter-THEME_PARK,false:_cbPlacesFilter-ZOO_AQUARIUM,false:_cbPlacesFilter-RACING_TRACK,false:_cbPlacesFilter-THEATER,false:_cbPlacesFilter-OTHER,false:_cbPlacesFilter-CONSTRUCTION_SITE,false:_cbPlacesFilter-LODGING,false:_cbPlacesFilter-HOTEL,false:_cbPlacesFilter-HOSTEL,false:_cbPlacesFilter-CAMPING_TRAILER_PARK,false:_cbPlacesFilter-COTTAGE_CABIN,false:_cbPlacesFilter-BED_AND_BREAKFAST,false:_cbPlacesFilter-OUTDOORS,false:_cbPlacesFilter-PARK,false:_cbPlacesFilter-PLAYGROUND,false:_cbPlacesFilter-BEACH,false:_cbPlacesFilter-SPORTS_COURT,false:_cbPlacesFilter-GOLF_COURSE,false:_cbPlacesFilter-PLAZA,false:_cbPlacesFilter-PROMENADE,false:_cbPlacesFilter-POOL,false:_cbPlacesFilter-SCENIC_LOOKOUT_VIEWPOINT,false:_cbPlacesFilter-SKI_AREA,false:_cbPlacesFilter-NATURAL_FEATURES,false:_cbPlacesFilter-ISLAND,false:_cbPlacesFilter-SEA_LAKE_POOL,false:_cbPlacesFilter-RIVER_STREAM,false:_cbPlacesFilter-FOREST_GROVE,false:_cbPlacesFilter-FARM,false:_cbPlacesFilter-CANAL,false:_cbPlacesFilter-SWAMP_MARSH,false:_cbPlacesFilter-DAM,false:_cbFilterPrivatePlaces,false:_cbInvertPlacesFilter,false[END]';
defaultSettings += '[UROverviewCurrentVersion][len=0][END]';
defaultSettings += '[UROverviewCWLGroups][len=16]0,No group,false[END]';
document.getElementById('_txtSettings').value = defaultSettings;
uroTextToSettings();
document.getElementById('_txtSettings').value = '';
}
function uroSettingsToText()
{
var txtSettings = '';
uroSaveSettings();
for(var lsEntry in localStorage)
{
if(lsEntry.indexOf('UROverview') === 0)
{
txtSettings += '['+lsEntry+'][len=' + localStorage[lsEntry].length + ']' + localStorage[lsEntry] + '[END]\n';
}
}
document.getElementById('_txtSettings').value = txtSettings;
document.getElementById('_txtSettings').focus();
document.getElementById('_txtSettings').select();
}
function uroTextToSettings()
{
var txtSettings = '';
txtSettings = uroGetElmValue('_txtSettings');
if(txtSettings.indexOf('[END]') == -1) return;
var subText = txtSettings.split('[END]');
for(var i=0;i<subText.length;i++)
{
var aPos = subText[i].indexOf('[');
var bPos = subText[i].indexOf(']');
if((aPos != -1) && (bPos != -1))
{
var settingID = subText[i].substr(aPos+1,bPos-1-aPos);
subText[i] = subText[i].substr(bPos+1);
bPos = subText[i].indexOf(']');
if(bPos != -1)
{
var settingLength = subText[i].substr(5,bPos-5);
subText[i] = subText[i].substr(bPos+1);
if(subText[i].length == settingLength)
{
localStorage[settingID] = subText[i];
}
}
}
}
uroLoadSettings();
}
function uroClearSettingsText()
{
document.getElementById('_txtSettings').value = '';
}
function uroDateToDays(dateToConvert)
{
var dateNow = new Date();
var elapsedSinceEpoch = dateNow.getTime();
var elapsedSinceEvent = elapsedSinceEpoch - dateToConvert;
dateNow.setHours(0);
dateNow.setMinutes(0);
dateNow.setSeconds(0);
dateNow.setMilliseconds(0);
var elapsedSinceMidnight = elapsedSinceEpoch - dateNow.getTime();
if(elapsedSinceEvent < elapsedSinceMidnight)
{
// event occurred today...
return 0;
}
else
{
// event occurred at some point prior to midnight this morning, so return a minimum value of 1...
return 1 + Math.floor((elapsedSinceEvent - elapsedSinceMidnight) / 86400000);
}
}
function uroGetURAge(urObj,ageType,getRaw)
{
if(ageType === 0)
{
if((urObj.attributes.driveDate === null)||(urObj.attributes.driveDate === 0)) return -1;
if(getRaw) return urObj.attributes.driveDate;
else return uroDateToDays(urObj.attributes.driveDate);
}
else if(ageType === 1)
{
if((urObj.attributes.resolvedOn === null)||(urObj.attributes.resolvedOn === 0)) return -1;
if(getRaw) return urObj.attributes.resolvedOn;
else return uroDateToDays(urObj.attributes.resolvedOn);
}
else
{
return -1;
}
}
function uroGetPURAge(purObj)
{
if(purObj.attributes.venueUpdateRequests[0].attributes.dateAdded !== null)
{
return uroDateToDays(purObj.attributes.venueUpdateRequests[0].attributes.dateAdded);
}
else
{
return -1;
}
}
function uroGetCameraAge(camObj, mode)
{
if(mode === 0)
{
if(camObj.attributes.updatedOn === null) return -1;
return uroDateToDays(camObj.attributes.updatedOn);
}
if(mode === 1)
{
if(camObj.attributes.createdOn === null) return -1;
return uroDateToDays(camObj.attributes.createdOn);
}
}
function uroGetCommentAge(commentObj)
{
if(commentObj.createdOn === null) return -1;
return uroDateToDays(commentObj.createdOn);
}
function uroParseDaysAgo(days)
{
if(days === 0) return 'today';
else if(days === 1) return '1 day ago';
else return days+' days ago';
}
function uroGetLocalisedSpeedString(camSpeed)
{
if(camSpeed !== null)
{
var conversionFactor = 1; // default to metric
var multipleFactor = 10; // default to limits being set in multiples of 10
var country;
if(W.model.countries.top === undefined)
{
country = W.model.countries.additionalInfo[0].name;
}
else
{
country = W.model.countries.top.name;
}
if(country !== null)
{
// country-specific deviations from the above...
if
(
(country == "United Kingdom") ||
(country == "Jersey") ||
(country == "Guernsey") ||
(country == "United States")
)
{
// countries using MPH
conversionFactor = 1.609;
}
if
(
(country == "United States") ||
(country == "Guernsey")
)
{
// countries with speed limits set in multiples of 5
multipleFactor = 5;
}
}
var speed = Math.round(camSpeed / conversionFactor);
var retval = speed;
if(conversionFactor == 1) retval += "KM/H";
else retval += "MPH";
if(speed % multipleFactor !== 0) retval += " (not valid?)";
return retval;
}
else return "not set";
}
// --------------------------------------------------------------------------------------------------------------------
// AREA FRIENDLYNAME STUFF
// --------------------------------------------------------------------------------------------------------------------
function uroAFNObj(fName, area, server)
{
this.fName = fName;
this.area = area;
this.server = server;
}
function uroUpdateAreaName(name, server, area)
{
var foundExisting = false;
for(var i=0; i<uroFriendlyAreaNames.length; i++)
{
if((uroFriendlyAreaNames[i].server == server) && (uroFriendlyAreaNames[i].area == area))
{
if(name === "")
{
uroFriendlyAreaNames.splice(i,1);
foundExisting = true;
}
else
{
uroFriendlyAreaNames[i].fName = name;
foundExisting = true;
}
}
}
if((foundExisting === false) && (name !== ""))
{
uroFriendlyAreaNames.push(new uroAFNObj(name,area,server));
}
uroReplaceAreaNames(true);
}
function uroAreaNameHover()
{
if((uroAreaNameHoverObj === null) || (uroAreaNameHoverObj != this))
{
uroAreaNameHoverTime = 0;
}
uroAreaNameHoverObj = this;
}
function uroAreaNameUnHover()
{
if(uroANEditHovered === true)
{
return false;
}
if(uroAreaNameOverlayShown)
{
uroAreaNameHoverObj.removeChild(uroANEditBox);
}
uroAreaNameHoverObj = null;
uroAreaNameHoverTime = -1;
uroAreaNameOverlayShown = false;
}
function uroANEditHover()
{
uroANEditHovered = true;
uroAddEventListener('uroANEditBox','mouseout',uroANEditUnHover,false);
uroAddEventListener('uroANEditBox','click',uroANEditClick,false);
}
function uroANEditUnHover()
{
var newName = document.getElementById('_textAreaName').value;
// sanitise name to avoid conflicts with config storage delimiters...
newName = newName.replace(',','');
newName = newName.replace(':','');
var server = W.location.code;
var area = uroGetAreaArea(uroAreaNameHoverObj.parentNode.children[1]);
uroAreaNameHoverObj.removeChild(uroANEditBox);
uroAreaNameOverlayShown = false;
uroANEditHovered = false;
uroUpdateAreaName(newName, server, area);
}
function uroANEditClick(e)
{
// this traps the click to prevent it falling through to the underlying area name element and
// potentially causing the map view to be relocated to that area...
e.stopPropagation();
}
function uroGetAreaArea(listObj)
{
var area = listObj.getElementsByTagName('span')[0].innerHTML;
area = parseFloat(area.split(' ')[0]);
return area;
}
function uroAreaNameOverlaySetup()
{
uroAreaNameOverlayShown = true;
uroANEditBox = document.createElement('div');
uroANEditBox.id = "uroANEditBox";
uroANEditBox.style.position = "absolute";
uroANEditBox.style.top = '7px';
uroANEditBox.style.left = '2px';
uroANEditBox.style.width = "99%";
uroAreaNameHoverObj.appendChild(uroANEditBox);
uroANEditBox.onmouseover = uroANEditHover();
var existingName = uroAreaNameHoverObj.innerHTML;
var italicTagPos = existingName.indexOf(' <i>');
if(italicTagPos == -1)
{
existingName = "";
}
else
{
existingName = existingName.substr(0,italicTagPos);
}
uroANEditBox.innerHTML = '<input type="text" style="font-size:14px; line-height:16px; height:22px; width:100%" id="_textAreaName" value="'+existingName+'">';
}
function uroReplaceAreaNames(replaceAfterNameChange)
{
if(document.getElementById('sidepanel-areas') === undefined)
{
return;
}
if(replaceAfterNameChange === false)
{
if(document.getElementById('sidepanel-areas').getElementsByClassName('result-list')[0].id == "friendlyNamed")
{
return;
}
}
var panelRootObj = document.getElementById('sidepanel-areas').getElementsByClassName('result-list')[0];
if(panelRootObj === undefined)
{
// we get here if the user doesn't have any areas defined...
return;
}
var areaCount = panelRootObj.children.length;
if(areaCount === 0)
{
return;
}
var localisedManagedArea = I18n.lookup("user.areas.managed_area");
for(var loop=0; loop < areaCount; loop++)
{
var childObjPElems = panelRootObj.children[loop].getElementsByTagName('p');
var title = childObjPElems[0].innerHTML;
if(title.indexOf(localisedManagedArea) > -1)
{
var area = uroGetAreaArea(childObjPElems[1]);
childObjPElems[0].innerHTML = localisedManagedArea;
for(var fnIdx=0; fnIdx < uroFriendlyAreaNames.length; fnIdx++)
{
var fnObj = uroFriendlyAreaNames[fnIdx];
if((fnObj.area == area) && (fnObj.server == W.location.code))
{
childObjPElems[0].innerHTML = fnObj.fName +' <i>('+localisedManagedArea+')</i>';
break;
}
}
var titleObj = panelRootObj.getElementsByClassName('title')[loop];
titleObj.addEventListener("mouseover", uroAreaNameHover, false);
titleObj.addEventListener("mouseout", uroAreaNameUnHover, false);
titleObj.style.cursor = "text";
}
}
document.getElementById('sidepanel-areas').getElementsByClassName('result-list')[0].id = "friendlyNamed";
}
// --------------------------------------------------------------------------------------------------------------------
// WATCHLIST STUFF
// --------------------------------------------------------------------------------------------------------------------
// Generic Functions
function uroTypeCast(varin)
{
if(varin == "null") return null;
if(typeof varin == "string") return parseInt(varin);
return varin;
}
function uroTruncate(val)
{
if(val === null) return val;
if(val < 0) return Math.ceil(val);
return Math.floor(val);
}
function uroOWLGroupObj(groupID, groupName, groupCollapsed)
{
groupID = uroTypeCast(groupID);
this.groupID = groupID;
this.groupName = groupName;
this.groupCount = 0;
this.groupCollapsed = groupCollapsed;
}
// Camera Functions
function uroCamWatchObjCheckProps(type, azymuth, speed, validated, lat, lon)
{
if(type !== null) type = uroTypeCast(type);
if(azymuth !== null) azymuth = uroTruncate(uroTypeCast(azymuth)%360);
if(speed !== null) speed = uroTruncate(uroTypeCast(speed));
if(typeof validated == "string") validated = (validated == "true");
if(lat !== null) lat = uroTruncate(uroTypeCast(lat));
if(lon !== null) lon = uroTruncate(uroTypeCast(lon));
this.type = type;
this.azymuth = azymuth;
this.speed = speed;
this.validated = validated;
this.lat = lat;
this.lon = lon;
}
function uroCamWatchObj(persistent, fid, lon, lat, type, azymuth, speed, validated, groupID, server)
{
fid = uroTypeCast(fid);
groupID = uroTypeCast(groupID);
if(typeof persistent == "string") persistent = (persistent == "true");
this.fid = fid;
this.persistent = persistent;
this.loaded = false;
this.server = server;
this.groupID = groupID;
this.watch = new uroCamWatchObjCheckProps(type, azymuth, speed, validated, lat, lon);
this.current = new uroCamWatchObjCheckProps(null, null, null, null, null, null);
}
function uroCamDataChanged(idx)
{
var camObj = uroCamWatchObjects[idx];
if(camObj.loaded === false) return false;
if(camObj.current.type != camObj.watch.type) return true;
if(camObj.current.azymuth != camObj.watch.azymuth) return true;
if(camObj.current.speed != camObj.watch.speed) return true;
if(camObj.current.validated != camObj.watch.validated) return true;
if(camObj.current.lat != camObj.watch.lat) return true;
if(camObj.current.lon != camObj.watch.lon) return true;
return false;
}
function uroFindCWLGroupByIdx(groupIdx)
{
var groupName = '';
for(var loop=0;loop<uroCWLGroups.length;loop++)
{
if(uroCWLGroups[loop].groupID == groupIdx)
{
groupName = uroCWLGroups[loop].groupName;
break;
}
}
return groupName;
}
function uroIsCamOnWatchList(fid)
{
for(var loop=0;loop<uroCamWatchObjects.length;loop++)
{
if(uroCamWatchObjects[loop].fid == fid) return loop;
}
return -1;
}
function uroAddCurrentCamWatchData(idx, lat, lon, type, azymuth, speed, validated, server)
{
var camObj = uroCamWatchObjects[idx];
camObj.loaded = true;
camObj.server = server;
camObj.current = new uroCamWatchObjCheckProps(type, azymuth, speed, validated, lat, lon);
return(uroCamDataChanged(idx));
}
function uroAddCamToWatchList()
{
if(uroIsCamOnWatchList(uroShownFID) == -1)
{
var camObj = W.model.cameras.objects[uroShownFID];
uroCamWatchObjects.push(new uroCamWatchObj(true, uroShownFID, camObj.geometry.x, camObj.geometry.y, camObj.attributes.type, camObj.attributes.azymuth, camObj.attributes.speed, camObj.attributes.validated, 0, W.location.code));
uroAddCurrentCamWatchData(uroCamWatchObjects.length-1, camObj.geometry.y, camObj.geometry.x, camObj.attributes.type, camObj.attributes.azymuth, camObj.attributes.speed, camObj.attributes.validated, W.location.code);
uroAddLog('added camera '+uroShownFID+' to watchlist');
uroOWLUpdateHTML();
}
}
function uroRemoveCamFromWatchList()
{
var camidx = uroIsCamOnWatchList(uroShownFID);
if(camidx != -1)
{
uroCamWatchObjects.splice(camidx,1);
uroAddLog('removed camera '+uroShownFID+' from watchlist');
uroOWLUpdateHTML();
}
}
function uroUpdateCamWatchList()
{
var camIdx = uroIsCamOnWatchList(uroShownFID);
if(camIdx != -1)
{
var camObj = W.model.cameras.objects[uroShownFID];
uroCamWatchObjects[camIdx].watch = new uroCamWatchObjCheckProps(camObj.attributes.type, camObj.attributes.azymuth, camObj.attributes.speed, camObj.attributes.validated, camObj.geometry.y, camObj.geometry.x);
}
}
function uroClearCamWatchList()
{
uroShowAlertBox("fa-warning", "URO+ Warning", "Removing all cameras from the OWL <b>cannot</b> be undone.<br>Are you <i>sure</i> you want to do this?", true, "Delete ALL Cameras", "Keep Cameras", uroClearCamWatchListAction, null);
}
function uroClearCamWatchListAction()
{
uroCamWatchObjects = [];
uroOWLUpdateHTML();
}
function uroRetrieveCameras(lat, lon)
{
var camPos = new OpenLayers.LonLat();
var camChanged = false;
camPos.lon = lon;
camPos.lat = lat;
camPos.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326"));
var camURL = 'https://' + document.location.host;
camURL += Waze.Config.api_base;
camURL += '/Features?language=en&cameras=true&bbox=';
var latl = camPos.lat - 0.25;
var latu = camPos.lat + 0.25;
var lonl = camPos.lon - 0.25;
var lonr = camPos.lon + 0.25;
camURL += lonl+','+latl+','+lonr+','+latu;
uroAddLog('retrieving camera data around '+camPos.lon+','+camPos.lat);
var camReq = new XMLHttpRequest();
camReq.open('GET',camURL,false);
try
{
camReq.send();
uroAddLog('response '+camReq.status+' received');
if (camReq.status === 200)
{
var camData = JSON.parse(camReq.responseText);
for(var camIdx = 0; camIdx < camData.cameras.objects.length; camIdx++)
{
var camObj = camData.cameras.objects[camIdx];
var listIdx = uroIsCamOnWatchList(camObj.id);
if(listIdx != -1)
{
camPos.lon = camObj.geometry.coordinates[0];
camPos.lat = camObj.geometry.coordinates[1];
camPos.transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913"));
camPos.lon = uroTruncate(camPos.lon);
camPos.lat = uroTruncate(camPos.lat);
camChanged |= uroAddCurrentCamWatchData(listIdx, camPos.lat, camPos.lon, camObj.type, camObj.azymuth, camObj.speed, camObj.validated, W.location.code);
}
else if(camObj.validated === false)
{
}
}
}
else
{
uroAddLog('request failed (status != 200)');
}
}
catch(err)
{
uroAddLog('camera load request failed (exception '+err+' caught)');
}
return camChanged;
}
function uroGetCurrentCamWatchListObjects()
{
var camChanged = false;
var camsChanged = [];
var camsDeleted = [];
var camidx;
var camObj;
for(camidx=0;camidx<uroCamWatchObjects.length;camidx++)
{
camObj = uroCamWatchObjects[camidx];
if((camObj.loaded === false) && ((camObj.server == W.location.code) || (camObj.server == '??')))
{
if(typeof W.model.cameras.objects[camObj.fid] == 'object')
{
if(W.model.cameras.objects[camObj.fid].state != "Delete")
{
var wazeObj = W.model.cameras.objects[camObj.fid];
camChanged |= uroAddCurrentCamWatchData(camidx, wazeObj.geometry.y, wazeObj.geometry.x, wazeObj.attributes.type, wazeObj.attributes.azymuth, wazeObj.attributes.speed, wazeObj.attributes.validated);
}
else
{
camChanged |= uroRetrieveCameras(camObj.watch.lat, camObj.watch.lon);
}
}
else
{
camChanged |= uroRetrieveCameras(camObj.watch.lat, camObj.watch.lon);
}
}
}
if(camChanged)
{
for(camidx=0;camidx<uroCamWatchObjects.length;camidx++)
{
if(uroCamDataChanged(camidx))
{
camsChanged.push(uroCamWatchObjects[camidx]);
}
}
}
for(camidx=0;camidx<uroCamWatchObjects.length;camidx++)
{
camObj = uroCamWatchObjects[camidx];
if((camObj.loaded === false) && (camObj.server == W.location.code))
{
camsDeleted.push(camObj);
}
}
if((camsChanged.length > 0) || (camsDeleted.length > 0))
{
var alertStr = '';
for(camidx=0;camidx<camsChanged.length;camidx++)
{
alertStr += 'Camera ID '+camsChanged[camidx].fid+' in group "'+uroFindCWLGroupByIdx(camsChanged[camidx].groupID)+'" has been changed<br>';
}
alertStr += '<br>';
for(camidx=0;camidx<camsDeleted.length;camidx++)
{
alertStr += 'Camera ID '+camsDeleted[camidx].fid+' in group "'+uroFindCWLGroupByIdx(camsDeleted[camidx].groupID)+'" has been deleted<br>';
}
uroShowAlertBox("fa-info-circle", "URO+ Camera Watchlist Alert", alertStr, false, "OK", null, null, null);
}
}
function uroClearDeletedCameras()
{
for(var camidx=uroCamWatchObjects.length-1;camidx>=0;camidx--)
{
if(uroCamWatchObjects[camidx].loaded === false)
{
uroShownFID = uroCamWatchObjects[camidx].fid;
uroRemoveCamFromWatchList();
}
}
}
function uroClearUnknownServerCameras()
{
var confirmMsg = '<p>Cameras with an unknown server <i>cannot</i> be automatically verified by URO+</p>';
confirmMsg += 'It is recommended that you manually load WME from each server (World, USA/Canada and Israel) to give URO+ a chance of locating these cameras.<br>';
confirmMsg += 'If the cameras then continue to show up as an unknown server, it is safe to delete them...<br><br>';
confirmMsg += 'Do you still wish to proceed with deleting all unknown server cameras?';
uroShowAlertBox("fa-warning", "URO+ Warning", confirmMsg, true, "Delete unknown cameras", "Keep unknown cameras", uroClearUnknownServerCamerasAction, null);
}
function uroClearUnknownServerCamerasAction()
{
for(var camidx=uroCamWatchObjects.length-1;camidx>=0;camidx--)
{
if(uroCamWatchObjects[camidx].server == '??')
{
uroShownFID = uroCamWatchObjects[camidx].fid;
uroRemoveCamFromWatchList();
}
}
}
function uroRescanCamWatchList()
{
for(var camidx=0;camidx<uroCamWatchObjects.length;camidx++)
{
uroCamWatchObjects[camidx].loaded = false;
}
uroGetCurrentCamWatchListObjects();
uroOWLUpdateHTML();
}
function uroGotoCam()
{
var camidx = this.id.substr(13);
var camPos = new OpenLayers.LonLat();
camPos.lon = uroCamWatchObjects[camidx].watch.lon;
camPos.lat = uroCamWatchObjects[camidx].watch.lat;
W.map.setCenter(camPos,4);
W.map.camerasLayer.setVisibility(true);
return false;
}
// Segment Functions
/*
function uroSegWatchObjCheckProps(left, right, bottom, top, fromNode, toNode, fwdDir, revDir, length, level, rank, roadType, updatedOn)
{
if(left !== null) left = uroTruncate(uroTypeCast(left));
if(right !== null) right = uroTruncate(uroTypeCast(right));
if(bottom !== null) bottom = uroTruncate(uroTypeCast(bottom));
if(top !== null) top = uroTruncate(uroTypeCast(top));
if(fromNode !== null) fromNode = uroTypeCast(fromNode);
if(toNode !== null) toNode = uroTypeCast(toNode);
if(fwdDir !== null) fwdDir = uroTypeCast(fwdDir);
if(revDir !== null) revDir = uroTypeCast(revDir);
if(length !== null) length = uroTypeCast(length);
if(level !== null) level = uroTypeCast(level);
if(rank !== null) rank = uroTypeCast(rank);
if(roadType !== null) roadType = uroTypeCast(roadType);
if(updatedOn !== null) updatedOn = uroTypeCast(updatedOn);
this.left = left;
this.right = right;
this.bottom = bottom;
this.top = top;
this.fromNode = fromNode;
this.toNode = toNode;
this.fwdDir = fwdDir;
this.revDir = revDir;
this.length = length;
this.level = level;
this.rank = rank;
this.roadType = roadType;
this.updatedOn = updatedOn;
}
function uroSegWatchObj(persistent, fid, left, right, bottom, top, fromNode, toNode, fwdDir, revDir, length, level, rank, roadType, updatedOn, groupID, server)
{
fid = uroTypeCast(fid);
groupID = uroTypeCast(groupID);
if(typeof persistent == "string") persistent = (persistent == "true");
this.fid = fid;
this.persistent = persistent;
this.loaded = false;
this.server = server;
this.groupID = groupID;
this.watch = new uroSegWatchObjCheckProps(left, right, bottom, top, fromNode, toNode, fwdDir, revDir, length, level, rank, roadType, updatedOn);
this.current = new uroSegWatchObjCheckProps(null, null, null, null, null, null, null, null, null, null, null, null, null);
}
function uroSegDataChanged(idx)
{
var segObj = uroSegWatchObjects[idx];
if(segObj.loaded === false) return false;
if(segObj.current.left != segObj.watch.left) return true;
if(segObj.current.right != segObj.watch.right) return true;
if(segObj.current.bottom != segObj.watch.bottom) return true;
if(segObj.current.top != segObj.watch.top) return true;
if(segObj.current.fromNode != segObj.watch.fromNode) return true;
if(segObj.current.toNode != segObj.watch.toNode) return true;
if(segObj.current.fwdDir != segObj.watch.fwdDir) return true;
if(segObj.current.revDir != segObj.watch.revDir) return true;
if(segObj.current.length != segObj.watch.length) return true;
if(segObj.current.level != segObj.watch.level) return true;
if(segObj.current.rank != segObj.watch.rank) return true;
if(segObj.current.roadType != segObj.watch.roadType) return true;
if(segObj.current.updatedOn != segObj.watch.updatedOn) return true;
return false;
}
function uroIsSegOnWatchList(fid)
{
for(var loop=0;loop<uroSegWatchObjects.length;loop++)
{
if(uroSegWatchObjects[loop].fid == fid) return loop;
}
return -1;
}
function uroAddCurrentSegWatchData(idx, left, right, bottom, top, fromNode, toNode, fwdDir, revDir, length, level, rank, roadType, updatedOn, server)
{
var segObj = uroSegWatchObjects[idx];
segObj.loaded = true;
segObj.server = server;
segObj.current = new uroSegWatchObjCheckProps(left, right, bottom, top, fromNode, toNode, fwdDir, revDir, length, level, rank, roadType, updatedOn);
return(uroSegDataChanged(idx));
}
function uroClearSegWatchList()
{
if(confirm('Removing all segments from the OWL cannot be undone\nAre you sure you want to do this?') === true)
{
uroSegWatchObjects = [];
uroOWLUpdateHTML();
}
}
function uroAddUpdateSegWatchList()
{
var selectedCount = W.selectionManager.selectedItems.length;
if(selectedCount === 0)
{
return;
}
for(var loop=0;loop < selectedCount; loop++)
{
var segObj = W.selectionManager.selectedItems[loop].model.attributes;
var fid = segObj.id;
var idx = uroIsSegOnWatchList(fid);
if(idx != -1)
{
uroSegWatchObjects[idx].watch = new uroSegWatchObjCheckProps(segObj.geometry.bounds.left, segObj.geometry.bounds.right, segObj.geometry.bounds.bottom, segObj.geometry.bounds.top, segObj.fromNodeID, segObj.toNodeID, segObj.fwdDirection, segObj.revDirection, segObj.length, segObj.level, segObj.rank, segObj.roadType, segObj.updatedOn);
uroAddLog('updated watchlist details for segment '+fid);
}
else
{
uroSegWatchObjects.push(new uroSegWatchObj(true, fid, segObj.geometry.bounds.left, segObj.geometry.bounds.right, segObj.geometry.bounds.bottom, segObj.geometry.bounds.top, segObj.fromNodeID, segObj.toNodeID, segObj.fwdDirection, segObj.revDirection, segObj.length, segObj.level, segObj.rank, segObj.roadType, segObj.updatedOn, 0, W.location.code));
uroAddCurrentSegWatchData(uroSegWatchObjects.length-1, segObj.geometry.bounds.left, segObj.geometry.bounds.right, segObj.geometry.bounds.bottom, segObj.geometry.bounds.top, segObj.fromNodeID, segObj.toNodeID, segObj.fwdDirection, segObj.revDirection, segObj.length, segObj.level, segObj.rank, segObj.roadType, segObj.updatedOn, W.location.code);
uroAddLog('added segment '+fid+' to watchlist');
}
}
//uroOWLUpdateHTML();
}
function uroRemoveSegFromWatchList()
{
var selectedCount = W.selectionManager.selectedItems.length;
if(selectedCount === 0)
{
return;
}
for(var loop=0;loop < selectedCount; loop++)
{
var fid = W.selectionManager.selectedItems[loop].model.attributes.id;
var idx = uroIsSegOnWatchList(fid);
if(idx != -1)
{
uroSegWatchObjects.splice(idx,1);
uroAddLog('removed segment '+fid+' from watchlist');
}
}
//uroOWLUpdateHTML();
}
function uroRetrieveSegments(lat, lon)
{
var pos = new OpenLayers.LonLat();
var changed = false;
pos.lon = lon;
pos.lat = lat;
pos.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326"));
var URL = 'https://' + document.location.host;
URL += Waze.Config.api_base;
URL += '/Features?roadTypes=1%2C2%2C3%2C4%2C5%2C6%2C7%2C8%2C9%2C10%2C11%2C12%2C13%2C14%2C15%2C16%2C17%2C18%2C19%2C20%2C21';
URL += '&bbox=';
var latl = pos.lat - 0.25;
var latu = pos.lat + 0.25;
var lonl = pos.lon - 0.25;
var lonr = pos.lon + 0.25;
URL += lonl+','+latl+','+lonr+','+latu;
URL += '&language=en';
uroAddLog('retrieving segment data around '+pos.lon+','+pos.lat);
var req = new XMLHttpRequest();
req.open('GET',URL,false);
try
{
req.send();
uroAddLog('response '+req.status+' received');
if (req.status === 200)
{
var data = JSON.parse(req.responseText);
for(var idx = 0; idx < data.segments.objects.length; idx++)
{
var obj = data.segments.objects[idx];
var listIdx = uroIsSegOnWatchList(obj.id);
if(listIdx != -1)
{
//pos.lon = obj.geometry.coordinates[0];
//pos.lat = obj.geometry.coordinates[1];
//pos.transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913"));
//camPos.lon = uroTruncate(camPos.lon);
//camPos.lat = uroTruncate(camPos.lat);
//camChanged |= uroAddCurrentCamWatchData(listIdx, camPos.lat, camPos.lon, camObj.type, camObj.azymuth, camObj.speed, camObj.validated, W.location.code);
}
else if(obj.validated === false)
{
}
}
}
else
{
uroAddLog('request failed (status != 200)');
}
}
catch(err)
{
uroAddLog('segment load request failed (exception '+err+' caught)');
}
return changed;
}
function uroGetCurrentSegWatchListObjects()
{
var segChanged = false;
var segsChanged = [];
var segsDeleted = [];
var idx;
var segObj;
for(idx=0;idx<uroSegWatchObjects.length;idx++)
{
segObj = uroSegWatchObjects[idx];
if((segObj.loaded === false) && ((segObj.server == W.location.code) || (segObj.server == '??')))
{
var segLat = (segObj.watch.top + segObj.watch.bottom) / 2;
var segLon = (segObj.watch.right + segObj.watch.left) / 2;
if(typeof W.model.segments.objects[segObj.fid] == 'object')
{
if(W.model.segments.objects[segObj.fid].state != "Delete")
{
var wazeObj = W.model.segments.objects[segObj.fid];
segChanged |= uroAddCurrentSegWatchData(idx, wazeObj.geometry.bounds.left, wazeObj.geometry.bounds.right, wazeObj.geometry.bounds.bottom, wazeObj.geometry.bounds.top, wazeObj.fromNodeID, wazeObj.toNodeID, wazeObj.fwdDirection, wazeObj.revDirection, wazeObj.length, wazeObj.level, wazeObj.rank, wazeObj.roadType, wazeObj.updatedOn, W.location.code);
}
else
{
segChanged |= uroRetrieveSegments(segLat, segLon);
}
}
else
{
segChanged |= uroRetrieveSegments(segLat, segLon);
}
}
}
if(segChanged)
{
for(idx=0;idx<uroSegWatchObjects.length;idx++)
{
if(uroSegDataChanged(idx))
{
segsChanged.push(uroSegWatchObjects[idx]);
}
}
}
for(idx=0;idx<uroSegWatchObjects.length;idx++)
{
segObj = uroSegWatchObjects[idx];
if((segObj.loaded === false) && (segObj.server == W.location.code))
{
segsDeleted.push(segObj);
}
}
if((segsChanged.length > 0) || (segsDeleted.length > 0))
{
var alertStr = 'Segment WatchList Alert!!!\r\n';
for(idx=0;idx<segsChanged.length;idx++)
{
alertStr += 'Segment ID '+segsChanged[idx].fid+' in group "'+uroFindCWLGroupByIdx(segsChanged[idx].groupID)+'" has been changed\r\n';
}
for(idx=0;idx<segsDeleted.length;idx++)
{
alertStr += 'Segment ID '+segsDeleted[idx].fid+' in group "'+uroFindCWLGroupByIdx(segsDeleted[idx].groupID)+'" has been deleted\r\n';
}
alert(alertStr);
}
}
// Places Functions
function uroPlaceWatchObjCheckProps(left, right, bottom, top, name, imageCount, residential, updatedOn)
{
if(left !== null) left = uroTruncate(uroTypeCast(left));
if(right !== null) right = uroTruncate(uroTypeCast(right));
if(bottom !== null) bottom = uroTruncate(uroTypeCast(bottom));
if(top !== null) top = uroTruncate(uroTypeCast(top));
if(imageCount !== null) imageCount = uroTypeCast(imageCount);
if(typeof residential == "string") residential = (residential == "true");
if(updatedOn !== null) updatedOn = uroTypeCast(updatedOn);
this.left = left;
this.right = right;
this.bottom = bottom;
this.top = top;
this.name = name;
this.imageCount = imageCount;
this.residential = residential;
this.updatedOn = updatedOn;
}
function uroPlaceWatchObj(persistent, fid, left, right, bottom, top, imageCount, name, residential, updatedOn, groupID, server)
{
groupID = uroTypeCast(groupID);
if(typeof persistent == "string") persistent = (persistent == "true");
this.fid = fid;
this.persistent = persistent;
this.loaded = false;
this.server = server;
this.groupID = groupID;
this.watch = new uroPlaceWatchObjCheckProps(left, right, bottom, top, name, imageCount, residential, updatedOn);
this.current = new uroPlaceWatchObjCheckProps(null, null, null, null, null, null, null, null);
}
function uroPlaceDataChanged(idx)
{
var placeObj = uroPlaceWatchObjects[idx];
if(placeObj.loaded === false) return false;
if(placeObj.current.left != placeObj.watch.left) return true;
if(placeObj.current.right != placeObj.watch.right) return true;
if(placeObj.current.bottom != placeObj.watch.bottom) return true;
if(placeObj.current.top != placeObj.watch.top) return true;
if(placeObj.current.name != placeObj.watch.name) return true;
if(placeObj.current.imageCount != placeObj.watch.imageCount) return true;
if(placeObj.current.residential != placeObj.watch.residential) return true;
if(placeObj.current.updatedOn != placeObj.watch.updatedOn) return true;
return false;
}
function uroIsPlaceOnWatchList(fid)
{
for(var loop=0;loop<uroPlaceWatchObjects.length;loop++)
{
if(uroPlaceWatchObjects[loop].fid == fid) return loop;
}
return -1;
}
function uroClearPlaceWatchList()
{
if(confirm('Removing all places from the OWL cannot be undone\nAre you sure you want to do this?') === true)
{
uroPlaceWatchObjects = [];
uroOWLUpdateHTML();
}
}
*/
function uroHighlightCWLEntry()
{
this.style.backgroundColor = '#FFFFAA';
return false;
}
function uroUnhighlightCWLEntry()
{
var camidx = this.id.substr(8);
var changed = uroCamDataChanged(camidx);
var deleted = (uroCamWatchObjects[camidx].loaded === false);
if(uroCamWatchObjects[camidx].server != W.location.code)
{
if(uroCamWatchObjects[camidx].server == '??') this.style.backgroundColor = '#A0A0A0';
else this.style.backgroundColor = '#AAFFAA';
}
else if(changed) this.style.backgroundColor = '#AAAAFF';
else if(deleted) this.style.backgroundColor = '#FFAAAA';
else this.style.backgroundColor = '#FFFFFF';
return false;
}
function uroCWLIconHighlight()
{
this.style.color="#0000ff";
return false;
}
function uroCWLIconLowlight()
{
this.style.color="#ccccff";
return false;
}
function uroPopulateCWLGroupSelect()
{
var selector = document.getElementById('_uroCWLGroupSelect');
while(selector.options.length > 0)
{
selector.options.remove(0);
}
for(var loop=0;loop<uroCWLGroups.length;loop++)
{
var groupObj = uroCWLGroups[loop];
if(groupObj.groupID != -1)
{
selector.options.add(new Option(groupObj.groupName,groupObj.groupID));
}
}
}
function uroGetNextCWLGroupID()
{
var nextID = 1;
for(var loop=0;loop<uroCWLGroups.length;loop++)
{
if(uroCWLGroups[loop].groupID >= nextID)
{
nextID = uroCWLGroups[loop].groupID + 1;
}
}
return nextID;
}
function uroFindCWLGroupByName(groupName)
{
var groupID = -1;
for(var loop=0;loop<uroCWLGroups.length;loop++)
{
if((uroCWLGroups[loop].groupName == groupName) && (uroCWLGroups[loop].groupID != -1))
{
groupID = uroCWLGroups[loop].groupID;
break;
}
}
return groupID;
}
function uroAddCWLGroup()
{
var groupID = uroGetNextCWLGroupID();
var groupName = uroGetElmValue('_uroCWLGroupEntry');
if(uroFindCWLGroupByName(groupName) == -1)
{
uroCWLGroups.push(new uroOWLGroupObj(groupID,groupName,false));
uroPopulateCWLGroupSelect();
}
}
function uroRemoveCWLGroup()
{
var loop;
var selector = document.getElementById('_uroCWLGroupSelect');
var groupID = parseInt(selector.selectedOptions[0].value);
if(groupID === 0) return false; // prevent deletion of the default group
for(loop=0;loop<uroCamWatchObjects.length;loop++)
{
var cwObj = uroCamWatchObjects[loop];
if(cwObj.groupID == groupID)
{
cwObj.groupID = 0;
}
}
for(loop=0;loop<uroCWLGroups.length;loop++)
{
var groupObj = uroCWLGroups[loop];
if(groupObj.groupID == groupID)
{
groupObj.groupID = -1;
}
}
uroOWLUpdateHTML();
}
function uroAssignCameraToGroup()
{
var camidx = this.id.substr(13);
var selector = document.getElementById('_uroCWLGroupSelect');
uroCamWatchObjects[camidx].groupID = parseInt(selector.selectedOptions[0].value);
uroOWLUpdateHTML();
return false;
}
function uroAddBtnEvl(btnID, evlType, evlFunction)
{
var btnObj = document.getElementById(btnID);
if(btnObj !== null)
{
btnObj.addEventListener(evlType, evlFunction, true);
}
}
function uroCWLGroupCollapseExpand()
{
var groupidx = this.id.substr(18);
if(uroCWLGroups[groupidx].groupCollapsed === true) uroCWLGroups[groupidx].groupCollapsed = false;
else uroCWLGroups[groupidx].groupCollapsed = true;
uroOWLUpdateHTML();
return false;
}
var uroSelectedOWLGroup = null;
function uroOWLUpdateHTML(doFullUpdate)
{
var camTypes = new Array("","","Speed", "Dummy", "Red Light");
var iHTML = '';
if(document.getElementById('_uroCWLGroupSelect') !== null)
{
uroSelectedOWLGroup = document.getElementById('_uroCWLGroupSelect').selectedIndex;
}
iHTML = '<br><b>Camera Watchlist:</b><br><br>';
iHTML += '<div id="_uroCWLCamList" style="height:65%;overflow:auto;">';
if(uroCWLGroups.length > 0)
{
var camidx;
for(var groupidx=0;groupidx<uroCWLGroups.length;groupidx++)
{
var groupObj = uroCWLGroups[groupidx];
iHTML += '<div id="_uroCWLGroup-'+groupidx+'">';
if(groupObj.groupCollapsed === true)
{
iHTML += '<i class="fa fa-plus-square-o" style="cursor:pointer;font-size:14px;" id="_uroCWLGroupState-'+groupidx+'"></i>';
}
else
{
iHTML += '<i class="fa fa-minus-square-o" style="cursor:pointer;font-size:14px;" id="_uroCWLGroupState-'+groupidx+'"></i>';
}
iHTML += '<b>'+groupObj.groupName+'</b><br>';
groupObj.groupCount = 0;
if(uroCamWatchObjects.length > 0)
{
for(camidx=0;camidx<uroCamWatchObjects.length;camidx++)
{
var camObj = uroCamWatchObjects[camidx];
if(camObj.groupID == groupObj.groupID)
{
groupObj.groupCount++;
var changed = uroCamDataChanged(camidx);
var deleted = (camObj.loaded === false);
iHTML += '<div id="_uroCWL-'+camidx+'" style="padding:3px;border-width:2px;border-style:solid;border-color:#FFFFFF;background-color:';
if(camObj.server != W.location.code)
{
if(camObj.server == '??') iHTML += '#A0A0A0;';
else iHTML += '#AAFFAA;';
}
else if(changed) iHTML += '#AAAAFF;';
else if(deleted) iHTML += '#FFAAAA;';
else iHTML += '#FFFFFF;';
if(groupObj.groupCollapsed === true) iHTML += 'display:none;">';
else iHTML += 'display:block;">';
iHTML += 'ID: '+camObj.fid;
iHTML += ' ('+camObj.server+')';
iHTML += ' Type: '+camTypes[camObj.watch.type];
if(camObj.server != W.location.code)
{
if(camObj.server == '??')
{
iHTML += '<br><i>Unknown server</i>';
}
else
{
iHTML += '<br><i>Not on this server</i>';
}
}
else if(deleted)
{
iHTML += '<br>DELETED';
}
else if(changed)
{
if(camObj.current.type != camObj.watch.type)
{
iHTML += '<br> Type changed';
iHTML += ' ('+camObj.watch.type+' to '+camObj.current.type+')';
}
if(camObj.current.azymuth != camObj.watch.azymuth)
{
iHTML += '<br> Azimuth changed';
iHTML += ' ('+camObj.watch.azymuth+' to '+camObj.current.azymuth+')';
}
if(camObj.current.speed != camObj.watch.speed)
{
iHTML += '<br> Speed changed';
iHTML += ' ('+camObj.watch.speed+' to '+camObj.current.speed+')';
}
if(camObj.current.validated != camObj.watch.validated)
{
iHTML += '<br> Approval state changed';
iHTML += ' ('+camObj.watch.validated+' to '+camObj.current.validated+')';
}
if(camObj.current.lat != camObj.watch.lat)
{
iHTML += '<br> Latitude changed';
iHTML += ' ('+camObj.watch.lat+' to '+camObj.current.lat+')';
}
if(camObj.current.lon != camObj.watch.lon)
{
iHTML += '<br> Longitude changed';
iHTML += ' ('+camObj.watch.lon+' to '+camObj.current.lon+')';
}
}
if(camObj.server == W.location.code)
{
if(deleted === false)
{
iHTML += ' <i class="fa fa-group" style="cursor:pointer;font-size:14px;color:#ccccff;" id="_uroCWLIcon1-'+camidx+'"></i>';
}
iHTML += ' <i class="fa fa-arrow-circle-right" style="cursor:pointer;font-size:14px;color:#ccccff;" id="_uroCWLIcon2-'+camidx+'"></i>';
}
iHTML += '</div>';
}
}
}
iHTML += '</div>';
}
}
iHTML += '</div><div id="_uroCWLControls">';
iHTML += '<hr>Group control:<br>';
iHTML += '<select id="_uroCWLGroupSelect" style="width:40%;height:22px;"></select> <input type="button" id="_btnCWLGroupDel" value="Delete group"><br>';
iHTML += '<input type="text" id="_uroCWLGroupEntry" style="width:40%;height:22px;"> <input type="button" id="_btnCWLGroupAdd" value="Add group">';
iHTML += '<br><input type="button" id="_btnRescanCamWatchList" value="Refresh Camera Data"><br><br>';
iHTML += '<b>Remove cameras from OWL:</b><br>';
iHTML += '<input type="button" id="_btnRemoveDeletedCameras" value="Deleted"> ';
iHTML += '<input type="button" id="_btnRemoveUnknownServerCameras" value="Unknown Server"> ';
iHTML += '<input type="button" id="_btnClearCamWatchList" value="ALL Cameras">';
iHTML += '</div>';
uroOWL.innerHTML = iHTML;
uroFinaliseOWLHTMLUpdate();
}
function uroFinaliseOWLHTMLUpdate()
{
if(uroCamWatchObjects.length > 0)
{
if(document.getElementById("_uroCWL-0") == null)
{
setTimeout(uroFinaliseOWLHTMLUpdate,100);
return;
}
for(var camidx=0;camidx<uroCamWatchObjects.length;camidx++)
{
document.getElementById("_uroCWL-"+camidx).onmouseover = uroHighlightCWLEntry;
document.getElementById("_uroCWL-"+camidx).onmouseleave = uroUnhighlightCWLEntry;
if(uroCamWatchObjects[camidx].server == W.location.code)
{
var icon1 = document.getElementById("_uroCWLIcon1-"+camidx);
var icon2 = document.getElementById("_uroCWLIcon2-"+camidx);
if(icon1 !== null)
{
icon1.onmouseover = uroCWLIconHighlight;
icon1.onmouseleave = uroCWLIconLowlight;
icon1.onclick = uroAssignCameraToGroup;
}
if(icon2 !== null)
{
icon2.onmouseover = uroCWLIconHighlight;
icon2.onmouseleave = uroCWLIconLowlight;
icon2.onclick = uroGotoCam;
}
}
}
}
if(document.getElementById('_btnClearCamWatchList') == null)
{
setTimeout(uroFinaliseOWLHTMLUpdate,100);
return;
}
uroAddBtnEvl('_btnClearCamWatchList', 'click', uroClearCamWatchList);
uroAddBtnEvl('_btnRemoveDeletedCameras', 'click', uroClearDeletedCameras);
uroAddBtnEvl('_btnRemoveUnknownServerCameras', 'click', uroClearUnknownServerCameras);
uroAddBtnEvl('_btnRescanCamWatchList', 'click', uroRescanCamWatchList);
uroAddBtnEvl('_btnCWLGroupDel', 'click', uroRemoveCWLGroup);
uroAddBtnEvl('_btnCWLGroupAdd', 'click', uroAddCWLGroup);
if(document.getElementById('_uroCWLGroupSelect') !== null)
{
uroAddLog('populating CWL group list');
uroPopulateCWLGroupSelect();
var selector = document.getElementById('_uroCWLGroupSelect');
if(uroSelectedOWLGroup >= selector.length)
{
uroSelectedOWLGroup = 0;
}
selector.selectedIndex = uroSelectedOWLGroup;
}
if(uroCWLGroups.length > 0)
{
for(var groupidx=0;groupidx<uroCWLGroups.length;groupidx++)
{
if(uroCWLGroups[groupidx].groupCount === 0)
{
uroSetStyleDisplay('_uroCWLGroup-'+groupidx,'none');
}
else
{
uroSetOnClick('_uroCWLGroupState-'+groupidx,uroCWLGroupCollapseExpand);
}
}
}
}
// --------------------------------------------------------------------------------------------------------------------
// END OF WATCHLIST STUFF
// --------------------------------------------------------------------------------------------------------------------
function uroIsOnIgnoreList(fid)
{
if(sessionStorage.UROverview_FID_IgnoreList.indexOf('fid:'+fid) == -1) return false;
else return true;
}
function uroEnableIgnoreListControls()
{
var btnState = "visible";
if(sessionStorage.UROverview_FID_IgnoreList === '')
{
btnState = "hidden";
}
document.getElementById('_btnUndoLastHide').style.visibility = btnState;
document.getElementById('_btnClearSessionHides').style.visibility = btnState;
uroFilterItems();
}
function uroAddToIgnoreList()
{
if(!uroIsOnIgnoreList(uroShownFID))
{
sessionStorage.UROverview_FID_IgnoreList += 'fid:'+uroShownFID;
uroAddLog('added fid '+uroShownFID+' to ignore list');
uroAddLog(sessionStorage.UROverview_FID_IgnoreList);
uroDiv.style.visibility = 'hidden';
uroEnableIgnoreListControls();
W.map.events.register("mousemove", null, uroFilterItemsOnMove);
}
return false;
}
function uroRemoveLastAddedIgnore()
{
var ignorelist = sessionStorage.UROverview_FID_IgnoreList;
var fidpos = ignorelist.lastIndexOf('fid:');
if(fidpos != -1)
{
ignorelist = ignorelist.slice(0,fidpos);
sessionStorage.UROverview_FID_IgnoreList = ignorelist;
uroAddLog('removed last fid from ignore list');
uroAddLog(sessionStorage.UROverview_FID_IgnoreList);
uroEnableIgnoreListControls();
}
}
function uroRemoveAllIgnores()
{
sessionStorage.UROverview_FID_IgnoreList = '';
uroEnableIgnoreListControls();
}
function uroKeywordPresent(desc, keyword)
{
var re;
if(uroGetCBChecked('_cbCaseInsensitive') === true) re = RegExp(keyword,'i');
else re = RegExp(keyword);
if(desc.search(re) != -1) return true;
else return false;
}
function uroClickify(desc)
{
var linkStartPos = desc.indexOf('http://');
if(linkStartPos == -1) linkStartPos = desc.indexOf('https://');
if(linkStartPos != -1)
{
var descPreLink = desc.slice(0,linkStartPos);
var descURL = desc.slice(linkStartPos);
var linkEndPos = descURL.indexOf(' ');
var descPostLink = '';
if(linkEndPos != -1)
{
descPostLink = descURL.slice(linkEndPos);
descURL = descURL.slice(0,linkEndPos);
}
var linkTarget = '';
if(descURL.indexOf('cryosphere') != -1) linkTarget = '_cryosphere';
else if(descURL.indexOf('waze.com') != -1) linkTarget = '_wazeUR';
desc = descPreLink + '<a target="'+linkTarget+'" href="'+descURL+'">here</a>' + descPostLink;
}
return desc;
}
function uroGetUpdateRequestSessions()
{
var idList = [];
while((idList.length < 50) && (uroPendingURSessionIDs.length))
{
var id = uroPendingURSessionIDs.shift();
idList.push(id);
}
if(idList.length > 0)
{
uroAddLog('grabbing '+idList.length+' updateRequestSessions, IDs: '+idList);
W.model.updateRequestSessions.get(idList);
}
if((uroPendingURSessionIDs.length) || (uroRequestedURSessionIDs.length))
{
setTimeout(uroGetUpdateRequestSessions,1000);
}
}
function uroRefreshUpdateRequestSessions()
{
var urcount = 0;
uroPendingURSessionIDs = [];
uroRequestedURSessionIDs = [];
for (var urID in W.model.mapUpdateRequests.objects)
{
if(W.model.mapUpdateRequests.objects.hasOwnProperty(urID))
{
if(W.model.updateRequestSessions.objects[urID] === undefined)
{
uroPendingURSessionIDs.push(urID);
}
urcount++;
}
}
uroGetUpdateRequestSessions();
}
function uroURHasMyComments(fid)
{
if(uroUserID === -1) return false;
var nComments = W.model.updateRequestSessions.objects[fid].comments.length;
if(nComments === 0) return false;
for(var cidx=0; cidx<nComments; cidx++)
{
if(W.model.updateRequestSessions.objects[fid].comments[cidx].userID == uroUserID) return true;
}
return false;
}
function uroACMObj(urID, markerType, customType, hasMyComments, nComments)
{
this.urID = urID;
this.markerType = markerType;
this.customType = customType;
this.hasMyComments = hasMyComments;
this.nComments = nComments;
}
function uroAddCustomMarkers(urID, markerType, customType, hasMyComments, nComments)
{
var useCustomMarker = false;
if(uroGetCBChecked('_cbMasterEnable') === true)
{
if(customType === 0) useCustomMarker = (uroGetCBChecked('_cbCustomRoadworksMarkers'));
else if(customType === 1) useCustomMarker = (uroGetCBChecked('_cbCustomConstructionMarkers'));
else if(customType === 2) useCustomMarker = (uroGetCBChecked('_cbCustomClosuresMarkers'));
else if(customType === 3) useCustomMarker = (uroGetCBChecked('_cbCustomEventsMarkers'));
else if(customType === 4) useCustomMarker = (uroGetCBChecked('_cbCustomNotesMarkers'));
else if(customType === 5) useCustomMarker = (uroGetCBChecked('_cbCustomWSLMMarkers'));
else if(customType === 6) useCustomMarker = (uroGetCBChecked('_cbCustomBOGMarkers'));
else if(customType === 7) useCustomMarker = (uroGetCBChecked('_cbCustomDifficultMarkers'));
else if(customType === 98) useCustomMarker = (uroGetCBChecked('_cbCustomNativeSLMarkers'));
else if(customType === 99) useCustomMarker = (uroGetCBChecked('_cbCustomKeywordMarkers'));
else if(customType === 100) useCustomMarker = (uroGetCBChecked('_cbCustomElginMarkers'));
else if(customType === 101) useCustomMarker = (uroGetCBChecked('_cbCustomTrafficCastMarkers'));
else if(customType === 102) useCustomMarker = (uroGetCBChecked('_cbCustomTrafficMasterMarkers'));
else if(customType === 103) useCustomMarker = (uroGetCBChecked('_cbCustomCaltransMarkers'));
else if(customType === 104) useCustomMarker = (uroGetCBChecked('_cbCustomTFLMarkers'));
}
if(!useCustomMarker) customType = -1;
uroCustomMarkerList.push(new uroACMObj(urID, markerType, customType, hasMyComments, nComments));
}
function uroRenderCustomMarkers(markerType)
{
var urID;
var elmID;
var newSpan;
var divElem;
var objIdx;
var customType;
var cmlObj;
var defaultMarkerURL = "url('"+document.location.origin + '/assets-editor/sprites/vectors/' + uroNativeMarkerImage+"')";
var touchedByURO = false;
if(markerType == 'ur')
{
var useDefaultConvoMarker = false;
var addCommentCount = false;
if(uroGetCBChecked('_cbMasterEnable') === true)
{
if((uroGetCBChecked('_cbNativeConvoMarkers')) && (uroBetaEditor === false)) useDefaultConvoMarker = true;
if((uroGetCBChecked('_cbNativeBetaConvoMarkers')) && (uroBetaEditor === true)) useDefaultConvoMarker = true;
if(uroGetCBChecked('_cbCommentCount')) addCommentCount = true;
}
else
{
useDefaultConvoMarker = true;
}
var uRCM_masterEnable = uroGetCBChecked('_cbMasterEnable');
divElem = document.getElementById(W.map.updateRequestLayer.id);
if(divElem.childNodes.length > 0)
{
for(objIdx = 0; objIdx < uroCustomMarkerList.length; objIdx++)
{
customType = -1;
cmlObj = uroCustomMarkerList[objIdx];
if(cmlObj.markerType == 'ur')
{
if(uRCM_masterEnable === true)
{
customType = cmlObj.customType;
}
if(customType < 100)
{
urID = cmlObj.urID;
var nComments = cmlObj.nComments;
var iconObj = W.map.updateRequestLayer.markers[urID].icon;
newSpan = '';
if(nComments !== 0)
{
var classList = iconObj.imageDiv.classList;
elmID = "commentCount_"+urID;
if(addCommentCount)
{
// add a new comment count bubble if the UR doesn't already have one
if(document.getElementById(elmID) === null)
{
newSpan += '<span id="'+elmID+'" style="position:absolute;top:-9px;left:-11px;pointer-events:none;z-index:1">';
// define the comment-count holding span within the span used to hold the empty bubble image, and before the image is
// added to the HTML, to avoid z-indexing issues when adjacent comment count bubbles are overlapped...
newSpan += '<span id="'+elmID+"_inner"+'" style="position:absolute;top:4px;left:11px;font-size:11px;;pointer-events:none"></span>';
newSpan += '<img src="'+uroMarkers[0]+'">';
newSpan += '</span>';
}
}
else
{
// remove comment count bubble from this UR marker if one has previously been
// added and the user has now disabled the option...
if(document.getElementById(elmID) !== null)
{
document.getElementById(elmID).remove();
}
if(document.getElementById(elmID+"_inner") !== null)
{
document.getElementById(elmID+"_inner").remove();
}
}
elmID = "convoMarker_"+urID;
if(useDefaultConvoMarker === false)
{
if(document.getElementById(elmID) === null)
{
var hasMyComments = cmlObj.hasMyComments;
// z-index needs to be set to 1 here so that when a new comment is added to a UR and WME re-renders the native
// conversation marker, the custom marker remains on top...
newSpan += '<span id="'+elmID+'" style="position:absolute;top:-9px;left:18px;pointer-events:none;z-index:1">';
if(hasMyComments) newSpan += '<img src="'+uroMarkers[2]+'">';
else newSpan += '<img src="'+uroMarkers[1]+'">';
newSpan += '</span>';
classList.remove("has-comments");
}
}
else
{
// remove custom conversation marker from this UR if one has previously been
// added and the user has now disabled this option
if(document.getElementById(elmID) !== null)
{
document.getElementById(elmID).remove();
}
if(nComments > 0)
{
// only replace the native marker class if the UR has comments - if we're just clearing the custom
// marker following a master enable switchoff, we don't then want to add native markers to URs which
// didn't have them in the first place...
classList.add("has-comments");
}
}
}
// change main marker if required
touchedByURO = W.map.updateRequestLayer.markers[urID].touchedByURO;
if(customType != -1)
{
if((touchedByURO === undefined) || (touchedByURO === false))
{
customType = uroGetCustomMarkerIdx(customType);
W.map.updateRequestLayer.markers[urID].icon.imageDiv.style.backgroundImage = uroAltMarkers[customType];
W.map.updateRequestLayer.markers[urID].touchedByURO = true;
}
}
else
{
if((touchedByURO === undefined) || (touchedByURO === true))
{
W.map.updateRequestLayer.markers[urID].icon.imageDiv.style.backgroundImage = defaultMarkerURL;
W.map.updateRequestLayer.markers[urID].touchedByURO = false;
}
}
if(newSpan !== '')
{
iconObj.$div.prepend(newSpan);
if(addCommentCount)
{
var styleLeft;
if(nComments < 10) styleLeft = '11px';
else if(nComments < 100) styleLeft = '8px';
else styleLeft = '5px';
elmID = "commentCount_"+urID;
if(document.getElementById(elmID+"_inner") !== null)
{
document.getElementById(elmID+"_inner").innerHTML = nComments;
document.getElementById(elmID+"_inner").style.left = styleLeft;
}
}
}
}
}
}
}
}
else if(markerType == 'mp')
{
divElem = document.getElementById(W.map.problemLayer.id);
if(divElem.childNodes.length > 0)
{
for(objIdx = 0; objIdx < uroCustomMarkerList.length; objIdx++)
{
cmlObj = uroCustomMarkerList[objIdx];
if(cmlObj.markerType == 'mp')
{
customType = cmlObj.customType;
if((customType >= 100) || (customType == -1))
{
urID = cmlObj.urID;
// change main marker if required
touchedByURO = W.map.problemLayer.markers[urID].touchedByURO;
if(customType != -1)
{
if((touchedByURO === undefined) || (touchedByURO === false))
{
customType = uroGetCustomMarkerIdx(customType);
W.map.problemLayer.markers[urID].icon.imageDiv.style.backgroundImage = uroAltMarkers[customType];
W.map.problemLayer.markers[urID].touchedByURO = true;
}
}
else
{
if((touchedByURO === undefined) || (touchedByURO === true))
{
W.map.problemLayer.markers[urID].icon.imageDiv.style.backgroundImage = defaultMarkerURL;
W.map.problemLayer.markers[urID].touchedByURO = false;
}
}
}
}
}
}
}
}
function uroFilterPlaces()
{
if(uroFilterPreamble() === false) return;
if(uroPlaceSelected === true) return;
if(uroGetCBChecked('_cbDisablePlacesFiltering') === true) return;
var filterCats = [];
for(var i=0; i<W.Config.venues.categories.length; i++)
{
var parentCategory = W.Config.venues.categories[i];
var subCategory;
if(uroGetCBChecked('_cbPlacesFilter-'+parentCategory) === true)
{
filterCats.push(parentCategory);
for(var i1=0; i1<W.Config.venues.subcategories[parentCategory].length; i1++)
{
subCategory = W.Config.venues.subcategories[parentCategory][i1];
filterCats.push(subCategory);
}
}
else
{
for(var i2=0; i2<W.Config.venues.subcategories[parentCategory].length; i2++)
{
subCategory = W.Config.venues.subcategories[parentCategory][i2];
if(uroGetCBChecked('_cbPlacesFilter-'+subCategory) === true)
{
filterCats.push(subCategory);
}
}
}
}
var placeStyle;
var uFP_filterEditedLessThan = uroGetCBChecked('_cbPlaceFilterEditedLessThan');
var uFP_filterEditedMoreThan = uroGetCBChecked('_cbPlaceFilterEditedMoreThan');
var uFP_filterL0 = uroGetCBChecked('_cbHidePlacesL0');
var uFP_filterL1 = uroGetCBChecked('_cbHidePlacesL1');
var uFP_filterL2 = uroGetCBChecked('_cbHidePlacesL2');
var uFP_filterL3 = uroGetCBChecked('_cbHidePlacesL3');
var uFP_filterL4 = uroGetCBChecked('_cbHidePlacesL4');
var uFP_filterL5 = uroGetCBChecked('_cbHidePlacesL5');
var uFP_filterStaff = uroGetCBChecked('_cbHidePlacesStaff');
var uFP_filterAL = uroGetCBChecked('_cbHidePlacesAdLocked');
var uFP_filterOnLockLevel = (uFP_filterL0 || uFP_filterL1 || uFP_filterL2 || uFP_filterL3 || uFP_filterL4 || uFP_filterL5 || uFP_filterStaff);
var uFP_filterNoPhotos = uroGetCBChecked('_cbHideNoPhotoPlaces');
var uFP_filterWithPhotos = uroGetCBChecked('_cbHidePhotoPlaces');
var uFP_filterNoLinks = uroGetCBChecked('_cbHideNoLinkedPlaces');
var uFP_filterWithLinks = uroGetCBChecked('_cbHideLinkedPlaces');
var uFP_filterNoKeyword = uroGetCBChecked('_cbHideKeywordPlaces');
var uFP_filterKeyword = uroGetCBChecked('_cbHideNoKeywordPlaces');
var uFP_filterPrivate = uroGetCBChecked('_cbFilterPrivatePlaces');
var uFP_invertFilters = uroGetCBChecked('_cbInvertPlacesFilter');
var uFP_masterEnable = uroGetCBChecked('_cbMasterEnable');
var uFP_filterAreaPlaces = uroGetCBChecked('_cbHideAreaPlaces');
var uFP_filterPointPlaces = uroGetCBChecked('_cbHidePointPlaces');
var uFP_NameKeyword = document.getElementById('_textKeywordPlace').value.toLowerCase();
var uFP_thresholdMinDays = document.getElementById('_inputFilterPlaceEditMinDays').value;
var uFP_thresholdMaxDays = document.getElementById('_inputFilterPlaceEditMaxDays').value;
for(var v=0; v<W.map.landmarkLayer.features.length; v++)
{
placeStyle = 'visible';
if(uFP_masterEnable === true)
{
var lmObj = W.map.landmarkLayer.features[v];
// when an area place is selected, the drag points for editing the place outline now get added as objects into W.map.landmarkLayer.features,
// however none of these objects have the .model property - we must therefore check each entry in features[] to see if it has .model before
// attempting to filter it...
if(lmObj.model != null)
{
if(lmObj.model.attributes.id < 0)
{
// don't apply filtering to newly-created places - this allows the user to leave their filtering settings unchanged whilst
// adding a new place which, once saved, would then be hidden...
break;
}
if(uFP_filterAreaPlaces)
{
if(lmObj.model.attributes.geometry.id.indexOf('Polygon') !== -1)
{
placeStyle = 'hidden';
}
}
if(uFP_filterPointPlaces)
{
if(lmObj.model.attributes.geometry.id.indexOf('Point') !== -1)
{
placeStyle = 'hidden';
}
}
if(placeStyle == 'visible')
{
if((uFP_filterEditedLessThan) || (uFP_filterEditedMoreThan))
{
var editDate = lmObj.model.attributes.updatedOn;
if(editDate === undefined)
{
// where a place has never been edited since its creation, use the creation date instead...
editDate = lmObj.model.attributes.createdOn;
}
if(editDate != null)
{
var editDaysAgo = uroDateToDays(editDate);
if(uFP_filterEditedLessThan)
{
if(editDaysAgo < uFP_thresholdMinDays)
{
placeStyle = 'hidden';
}
}
if(uFP_filterEditedMoreThan)
{
if(editDaysAgo > uFP_thresholdMaxDays)
{
placeStyle = 'hidden';
}
}
}
}
}
if(placeStyle == 'visible')
{
if(uFP_filterOnLockLevel)
{
var lockLevel = lmObj.model.attributes.lockRank;
if ((uFP_filterL0) && (lockLevel === 0)) placeStyle = 'hidden';
if ((uFP_filterL1) && (lockLevel === 1)) placeStyle = 'hidden';
if ((uFP_filterL2) && (lockLevel === 2)) placeStyle = 'hidden';
if ((uFP_filterL3) && (lockLevel === 3)) placeStyle = 'hidden';
if ((uFP_filterL4) && (lockLevel === 4)) placeStyle = 'hidden';
if ((uFP_filterL5) && (lockLevel === 5)) placeStyle = 'hidden';
if ((uFP_filterStaff) && (lockLevel === 6)) placeStyle = 'hidden';
}
}
if(placeStyle == 'visible')
{
if(uFP_filterAL)
{
if(lmObj.model.attributes.adLocked) placeStyle = 'hidden';
}
}
if(placeStyle == 'visible')
{
if(uFP_filterNoPhotos || uFP_filterWithPhotos)
{
var nPhotos = 0;
for(var loop=0; loop<lmObj.model.attributes.images.length; loop++)
{
if(lmObj.model.attributes.images[loop].attributes.approved) nPhotos++;
}
if((uFP_filterNoPhotos) && (nPhotos === 0)) placeStyle = 'hidden';
if((uFP_filterWithPhotos) && (nPhotos !== 0)) placeStyle = 'hidden';
}
}
if(placeStyle == 'visible')
{
if(uFP_filterNoLinks || uFP_filterWithLinks)
{
var nLinks = lmObj.model.attributes.externalProviderIDs.length;
if((uFP_filterNoLinks) && (nLinks === 0)) placeStyle = 'hidden';
if((uFP_filterWithLinks) && (nLinks !== 0)) placeStyle = 'hidden';
}
}
if(placeStyle == 'visible')
{
if((uFP_filterPrivate === true) && (lmObj.model.attributes.residential === true))
{
placeStyle = 'hidden';
}
else
{
for(var cat=0; cat<filterCats.length; cat++)
{
if(lmObj.model.attributes.categories.contains(filterCats[cat]))
{
placeStyle = 'hidden';
break;
}
}
}
}
if(placeStyle == 'visible')
{
if(uFP_filterNoKeyword || uFP_filterKeyword)
{
var venueName = lmObj.model.attributes.name.toLowerCase();
var noKeywordMatch = true;
if(uFP_NameKeyword === '')
{
noKeywordMatch = (venueName !== '');
}
else
{
noKeywordMatch = (venueName.indexOf(uFP_NameKeyword) === -1);
}
if(!noKeywordMatch && uFP_filterNoKeyword) placeStyle = 'hidden';
if(noKeywordMatch && uFP_filterKeyword) placeStyle = 'hidden';
}
}
}
if(uFP_invertFilters === true)
{
if(placeStyle == 'hidden') placeStyle = 'visible';
else placeStyle = 'hidden';
}
}
var geoID = W.map.landmarkLayer.features[v].geometry.id;
if(document.getElementById(geoID) !== null)
{
document.getElementById(geoID).style.visibility = placeStyle;
}
}
var uFP_filterUneditable = uroGetCBChecked('_cbFilterUneditablePlaceUpdates');
var uFP_filterLockRanked = uroGetCBChecked('_cbFilterLockRankedPlaceUpdates');
var uFP_filterFlagged = uroGetCBChecked("_cbFilterFlaggedPUR");
var uFP_filterNewPlace = uroGetCBChecked("_cbFilterNewPlacePUR");
var uFP_filterUpdatedDetails = uroGetCBChecked("_cbFilterUpdatedDetailsPUR");
var uFP_filterNewPhoto = uroGetCBChecked("_cbFilterNewPhotoPUR");
var uFP_filterMinPURAge = uroGetCBChecked('_cbEnablePURMinAgeFilter');
var uFP_filterMaxPURAge = uroGetCBChecked('_cbEnablePURMaxAgeFilter');
var uFP_invertPURFilters = uroGetCBChecked('_cbInvertPURFilters');
var uFP_filterHighSeverity = uroGetCBChecked('_cbPURFilterHighSeverity');
var uFP_filterMedSeverity = uroGetCBChecked('_cbPURFilterMediumSeverity');
var uFP_filterLowSeverity = uroGetCBChecked('_cbPURFilterLowSeverity');
var uFP_leavePURGeos = uroGetCBChecked('_cbLeavePURGeos');
var uFP_thresholdMinPURDays = uroGetElmValue('_inputPURFilterMinDays');
var uFP_thresholdMaxPURDays = uroGetElmValue('_inputPURFilterMaxDays');
var uFP_isLoggedIn = W.loginManager.isLoggedIn();
var uFP_userRank = W.loginManager.user.rank;
var purAge = null;
for(var pu in W.map.placeUpdatesLayer.markers)
{
if(W.map.placeUpdatesLayer.markers.hasOwnProperty(pu))
{
var puObj = W.map.placeUpdatesLayer.markers[pu];
if(W.map.placeUpdatesLayer.getVisibility() === true)
{
placeStyle = 'visible';
if(uFP_masterEnable === true)
{
if(uFP_masterEnable === true)
{
if(uFP_filterUneditable === true)
{
if(puObj.model.attributes.permissions === 0)
{
placeStyle = 'hidden';
}
if((placeStyle == 'visible') && (uFP_isLoggedIn))
{
if(uFP_userRank < puObj.model.attributes.lockRank)
{
placeStyle = 'hidden';
}
}
if((placeStyle == 'visible') && (puObj.model.attributes.adLocked))
{
placeStyle = 'hidden';
}
}
if((placeStyle == 'visible') && (uFP_filterLockRanked === true))
{
if(puObj.model.attributes.lockRank !== 0)
{
placeStyle = 'hidden';
}
}
if((placeStyle == 'visible') && (uFP_filterFlagged === true))
{
if(puObj.icon.imageDiv.className.indexOf('flag') != -1)
{
placeStyle = 'hidden';
}
}
if((placeStyle == 'visible') && (uFP_filterNewPlace === true))
{
if(puObj.icon.imageDiv.className.indexOf('add_venue') != -1)
{
placeStyle = 'hidden';
}
}
if((placeStyle == 'visible') && (uFP_filterUpdatedDetails === true))
{
if((puObj.icon.imageDiv.className.indexOf('update_venue') != -1) || (puObj.icon.imageDiv.className.indexOf('multiple') != -1))
{
placeStyle = 'hidden';
}
}
if((placeStyle == 'visible') && (uFP_filterNewPhoto === true))
{
if(puObj.icon.imageDiv.className.indexOf('add_image') != -1)
{
placeStyle = 'hidden';
}
}
if(uFP_invertPURFilters === true)
{
if(placeStyle == 'hidden') placeStyle = 'visible';
else placeStyle = 'hidden';
}
if(uFP_filterMinPURAge || uFP_filterMaxPURAge)
{
purAge = uroGetPURAge(puObj.model);
if(uFP_filterMinPURAge === true)
{
if(purAge < uFP_thresholdMinPURDays) placeStyle = 'hidden';
}
if(uFP_filterMaxPURAge === true)
{
if(purAge > uFP_thresholdMaxPURDays) placeStyle = 'hidden';
}
}
if(placeStyle == 'visible')
{
var purSeverity = puObj._getSeverity();
if((uFP_filterHighSeverity) && (purSeverity == "high")) placeStyle = 'hidden';
if((placeStyle == 'visible') && (uFP_filterMedSeverity) && (purSeverity == "medium")) placeStyle = 'hidden';
if((placeStyle == 'visible') && (uFP_filterLowSeverity) && (purSeverity == "low")) placeStyle = 'hidden';
}
}
}
puObj.icon.imageDiv.style.visibility = placeStyle;
if(uFP_leavePURGeos === false)
{
if(puObj.model != null)
{
if(puObj.model.geometry != null)
{
var puGeo = document.getElementById(puObj.model.geometry.id);
if(puGeo !== null)
{
puGeo.style.visibility = placeStyle;
}
}
}
}
}
}
}
}
function uroFilterCameras()
{
if(uroFilterPreamble() === false) return;
var camLayer = document.getElementById(uroRootContainer+'_svgRoot');
if(camLayer === null)
{
if(uroNullCamLayer === false)
{
uroAddLog('caught null camLayer');
uroNullCamLayer = true;
}
return;
}
uroNullCamLayer = false;
if(uroMouseIsDown === false) W.map.camerasLayer.redraw();
if(uroGetCBChecked('_cbMasterEnable') === true)
{
uroUpdateCamEditorList();
var filterNameID = null;
var tbUserName = uroGetElmValue('_textCameraEditor');
var selector = document.getElementById('_selectCameraUserID');
if(selector.selectedIndex > 0)
{
var selUserName = document.getElementById('_selectCameraUserID').selectedOptions[0].innerHTML;
if(selUserName == tbUserName)
{
filterNameID = document.getElementById('_selectCameraUserID').selectedOptions[0].value;
}
}
if(filterNameID === null)
{
var userObj = W.model.users.getByAttributes({userName:tbUserName})[0];
if(userObj !== undefined)
{
filterNameID = userObj.id;
}
}
for (var uroCamObj in W.model.cameras.objects)
{
if(W.model.cameras.objects.hasOwnProperty(uroCamObj))
{
var uroCamUpdater = '';
var uroCamUpdaterRank = -1;
var uroCamCreator = '';
var uroCamCreatorRank = -1;
var uroCam = W.model.cameras.objects[uroCamObj];
var uroCamStyle = 'visible';
if(uroCam.attributes.createdBy !== null)
{
if(W.model.users.objects[uroCam.attributes.createdBy] != null)
{
uroCamCreator = W.model.users.objects[uroCam.attributes.createdBy].userName;
uroCamCreatorRank = W.model.users.objects[uroCam.attributes.createdBy].rank;
}
}
if(uroCam.attributes.updatedBy !== null)
{
if(W.model.users.objects[uroCam.attributes.updatedBy] != null)
{
uroCamUpdater = W.model.users.objects[uroCam.attributes.updatedBy].userName;
uroCamUpdaterRank = W.model.users.objects[uroCam.attributes.updatedBy].rank;
}
}
var uroCamApproved = uroCam.attributes.validated;
var uroCamType = uroCam.attributes.type;
if(filterNameID != null)
{
if(uroGetCBChecked('_cbShowOnlyCamsCreatedBy') === true)
{
if(filterNameID != uroCam.attributes.createdBy) uroCamStyle = 'hidden';
}
if(uroGetCBChecked('_cbShowOnlyCamsEditedBy') === true)
{
if(filterNameID != uroCam.attributes.updatedBy) uroCamStyle = 'hidden';
}
}
if(uroGetCBChecked('_cbShowOnlyMyCams') === true)
{
if((uroUserID != uroCam.attributes.createdBy)&&(uroUserID != uroCam.attributes.updatedBy)) uroCamStyle = 'hidden';
}
if((uroGetCBChecked('_cbShowWorldCams') === false) || (uroGetCBChecked('_cbShowUSACams') === false) || (uroGetCBChecked('_cbShowNonWorldCams') === false))
{
var posWorld = uroCamCreator.indexOf('world_');
var posUSA = uroCamCreator.indexOf('usa_');
if((uroGetCBChecked('_cbShowWorldCams') === false) && (posWorld === 0)) uroCamStyle = 'hidden';
if((uroGetCBChecked('_cbShowUSACams') === false) && (posUSA === 0)) uroCamStyle = 'hidden';
if((uroGetCBChecked('_cbShowNonWorldCams') === false) && (posWorld !== 0) && (posUSA !== 0)) uroCamStyle = 'hidden';
}
if((uroGetCBChecked('_cbShowApprovedCams') === false) || (uroGetCBChecked('_cbShowNonApprovedCams') === false))
{
if((uroGetCBChecked('_cbShowApprovedCams') === false) && (uroCamApproved === true)) uroCamStyle = 'hidden';
if((uroGetCBChecked('_cbShowNonApprovedCams') === false) && (uroCamApproved === false)) uroCamStyle = 'hidden';
}
if((uroGetCBChecked('_cbShowNonApprovedCams') === true) && (uroCamApproved === false))
{
if(((uroGetCBChecked('_cbShowOlderCreatedNonApproved') === true)) && (uroGetCameraAge(uroCam,1) <= uroGetElmValue('_inputCameraMinCreatedDays'))) uroCamStyle = 'hidden';
if(((uroGetCBChecked('_cbShowOlderUpdatedNonApproved') === true)) && (uroGetCameraAge(uroCam,0) <= uroGetElmValue('_inputCameraMinUpdatedDays'))) uroCamStyle = 'hidden';
}
if((uroGetCBChecked('_cbShowSpeedCams') === false) || (uroGetCBChecked('_cbShowRedLightCams') === false) || (uroGetCBChecked('_cbShowDummyCams') === false))
{
if((uroGetCBChecked('_cbShowSpeedCams') === false) && (uroCamType == 2)) uroCamStyle = 'hidden';
if((uroGetCBChecked('_cbShowRedLightCams') === false) && (uroCamType == 4)) uroCamStyle = 'hidden';
if((uroGetCBChecked('_cbShowDummyCams') === false) && (uroCamType == 3)) uroCamStyle = 'hidden';
}
if(uroGetCBChecked('_cbShowSpeedCams') === true)
{
if((uroGetCBChecked('_cbShowIfNoSpeedSet') === false) && (uroCam.attributes.speed === null)) uroCamStyle = 'hidden';
if((uroGetCBChecked('_cbShowIfSpeedSet') === false) && (uroCam.attributes.speed !== null)) uroCamStyle = 'hidden';
}
if(uroGetCBChecked('_cbHideCreatedByMe') === true)
{
if(uroUserID == uroCam.attributes.createdBy) uroCamStyle = 'hidden';
}
if((uroGetCBChecked('_cbHideCreatedByRank0') === true) && (uroCamCreatorRank === 0)) uroCamStyle = 'hidden';
if((uroGetCBChecked('_cbHideCreatedByRank1') === true) && (uroCamCreatorRank == 1)) uroCamStyle = 'hidden';
if((uroGetCBChecked('_cbHideCreatedByRank2') === true) && (uroCamCreatorRank == 2)) uroCamStyle = 'hidden';
if((uroGetCBChecked('_cbHideCreatedByRank3') === true) && (uroCamCreatorRank == 3)) uroCamStyle = 'hidden';
if((uroGetCBChecked('_cbHideCreatedByRank4') === true) && (uroCamCreatorRank == 4)) uroCamStyle = 'hidden';
if((uroGetCBChecked('_cbHideCreatedByRank5') === true) && (uroCamCreatorRank == 5)) uroCamStyle = 'hidden';
if(uroGetCBChecked('_cbHideUpdatedByMe') === true)
{
if(uroUserID == uroCam.attributes.updatedBy) uroCamStyle = 'hidden';
}
if((uroGetCBChecked('_cbHideUpdatedByRank0') === true) && (uroCamUpdaterRank === 0)) uroCamStyle = 'hidden';
if((uroGetCBChecked('_cbHideUpdatedByRank1') === true) && (uroCamUpdaterRank == 1)) uroCamStyle = 'hidden';
if((uroGetCBChecked('_cbHideUpdatedByRank2') === true) && (uroCamUpdaterRank == 2)) uroCamStyle = 'hidden';
if((uroGetCBChecked('_cbHideUpdatedByRank3') === true) && (uroCamUpdaterRank == 3)) uroCamStyle = 'hidden';
if((uroGetCBChecked('_cbHideUpdatedByRank4') === true) && (uroCamUpdaterRank == 4)) uroCamStyle = 'hidden';
if((uroGetCBChecked('_cbHideUpdatedByRank5') === true) && (uroCamUpdaterRank == 5)) uroCamStyle = 'hidden';
if((uroGetCBChecked('_cbHideCWLCams') === true) && (uroIsCamOnWatchList(uroCam.attributes.id) != -1)) uroCamStyle = 'hidden';
var uroCamGeometryID = uroCam.geometry.id;
if(camLayer.getElementById(uroCamGeometryID) !== null)
{
if(uroCamStyle == "hidden")
{
camLayer.getElementById(uroCamGeometryID).remove();
}
}
}
}
}
}
function uroFilterURs_onObjectsChanged()
{
if(uroFilterPreamble())
{
if(uroBackfilling === false)
{
if(uroURDialogIsOpen === false)
{
uroURBackfill();
}
else
{
uroFilterURs();
}
}
}
}
function uroFilterURs_onObjectsAdded()
{
if(uroFilterPreamble())
{
if(uroBackfilling === false)
{
uroURBackfill();
}
}
}
function uroFilterURs_onObjectsRemoved()
{
if(uroFilterPreamble())
{
if(uroBackfilling === false)
{
uroURBackfill();
}
}
}
function uroBackfillQueueObj(lon, lat, blockSize)
{
this.lon = lon;
this.lat = lat;
this.blockSize = blockSize;
}
function uroURBackfill_GetData()
{
if(uroBackfillQueue.length === 0)
{
uroBackfilling = false;
uroFilterURs();
return;
}
var nextBFQueueObj = uroBackfillQueue.shift();
var lon = parseFloat(nextBFQueueObj.lon);
var lat = parseFloat(nextBFQueueObj.lat);
var blockSize = parseFloat(nextBFQueueObj.blockSize);
uroAddLog('Backfill square '+lon+','+lat);
var backfillReq = new XMLHttpRequest();
backfillReq.onreadystatechange = function ()
{
if (backfillReq.readyState == 4)
{
uroAddLog('backfill data request, response '+backfillReq.status+' received');
if (backfillReq.status == 200)
{
var tResp = JSON.parse(backfillReq.responseText);
var urCount = tResp.mapUpdateRequests.objects.length;
uroAddLog(urCount+' URs loaded for backfill processing');
if(urCount == 500)
{
uroAddLog('WARNING - backfill data may have been pre-filtered by server');
}
var backfilled = 0;
for(var i=0; i<urCount; i++)
{
var urID = tResp.mapUpdateRequests.objects[i].id;
if(W.model.mapUpdateRequests.objects[urID] === undefined)
{
var newUR = require('Waze/Feature/Vector/UpdateRequest');
var tUR = new newUR(tResp.mapUpdateRequests.objects[i]);
var tPoint = new OpenLayers.Geometry.Point();
tPoint.x = tResp.mapUpdateRequests.objects[i].geometry.coordinates[0];
tPoint.y = tResp.mapUpdateRequests.objects[i].geometry.coordinates[1];
tPoint.transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913"));
tUR.geometry = tPoint;
var tReqBounds = new OpenLayers.Geometry.Polygon();
var tBounds = new OpenLayers.Bounds();
tBounds.left = tPoint.x;
tBounds.right = tPoint.x;
tBounds.top = tPoint.y;
tBounds.bottom = tPoint.y;
tReqBounds.bounds = tBounds;
tUR.requestBounds = tReqBounds;
W.model.mapUpdateRequests.put(tUR);
backfilled++;
}
}
uroAddLog(backfilled+' URs backfilled');
}
uroURBackfill_GetData();
}
};
var tURL = 'https://' + document.location.host;
tURL += Waze.Config.api_base;
tURL += '/Features?language=en&mapUpdateRequestFilter=0';
tURL += '&bbox='+(lon)+','+(lat)+','+(lon + blockSize)+','+(lat + blockSize);
backfillReq.open('GET',tURL,true);
backfillReq.send();
}
function uroURBackfill()
{
if((uroGetCBChecked('_cbURBackfill') === false) || (uroGetCBChecked('_cbMasterEnable') === false))
{
uroFilterURs();
return;
}
var nativeURCount = Object.keys(W.model.mapUpdateRequests.objects).length;
if(nativeURCount < 500)
{
uroAddLog(nativeURCount+' URs loaded natively, no backfilling required');
uroFilterURs();
return;
}
uroAddLog('exactly 500 URs loaded, possible server-side filtering requiring backfill...');
var subSize = 0.1;
var vpWidth = W.map.getExtent().getWidth();
var vpHeight = W.map.getExtent().getHeight();
var vpCentre = W.map.getCenter();
var vpLL = new OpenLayers.LonLat();
var vpUR = new OpenLayers.LonLat();
vpLL.lon = vpCentre.lon - (vpWidth / 2);
vpLL.lat = vpCentre.lat - (vpHeight / 2);
vpUR.lon = vpCentre.lon + (vpWidth / 2);
vpUR.lat = vpCentre.lat + (vpHeight / 2);
vpLL = vpLL.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326"));
vpUR = vpUR.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326"));
vpLL.lon -= (subSize / 2);
vpLL.lat -= (subSize / 2);
vpUR.lon += (subSize / 2);
vpUR.lat += (subSize / 2);
vpLL.lon = +vpLL.lon.toFixed(1);
vpLL.lat = +vpLL.lat.toFixed(1);
vpUR.lon = +vpUR.lon.toFixed(1);
vpUR.lat = +vpUR.lat.toFixed(1);
uroBackfilling = true;
uroBackfillQueue = [];
for(var bfLat = vpLL.lat; bfLat <= vpUR.lat; bfLat += subSize)
{
for(var bfLon = vpLL.lon; bfLon <= vpUR.lon; bfLon += subSize)
{
uroBackfillQueue.push(new uroBackfillQueueObj(bfLon, bfLat, subSize));
}
}
uroURBackfill_GetData();
}
function uroFilterURs()
{
if(uroUserID === -1) return;
// compatibility fix for URComments - based on code supplied by RickZabel
var hasActiveURFilters = false;
if(uroGetCBChecked('_cbMasterEnable') === true)
{
var urTabInputs = document.getElementById('uroCtrlURs').getElementsByTagName('input');
for(var loop = 0; loop < urTabInputs.length; loop++)
{
if(urTabInputs[loop].type == 'checkbox')
{
var ignoreCB = false;
ignoreCB = ignoreCB || (urTabInputs[loop].id == '_cbCaseInsensitive');
ignoreCB = ignoreCB || (urTabInputs[loop].id == '_cbNoFilterForTaggedURs');
if((urTabInputs[loop].checked) && (ignoreCB === false))
{
hasActiveURFilters = true;
break;
}
}
}
}
sessionStorage.UROverview_hasActiveURFilters = hasActiveURFilters;
if(uroFilterPreamble() === false) return;
uroRefreshUpdateRequestSessions();
var selectorResolver = document.getElementById('_selectURResolverID');
var selectorCommentUser = document.getElementById('_selectURUserID');
if(uroGetCBChecked('_cbURResolverIDFilter') === false)
{
while(selectorResolver.options.length > 0)
{
selectorResolver.options.remove(0);
}
}
if(uroGetCBChecked('_cbURUserIDFilter') === false)
{
while(selectorCommentUser.options.length > 0)
{
selectorCommentUser.options.remove(0);
}
}
if(Object.keys(W.model.updateRequestSessions.objects).length === 0)
{
return;
}
var commenterUser = null;
if(uroGetCBChecked('_cbURUserIDFilter') === true)
{
if(selectorCommentUser.options.length === 0)
{
uroUpdateUserList();
}
if(selectorCommentUser.selectedOptions[0] != null)
{
commenterUser = parseInt(selectorCommentUser.selectedOptions[0].value);
}
}
var resolverUser = null;
if(uroGetCBChecked('_cbURResolverIDFilter') === true)
{
if(selectorResolver.options.length === 0)
{
uroUpdateResolverList();
}
if(selectorResolver.selectedOptions[0] != null)
{
resolverUser = parseInt(selectorResolver.selectedOptions[0].value);
}
}
uroCustomMarkerList = [];
var uFURs_masterEnable = uroGetCBChecked('_cbMasterEnable');
var filterOutsideEditableArea = uroGetCBChecked('_cbURFilterOutsideArea');
var filterSolved = uroGetCBChecked('_cbFilterSolved');
var filterUnidentified = uroGetCBChecked('_cbFilterUnidentified');
var filterClosed = uroGetCBChecked('_cbFilterClosedUR');
var filterOpen = uroGetCBChecked('_cbFilterOpenUR');
var filterDescMustBePresent = uroGetCBChecked('_cbURDescriptionMustBePresent');
var filterDescMustBeAbsent = uroGetCBChecked('_cbURDescriptionMustBeAbsent');
var filterKeywordMustBePresent = uroGetCBChecked('_cbEnableKeywordMustBePresent');
var filterKeywordMustBeAbsent = uroGetCBChecked('_cbEnableKeywordMustBeAbsent');
var filterMinURAge = uroGetCBChecked('_cbEnableMinAgeFilter');
var filterMaxURAge = uroGetCBChecked('_cbEnableMaxAgeFilter');
var filterMinComments = uroGetCBChecked('_cbEnableMinCommentsFilter');
var filterMaxComments = uroGetCBChecked('_cbEnableMaxCommentsFilter');
var filterReporterLastCommenter = uroGetCBChecked('_cbHideIfReporterLastCommenter');
var filterReporterNotLastCommenter = uroGetCBChecked('_cbHideIfReporterNotLastCommenter');
var filterHideAnyComments = uroGetCBChecked('_cbHideAnyComments');
var filterHideNotLastCommenter = uroGetCBChecked('_cbHideIfNotLastCommenter');
var filterHideMyComments = uroGetCBChecked('_cbHideMyComments');
var filterIfLastCommenter = uroGetCBChecked('_cbHideIfLastCommenter');
var filterIfNotLastCommenter = uroGetCBChecked('_cbHideIfNotLastCommenter');
var filterCommentMinAge = uroGetCBChecked('_cbEnableCommentAgeFilter2');
var filterCommentMaxAge = uroGetCBChecked('_cbEnableCommentAgeFilter');
var filterUserID = uroGetCBChecked('_cbURUserIDFilter');
var filterMyFollowed = uroGetCBChecked('_cbHideMyFollowed');
var filterMyUnfollowed = uroGetCBChecked('_cbHideMyUnfollowed');
var filterWazeAuto = uroGetCBChecked('_cbFilterWazeAuto');
var filterRoadworks = uroGetCBChecked('_cbFilterRoadworks');
var filterConstruction = uroGetCBChecked('_cbFilterConstruction');
var filterClosure = uroGetCBChecked('_cbFilterClosure');
var filterEvent = uroGetCBChecked('_cbFilterEvent');
var filterNote = uroGetCBChecked('_cbFilterNote');
var filterWSLM = uroGetCBChecked('_cbFilterWSLM');
var filterBOG = uroGetCBChecked('_cbFilterBOG');
var filterDifficult = uroGetCBChecked('_cbFilterDifficult');
var filterIncorrectTurn = uroGetCBChecked('_cbFilterIncorrectTurn');
var filterIncorrectAddress = uroGetCBChecked('_cbFilterIncorrectAddress');
var filterIncorrectRoute = uroGetCBChecked('_cbFilterIncorrectRoute');
var filterMissingRoundabout = uroGetCBChecked('_cbFilterMissingRoundabout');
var filterGeneralError = uroGetCBChecked('_cbFilterGeneralError');
var filterTurnNotAllowed = uroGetCBChecked('_cbFilterTurnNotAllowed');
var filterIncorrectJunction = uroGetCBChecked('_cbFilterIncorrectJunction');
var filterMissingBridgeOverpass = uroGetCBChecked('_cbFilterMissingBridgeOverpass');
var filterWrongDrivingDirection = uroGetCBChecked('_cbFilterWrongDrivingDirection');
var filterMissingExit = uroGetCBChecked('_cbFilterMissingExit');
var filterMissingRoad = uroGetCBChecked('_cbFilterMissingRoad');
var filterMissingLandmark = uroGetCBChecked('_cbFilterMissingLandmark');
var filterNativeSpeedLimit = uroGetCBChecked('_cbFilterSpeedLimits');
var filterBlockedRoad = uroGetCBChecked('_cbFilterBlockedRoad');
var filterUndefined = uroGetCBChecked('_cbFilterUndefined');
var invertURFilters = uroGetCBChecked('_cbInvertURFilter');
var invertURStateFilters = uroGetCBChecked('_cbInvertURStateFilter');
var noFilterTaggedURs = uroGetCBChecked('_cbNoFilterForTaggedURs');
var noFilterURInURL = uroGetCBChecked('_cbNoFilterForURInURL');
var keywordPresent = uroGetElmValue('_textKeywordPresent');
var keywordAbsent = uroGetElmValue('_textKeywordAbsent');
var thresholdMinAge = uroGetElmValue('_inputFilterMinDays');
var thresholdMaxAge = uroGetElmValue('_inputFilterMaxDays');
var thresholdMinComments = uroGetElmValue('_inputFilterMinComments');
var thresholdMaxComments = uroGetElmValue('_inputFilterMaxComments');
var thresholdMaxCommentAge = uroGetElmValue('_inputFilterCommentDays');
var thresholdMinCommentAge = uroGetElmValue('_inputFilterCommentDays2');
var ignoreOtherEditorComments = uroGetCBChecked('_cbIgnoreOtherEditorComments');
var urcFilteringIsActive = false;
var urcCB = document.getElementById('URCommentsFilterEnabled');
if(urcCB !== null)
{
if(urcCB.checked)
{
urcFilteringIsActive = true;
}
}
urcCB = document.getElementById('URCommentUROOnlyMyUR');
if(urcCB !== null)
{
if(urcCB.checked)
{
urcFilteringIsActive = true;
}
}
urcCB = document.getElementById('URCommentUROHideTagged');
if(urcCB !== null)
{
if(urcCB.checked)
{
urcFilteringIsActive = true;
}
}
for (var urobj in W.model.mapUpdateRequests.objects)
{
if(W.model.mapUpdateRequests.objects.hasOwnProperty(urobj))
{
var ureq = W.model.mapUpdateRequests.objects[urobj];
var ureqID = null;
if(ureq.fid === null) ureqID = ureq.attributes.id;
else ureqID = ureq.fid;
var urStyle = 'visible';
var inhibitFiltering = ((ureqID == uroURIDInURL) && (noFilterURInURL));
var hasMyComments = false;
var nComments = 0;
var customType = uroGetCustomType(ureqID, "ur");
if(W.model.updateRequestSessions.objects[ureqID] != null)
{
nComments = W.model.updateRequestSessions.objects[ureqID].comments.length;
if((uFURs_masterEnable === false) && (nComments === 0))
{
// when master enable is turned off, we want to make sure that all URs, including ones that were previously hidden, are correctly
// displayed in their native form - i.e. no comment count or custom conversation bubbles. The easiest way to achieve this is to
// force the uroRenderCustomMarkers code to test for the presence of these bubbles on each UR, which we do by setting a non-zero
// comment count for each UR... For URs which genuinely do have no comments we use -1 to indicate that we're not really setting
// a comment count, but that we still need to do something that wouldn't be achieved by using 0.
nComments = -1;
}
}
if((uFURs_masterEnable === true) && (inhibitFiltering === false))
{
var wazeauto_ur = false;
var ukroadworks_ur = false;
var construction_ur = false;
var closure_ur = false;
var event_ur = false;
var note_ur = false;
var wslm_ur = false;
var bog_ur = false;
var difficult_ur = false;
var filterByNotIncludedKeyword = false;
var filterByIncludedKeyword = true;
var desc = '';
if(ureq.attributes.description !== null) desc = ureq.attributes.description.replace(/<\/?[^>]+(>|$)/g, "");
if(customType === 0) ukroadworks_ur = true;
else if(customType === 1) construction_ur = true;
else if(customType === 2) closure_ur = true;
else if(customType === 3) event_ur = true;
else if(customType === 4) note_ur = true;
else if(customType === 5) wslm_ur = true;
else if(customType === 6) bog_ur = true;
else if(customType === 7) difficult_ur = true;
// check UR against editable area...
if(filterOutsideEditableArea === true)
{
if(ureq.canEdit() === false) urStyle = 'hidden';
}
// check UR against current session ignore list...
if(uroIsOnIgnoreList(ureqID)) urStyle = 'hidden';
// state-age filtering
if(urStyle == 'visible')
{
// check against closed/not identified filtering if enabled...
if(filterSolved === true)
{
if(ureq.attributes.resolution === 0) urStyle = 'hidden';
}
if(filterUnidentified === true)
{
if(ureq.attributes.resolution == 1) urStyle = 'hidden';
}
if((ureq.attributes.resolvedOn !== null) && (filterClosed === true))
{
urStyle = 'hidden';
}
if((ureq.attributes.resolvedOn === null) && (filterOpen === true))
{
urStyle = 'hidden';
}
if(urStyle == 'visible')
{
// check UR against keyword filtering if enabled...
if(filterDescMustBePresent === true)
{
if(desc === '') urStyle = 'hidden';
}
if(filterDescMustBeAbsent === true)
{
if(desc !== '') urStyle = 'hidden';
}
if(filterKeywordMustBePresent === true)
{
var keywordIsPresentInDesc = uroKeywordPresent(desc,keywordPresent);
filterByIncludedKeyword &= (!keywordIsPresentInDesc);
}
if(filterKeywordMustBeAbsent === true)
{
var keywordIsAbsentInDesc = uroKeywordPresent(desc,keywordAbsent);
filterByNotIncludedKeyword |= keywordIsAbsentInDesc;
}
}
if(urStyle == 'visible')
{
// do age-based filtering if enabled
if(filterMinURAge === true)
{
if(uroGetURAge(ureq,0,false) < thresholdMinAge) urStyle = 'hidden';
}
if(filterMaxURAge === true)
{
if(uroGetURAge(ureq,0,false) > thresholdMaxAge) urStyle = 'hidden';
}
}
if(urStyle == 'visible')
{
if(resolverUser !== null)
{
if(ureq.attributes.resolvedBy != resolverUser) urStyle = 'hidden';
}
}
if(urStyle == 'visible')
{
// do comments/following filtering
if(W.model.updateRequestSessions.objects[ureqID] != null)
{
nComments = W.model.updateRequestSessions.objects[ureqID].comments.length;
var commentDaysOld = -1;
if(filterMinComments === true)
{
if(nComments < thresholdMinComments) urStyle = 'hidden';
}
if(filterMaxComments === true)
{
if(nComments > thresholdMaxComments) urStyle = 'hidden';
}
if(nComments > 0)
{
var reporterIsLastCommenter = false;
if(W.model.updateRequestSessions.objects[ureqID].comments[nComments-1].userID == -1) reporterIsLastCommenter = true;
if(filterReporterLastCommenter === true)
{
if(reporterIsLastCommenter === true) urStyle = 'hidden';
}
else if(filterReporterNotLastCommenter === true)
{
if(reporterIsLastCommenter === false) urStyle = 'hidden';
}
hasMyComments = uroURHasMyComments(ureqID);
if(hasMyComments === false)
{
if(filterHideAnyComments === true) urStyle = 'hidden';
if(filterHideNotLastCommenter === true) urStyle = 'hidden';
}
else
{
if(filterHideMyComments === true) urStyle = 'hidden';
var userIsLastCommenter = false;
if(W.model.updateRequestSessions.objects[ureqID].comments[nComments-1].userID == uroUserID) userIsLastCommenter = true;
if(filterIfLastCommenter === true)
{
if(userIsLastCommenter === true) urStyle = 'hidden';
}
else if(filterIfNotLastCommenter === true)
{
if(userIsLastCommenter === false) urStyle = 'hidden';
}
}
var cidx;
if(ignoreOtherEditorComments === false)
{
commentDaysOld = uroGetCommentAge(W.model.updateRequestSessions.objects[ureqID].comments[nComments-1]);
}
else
{
for(cidx=0; cidx<nComments; cidx++)
{
var cObj = W.model.updateRequestSessions.objects[ureqID].comments[cidx];
if((cObj.userID == uroUserID) || (cObj.userID == -1))
{
commentDaysOld = uroGetCommentAge(cObj);
}
}
}
if((filterCommentMinAge === true) && (commentDaysOld != -1))
{
if(thresholdMinCommentAge > commentDaysOld) urStyle = 'hidden';
}
if((filterCommentMaxAge === true) && (commentDaysOld != -1))
{
if(thresholdMaxCommentAge < commentDaysOld) urStyle = 'hidden';
}
if((commenterUser !== null) && (urStyle != 'hidden'))
{
urStyle = 'hidden';
for(cidx=0; cidx<nComments; cidx++)
{
if(W.model.updateRequestSessions.objects[ureqID].comments[cidx].userID == commenterUser)
{
urStyle = 'visible';
break;
}
}
}
var commentText = '';
for(cidx=0; cidx<nComments; cidx++)
{
commentText += W.model.updateRequestSessions.objects[ureqID].comments[cidx].text;
}
if(filterKeywordMustBePresent === true)
{
var keywordIsPresentInComments = uroKeywordPresent(commentText,keywordPresent);
filterByIncludedKeyword &= (!keywordIsPresentInComments);
}
if(filterKeywordMustBeAbsent === true)
{
var keywordIsAbsentInComments = uroKeywordPresent(commentText,keywordAbsent);
filterByNotIncludedKeyword |= keywordIsAbsentInComments;
}
}
else
{
if(filterUserID === true)
{
urStyle = 'hidden';
}
}
filterByNotIncludedKeyword &= filterKeywordMustBeAbsent;
filterByIncludedKeyword &= filterKeywordMustBePresent;
if(filterByNotIncludedKeyword || filterByIncludedKeyword)
{
urStyle = 'hidden';
}
if(W.model.updateRequestSessions.objects[ureqID].isFollowing === true)
{
if(filterMyFollowed === true) urStyle = 'hidden';
}
else
{
if(filterMyUnfollowed === true) urStyle = 'hidden';
}
}
}
if(invertURStateFilters === true)
{
if(urStyle == 'hidden') urStyle = 'visible';
else urStyle = 'hidden';
}
}
// type filtering
if(urStyle == 'visible')
{
// Test for Waze automatic URs before any others - these always (?) get inserted as General Error URs,
// so we can't filter them by type...
if(desc.indexOf('Waze Automatic:') != -1)
{
wazeauto_ur = true;
}
if(wazeauto_ur === true)
{
if(filterWazeAuto === true) urStyle = 'hidden';
}
else if(ukroadworks_ur === true)
{
if(filterRoadworks === true) urStyle = 'hidden';
}
else if(construction_ur === true)
{
if(filterConstruction === true) urStyle = 'hidden';
}
else if(closure_ur === true)
{
if(filterClosure === true) urStyle = 'hidden';
}
else if(event_ur === true)
{
if(filterEvent === true) urStyle = 'hidden';
}
else if(note_ur === true)
{
if(filterNote === true) urStyle = 'hidden';
}
else if(wslm_ur === true)
{
if(filterWSLM === true) urStyle = 'hidden';
}
else if(bog_ur === true)
{
if(filterBOG === true) urStyle = 'hidden';
}
else if(difficult_ur === true)
{
if(filterDifficult === true) urStyle = 'hidden';
}
else if(ureq.attributes.type == 6)
{
if(filterIncorrectTurn === true) urStyle = 'hidden';
}
else if(ureq.attributes.type == 7)
{
if (filterIncorrectAddress === true) urStyle = 'hidden';
}
else if(ureq.attributes.type == 8)
{
if(filterIncorrectRoute === true) urStyle = 'hidden';
}
else if(ureq.attributes.type == 9)
{
if(filterMissingRoundabout === true) urStyle = 'hidden';
}
else if(ureq.attributes.type == 10)
{
if(filterGeneralError === true) urStyle = 'hidden';
}
else if(ureq.attributes.type == 11)
{
if(filterTurnNotAllowed === true) urStyle = 'hidden';
}
else if(ureq.attributes.type == 12)
{
if(filterIncorrectJunction === true) urStyle = 'hidden';
}
else if(ureq.attributes.type == 13)
{
if(filterMissingBridgeOverpass === true) urStyle = 'hidden';
}
else if(ureq.attributes.type == 14)
{
if(filterWrongDrivingDirection === true) urStyle = 'hidden';
}
else if(ureq.attributes.type == 15)
{
if(filterMissingExit === true) urStyle = 'hidden';
}
else if(ureq.attributes.type == 16)
{
if(filterMissingRoad === true) urStyle = 'hidden';
}
else if(ureq.attributes.type == 18)
{
if(filterMissingLandmark === true) urStyle = 'hidden';
}
else if(ureq.attributes.type == 19)
{
if(filterBlockedRoad === true) urStyle = 'hidden';
}
else if(ureq.attributes.type == 23)
{
if(filterNativeSpeedLimit === true) urStyle = 'hidden';
}
else if(filterUndefined === true) urStyle = 'hidden';
if(invertURFilters === true)
{
if(urStyle == 'hidden') urStyle = 'visible';
else urStyle = 'hidden';
}
}
// stage-age filtering override for tagged URs
if(noFilterTaggedURs === true)
{
if(ukroadworks_ur === true)
{
if(filterRoadworks === false) urStyle = 'visible';
}
else if(construction_ur === true)
{
if(filterConstruction === false) urStyle = 'visible';
}
else if(closure_ur === true)
{
if(filterClosure === false) urStyle = 'visible';
}
else if(event_ur === true)
{
if(filterEvent === false) urStyle = 'visible';
}
else if(note_ur === true)
{
if(filterNote === false) urStyle = 'visible';
}
else if(wslm_ur === true)
{
if(filterWSLM === false) urStyle = 'visible';
}
}
}
// only touch marker visibility if we've got active filter settings, or if URComments is not
// doing any filtering of its own
if((hasActiveURFilters === true) || (urcFilteringIsActive === false) || (uFURs_masterEnable === false))
{
W.map.updateRequestLayer.markers[urobj].icon.imageDiv.style.visibility = urStyle;
}
if(urStyle != 'hidden')
{
uroAddCustomMarkers(ureqID,'ur',customType, hasMyComments, nComments);
}
}
}
uroRenderCustomMarkers('ur');
}
function uroFilterProblems()
{
if(uroFilterPreamble() === false) return;
var selector;
if((uroGetCBChecked('_cbMPNotClosedUserIDFilter') === false) && (uroGetCBChecked('_cbMPClosedUserIDFilter') === false))
{
selector = document.getElementById('_selectMPUserID');
while(selector.options.length > 0)
{
selector.options.remove(0);
}
}
var solverUser = null;
if((uroGetCBChecked('_cbMPNotClosedUserIDFilter') === true) || (uroGetCBChecked('_cbMPClosedUserIDFilter') === true))
{
selector = document.getElementById('_selectMPUserID');
if(selector.options.length === 0)
{
uroUpdateMPSolverList();
}
if(selector.selectedOptions[0] != null)
{
solverUser = parseInt(selector.selectedOptions[0].value);
}
}
var urobj;
var problem;
var problemStyle;
var problem_marker_img;
var uFP_masterEnable = uroGetCBChecked('_cbMasterEnable');
var filter_OutsideEditableArea = uroGetCBChecked('_cbMPFilterOutsideArea');
var filter_Solved = uroGetCBChecked('_cbMPFilterSolved');
var filter_Unidentified = uroGetCBChecked('_cbMPFilterUnidentified');
var filter_Closed = uroGetCBChecked('_cbMPFilterClosed');
var filter_NotClosedUserID = uroGetCBChecked('_cbMPNotClosedUserIDFilter');
var filter_ClosedUserID = uroGetCBChecked('_cbMPClosedUserIDFilter');
var filter_Reopened = uroGetCBChecked('_cbMPFilterReopenedProblem');
var filter_LowSeverity = uroGetCBChecked('_cbMPFilterLowSeverity');
var filter_MediumSeverity = uroGetCBChecked('_cbMPFilterMediumSeverity');
var filter_HighSeverity = uroGetCBChecked('_cbMPFilterHighSeverity');
var filter_TurnProblems = uroGetCBChecked('_cbMPFilterTurnProblem');
var filter_Type101 = uroGetCBChecked('_cbMPFilterDrivingDirectionMismatch');
var filter_Type102 = uroGetCBChecked('_cbMPFilterMissingJunction');
var filter_Type103 = uroGetCBChecked('_cbMPFilterMissingRoad');
var filter_Type104 = uroGetCBChecked('_cbMPFilterCrossroadsJunctionMissing');
var filter_Type105 = uroGetCBChecked('_cbMPFilterRoadTypeMismatch');
var filter_Type106 = uroGetCBChecked('_cbMPFilterRestrictedTurn');
var filter_Type200 = uroGetCBChecked('_cbMPFilterTurnProblem');
var filter_Type300 = uroGetCBChecked('_cbMPFilterRoadClosureProblem');
var filter_TypeUnknown = uroGetCBChecked('_cbMPFilterUnknownProblem');
var filter_TaggedElgin = uroGetCBChecked('_cbFilterElgin');
var filter_TaggedTrafficCast = uroGetCBChecked('_cbFilterTrafficCast');
var filter_TaggedTrafficMaster = uroGetCBChecked('_cbFilterTrafficMaster');
var filter_TaggedCaltrans = uroGetCBChecked('_cbFilterCaltrans');
var filter_TaggedTFL = uroGetCBChecked('_cbFilterTFL');
var filter_Invert = uroGetCBChecked('_cbInvertMPFilter');
for (urobj in W.model.problems.objects)
{
if(W.model.problems.objects.hasOwnProperty(urobj))
{
problem = W.model.problems.objects[urobj];
problemStyle = 'visible';
var ureqID = null;
var customType = null;
if(uFP_masterEnable === true)
{
var elgin_mp = false;
var trafficcast_mp = false;
var trafficmaster_mp = false;
var caltrans_mp = false;
var tfl_mp = false;
ureqID = problem.attributes.id;
customType = uroGetCustomType(ureqID, "mp");
if(customType === 100) elgin_mp = true;
else if(customType === 101) trafficcast_mp = true;
else if(customType === 102) trafficmaster_mp = true;
else if(customType === 103) caltrans_mp = true;
else if(customType === 104) tfl_mp = true;
// check problem against current session ignore list...
if(uroIsOnIgnoreList(ureqID)) problemStyle = 'hidden';
if(filter_OutsideEditableArea === true)
{
if(problem.canEdit() === false)
{
problemStyle = 'hidden';
}
}
// check against closed/not identified filtering if enabled...
problem_marker_img = '';
if(problem.geometry.id !== null)
{
if(document.getElementById(problem.geometry.id) !== null)
{
problem_marker_img = document.getElementById(problem.geometry.id).href.baseVal;
if(filter_Solved === true)
{
if(problem_marker_img.indexOf('_solved') != -1) problemStyle = 'hidden';
}
if(filter_Unidentified === true)
{
if(problem_marker_img.indexOf('_rejected') != -1) problemStyle = 'hidden';
}
}
}
if(filter_Closed === true)
{
if(problem.attributes.open === false)
{
problemStyle = 'hidden';
}
}
if(problemStyle == 'visible')
{
if(solverUser !== null)
{
if((filter_NotClosedUserID === true) && (problem.attributes.resolvedBy == solverUser)) problemStyle = 'hidden';
if((filter_ClosedUserID === true) && (problem.attributes.resolvedBy != solverUser)) problemStyle = 'hidden';
}
}
if(problemStyle == 'visible')
{
var problemType = null;
if(uroDOMHasTurnProblems)
{
problemType = problem.attributes.problemType;
}
else
{
problemType = problem.attributes.subType;
}
if(elgin_mp === true)
{
if(filter_TaggedElgin === true) problemStyle = 'hidden';
}
else if(trafficcast_mp === true)
{
if(filter_TaggedTrafficCast === true) problemStyle = 'hidden';
}
else if(trafficmaster_mp === true)
{
if(filter_TaggedTrafficMaster === true) problemStyle = 'hidden';
}
else if(caltrans_mp === true)
{
if(filter_TaggedCaltrans === true) problemStyle = 'hidden';
}
else if(tfl_mp === true)
{
if(filter_TaggedTFL === true) problemStyle = 'hidden';
}
else if(problemType == 101)
{
if(filter_Type101 === true) problemStyle = 'hidden';
}
else if(problemType == 102)
{
if(filter_Type102 === true) problemStyle = 'hidden';
}
else if(problemType == 103)
{
if(filter_Type103 === true) problemStyle = 'hidden';
}
else if(problemType == 104)
{
if(filter_Type104 === true) problemStyle = 'hidden';
}
else if(problemType == 105)
{
if(filter_Type105 === true) problemStyle = 'hidden';
}
else if(problemType == 106)
{
if(filter_Type106 === true) problemStyle = 'hidden';
}
else if(problemType == 200)
{
if(filter_Type200 === true) problemStyle = 'hidden';
}
else if(problemType == 300)
{
if(filter_Type300 === true) problemStyle = 'hidden';
}
else if(filter_TypeUnknown === true) problemStyle = 'hidden';
if(filter_Reopened === true)
{
if((problem.attributes.open === true) && (problem.attributes.resolvedOn !== null))
{
problemStyle = 'hidden';
}
}
if(filter_Invert === true)
{
if(problemStyle == 'hidden') problemStyle = 'visible';
else problemStyle = 'hidden';
}
if(problem.attributes.weight <= 3)
{
if(filter_LowSeverity === true) problemStyle = 'hidden';
}
else if(problem.attributes.weight <= 7)
{
if(filter_MediumSeverity === true) problemStyle = 'hidden';
}
else if(filter_HighSeverity === true) problemStyle = 'hidden';
}
}
W.map.problemLayer.markers[urobj].icon.imageDiv.style.visibility = problemStyle;
if((problemStyle != 'hidden') && (ureqID !== null) && (customType !== null))
{
uroAddCustomMarkers(ureqID,'mp',customType, false, 0);
}
}
}
if(uroDOMHasTurnProblems)
{
for (urobj in W.model.turnProblems.objects)
{
if(W.model.turnProblems.objects.hasOwnProperty(urobj))
{
problem = W.model.turnProblems.objects[urobj];
problemStyle = 'visible';
if(uFP_masterEnable === true)
{
// check problem against current session ignore list...
if(uroIsOnIgnoreList(problem.attributes.id)) problemStyle = 'hidden';
// check against closed/not identified filtering if enabled...
problem_marker_img = '';
if(problem.geometry.id !== null)
{
if(document.getElementById(problem.geometry.id) !== null)
{
problem_marker_img = document.getElementById(problem.geometry.id).href.baseVal;
if(filter_Solved === true)
{
if(problem_marker_img.indexOf('_solved') != -1) problemStyle = 'hidden';
}
if(filter_Unidentified === true)
{
if(problem_marker_img.indexOf('_rejected') != -1) problemStyle = 'hidden';
}
}
}
if(filter_Closed === true)
{
if(problem.attributes.open === false)
{
problemStyle = 'hidden';
}
}
if(problemStyle == 'visible')
{
if(filter_TurnProblems === true) problemStyle = 'hidden';
if(filter_Reopened === true)
{
if((problem.attributes.open === true) && (problem.attributes.resolvedOn !== null))
{
problemStyle = 'hidden';
}
}
if(filter_Invert === true)
{
if(problemStyle == 'hidden') problemStyle = 'visible';
else problemStyle = 'hidden';
}
}
}
W.map.problemLayer.markers[urobj].icon.imageDiv.style.visibility = problemStyle;
}
}
}
uroRenderCustomMarkers('mp');
}
function uroToHex(decValue,digits)
{
var modifier = 1;
for(var i=0; i<digits; i++)
{
modifier *= 16;
}
decValue = parseInt(decValue);
decValue += modifier;
var retval = decValue.toString(16);
retval = retval.substr(-digits);
retval = retval.toUpperCase();
return retval;
}
function uroFilterPreamble()
{
var mapviewport = document.getElementsByClassName("olMapViewport")[0];
if(mapviewport === null)
{
if(uroNullMapViewport === false)
{
uroAddLog('caught null mapviewport');
uroNullMapViewport = true;
}
return false;
}
var uiElms = document.getElementById('uroCtrlMisc');
if(uiElms == null)
{
uroAddLog('caught missing UI');
return false;
}
if(uiElms.innerHTML.length === 0)
{
uroAddLog('caught empty UI');
return false;
}
uroNullMapViewport = false;
return true;
}
function uroFilterItems_URTabClick()
{
uroFilterURs();
}
function uroFilterItems_MPTabClick()
{
uroFilterProblems();
}
function uroFilterItems_PlacesTabClick()
{
uroFilterPlaces();
}
function uroFilterItems_CamerasTabClick()
{
uroFilterCameras();
}
function uroFilterItems_MiscTabClick()
{
uroFilterItems();
}
function uroFilterItems_MasterEnableClick()
{
if(uroGetCBChecked('_cbMasterEnable') === false)
{
uroHidePopup();
}
uroFilterItems();
}
function uroScaleTheScaleBar()
{
// adjust the scale bar to more accurately reflect true distances at all latitudes
var currLat = W.map.getCenter().transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326")).lat;
if((currLat < 85) && (currLat > -85))
{
var cosLat = Math.cos((currLat * Math.PI) / 180);
var scaleElm;
var elmWidth;
scaleElm = document.getElementsByClassName('olControlScaleLineTop')[0];
if(scaleElm.innerHTML.indexOf(' ') !== -1)
{
elmWidth = Math.round((scaleElm.clientWidth + 2) / cosLat);
scaleElm.innerHTML = scaleElm.innerHTML.replace(' ','');
scaleElm.style.width = elmWidth + 'px';
}
scaleElm = document.getElementsByClassName('olControlScaleLineBottom')[0];
if(scaleElm.innerHTML.indexOf(' ') !== -1)
{
elmWidth = Math.round((scaleElm.clientWidth + 2) / cosLat);
scaleElm.innerHTML = scaleElm.innerHTML.replace(' ','');
scaleElm.style.width = elmWidth + 'px';
}
}
}
function uroFilterItems()
{
uroScaleTheScaleBar();
uroFilterProblems();
uroFilterPlaces();
uroFilterCameras();
uroFilterURs();
}
function uroFilterItemsOnMove()
{
W.map.events.unregister('mousemove',null,uroFilterItemsOnMove);
uroFilterItems();
}
function uroDeleteObject()
{
uroAddLog('delete camera ID '+uroShownFID);
if(W.model.cameras.objects[uroShownFID] === null)
{
uroAddLog('camera object not found...');
return false;
}
uroRemoveCamFromWatchList();
var actionObj = require('Waze/Action/DeleteObject');
var deleteAction = new actionObj(W.model.cameras.objects[uroShownFID], null);
W.model.actionManager.add(deleteAction);
uroExitPopup();
uroHidePopup();
return false;
}
function uroGetUserNameAndRank(userID)
{
var userName;
var userLevel;
if(W.model.users.objects[userID] != null)
{
userName = W.model.users.objects[userID].userName;
if(userName === undefined)
{
userName = userID;
}
userLevel = W.model.users.objects[userID].rank + 1;
}
else
{
userName = userID;
userLevel = '?';
}
return userName + ' (' + userLevel + ')';
}
function uroCheckCommentsForTag(idSrc, customText)
{
var ursObj = W.model.updateRequestSessions.objects[idSrc];
if(typeof(ursObj) == 'undefined') return -1;
if(ursObj.comments.length === 0) return -1;
for(var idx=ursObj.comments.length-1; idx>=0; idx--)
{
for(var tag=0; tag<uroCustomURTags.length; tag++)
{
var keyword = uroCustomURTags[tag];
if(ursObj.comments[idx].text.indexOf(keyword) != -1)
{
return tag;
}
}
if(customText !== '')
{
if(ursObj.comments[idx].text.toLowerCase().indexOf(customText) != -1)
{
return 99;
}
}
}
return -1;
}
function uroGetCustomMarkerIdx(customType)
{
if(customType === 0) return 1; // ROADWORKS
if(customType === 1) return 1; // CONSTRUCTION
if(customType === 2) return 0; // CLOSURE
if(customType === 3) return 4; // EVENT
if(customType === 4) return 3; // NOTE
if(customType === 5) return 5; // WSLM
if(customType === 6) return 11; // BOG
if(customType === 7) return 12; // DIFFICULT
if(customType === 98) return 5; // Native speed limit URs
if(customType === 99) return 2; // custom text
if(customType === 100) return 6; // ELGIN
if(customType === 101) return 7; // TRAFFICCAST
if(customType === 102) return 8; // TRAFFICMASTER
if(customType === 103) return 9; // CALTRANS
if(customType === 104) return 10; // TFL
return -1;
}
function uroGetCustomType(idSrc, markerType)
{
var desc = '';
var customText = '';
if(uroGetCBChecked('_cbCustomKeywordMarkers')) customText = document.getElementById('_textCustomKeyword').value.toLowerCase();
if(markerType == "ur")
{
var ureq = W.model.mapUpdateRequests.objects[idSrc];
// early test for native speed limit URs
if(ureq.attributes.type == 23) return 98;
// UR objects always have a .description attribute, which is set to null if empty...
if(ureq.attributes.description !== null)
{
desc = ureq.attributes.description;
}
}
else if(markerType == "mp")
{
var mp = W.model.problems.objects[idSrc];
// ...whereas MP objects with a blank description don't even get the attribute
if(mp.attributes.description != null)
{
desc = mp.attributes.description;
}
}
if(desc !== '')
{
if(markerType == 'ur')
{
for(var tag=0; tag<uroCustomURTags.length; tag++)
{
var keyword = uroCustomURTags[tag];
if(desc.indexOf(keyword) != -1)
{
return tag;
}
}
}
if((uroGetCBChecked('_cbCustomKeywordMarkers')) && (customText !== ''))
{
if(desc.toLowerCase().indexOf(customText) != -1) return 99;
}
if(markerType == 'mp')
{
if(desc.indexOf('[Elgin]') != -1) return 100;
if(desc.indexOf('[TrafficCast]') != -1) return 101;
if(desc.indexOf('[TM]') != -1) return 102;
if(desc.indexOf('[Caltrans]') != -1) return 103;
if(desc.indexOf('[TfL Open Data]') != -1) return 104;
}
}
if(markerType == "ur")
{
return uroCheckCommentsForTag(idSrc, customText);
}
return -1;
}
function uroFormatRestriction(restObj)
{
var retval = '<tr>';
retval += '<td style="text-align:center;">';
if((restObj.days & 1) == 1) retval += 'S';
else retval += '-';
retval += '</td><td style="text-align:center;">';
if((restObj.days & 2) == 2) retval += 'M';
else retval += '-';
retval += '</td><td style="text-align:center;">';
if((restObj.days & 4) == 4) retval += 'T';
else retval += '-';
retval += '</td><td style="text-align:center;">';
if((restObj.days & 8) == 8) retval += 'W';
else retval += '-';
retval += '</td><td style="text-align:center;">';
if((restObj.days & 16) == 16) retval += 'T';
else retval += '-';
retval += '</td><td style="text-align:center;">';
if((restObj.days & 32) == 32) retval += 'F';
else retval += '-';
retval += '</td><td style="text-align:center;">';
if((restObj.days & 64) == 64) retval += 'S';
else retval += '-';
retval += '</td><td>';
if(restObj.fromDate === null) retval += 'All dates';
else retval += restObj.fromDate+' to '+restObj.toDate;
retval += '</td><td>';
if(restObj.allDay === true) retval += 'All day';
else retval += restObj.fromTime+' to '+restObj.toTime;
retval += '</td><td>';
if(restObj.allVehicleTypes == restObj.vehicleTypes) retval += 'All vehicles';
else retval += 'Some vehicles';
retval += '</td><td>';
if(restObj.description !== null)
{
var desc = restObj.description.replace(/<\/?[^>]+(>|$)/g, "");
desc = uroClickify(desc);
retval += desc;
}
retval += '</td></tr>';
return retval;
}
function uroHidePopup()
{
if(uroPopupShown)
{
uroDiv.style.visibility = 'hidden';
uroPopupShown = false;
uroPopupTimer = -2;
uroShownFID = -1;
}
uroPopupSuppressed = false;
}
function uroSuppressPopup()
{
uroDiv.style.visibility = 'hidden';
window.getSelection().removeAllRanges();
uroPopupSuppressed = true;
}
function uroRecentreSessionOnUR()
{
W.map.updateRequestLayer.markers[uroShownFID].icon.imageDiv.click();
W.map.moveTo(W.map.updateRequestLayer.markers[uroShownFID].lonlat, 5);
uroHidePopup();
return false;
}
function uroRecentreSessionOnMP()
{
W.map.problemLayer.markers[uroShownFID].icon.imageDiv.click();
W.map.moveTo(W.map.problemLayer.markers[uroShownFID].lonlat, 5);
uroHidePopup();
return false;
}
function uroRecentreSessionOnPUR()
{
W.map.placeUpdatesLayer.markers[uroShownFID].icon.imageDiv.click();
W.map.moveTo(W.map.placeUpdatesLayer.markers[uroShownFID].lonlat, 5);
uroHidePopup();
return false;
}
function uroRecentreSessionOnVenueNavPoint()
{
W.map.moveTo(uroGetVenueNavPoint(uroShownFID), 5);
uroHidePopup();
return false;
}
function uroGetDateTimeString(ts)
{
var tDateObj = new Date(ts);
var dateLocale;
var timeLocale;
if(uroGetCBChecked('_cbDateFmtDDMMYY')) dateLocale = 'en-gb';
if(uroGetCBChecked('_cbDateFmtMMDDYY')) dateLocale = 'en-us';
if(uroGetCBChecked('_cbDateFmtYYMMDD')) dateLocale = 'ja';
if(uroGetCBChecked('_cbTimeFmt24H')) timeLocale = 'en-gb';
if(uroGetCBChecked('_cbTimeFmt12H')) timeLocale = 'en-us';
return tDateObj.toLocaleDateString(dateLocale) + ' ' + tDateObj.toLocaleTimeString(timeLocale);
}
function uroParsePxString(pxString)
{
return parseInt(pxString.split("px")[0]);
}
function uroStackListObj(fid,x,y)
{
this.fid = fid;
this.x = uroTypeCast(x);
this.y = uroTypeCast(y);
}
function uroRestackMarkers()
{
if(uroStackList.length === 0) return;
var markerCollection = null;
if(uroStackType == 1) markerCollection = W.map.updateRequestLayer.markers;
else if(uroStackType == 2) markerCollection = W.map.problemLayer.markers;
else if(uroStackType == 3) markerCollection = W.map.placeUpdatesLayer.markers;
if(markerCollection !== null)
{
uroAddLog('restacking markers...');
// strip off the .realX/realY attributes from any UR object we've previously added it to, to allow
// the native recentering to work again...
for(var marker in markerCollection)
{
if(markerCollection.hasOwnProperty(marker))
{
var testMarkerObj = markerCollection[marker];
if(testMarkerObj.model.attributes.geometry.realX != null)
{
testMarkerObj.model.attributes.geometry.x = testMarkerObj.model.attributes.geometry.realX;
testMarkerObj.model.attributes.geometry.y = testMarkerObj.model.attributes.geometry.realY;
delete(testMarkerObj.model.attributes.geometry.realX);
delete(testMarkerObj.model.attributes.geometry.realY);
}
}
}
// now restack any markers that were repositioned...
for(var idx=0; idx<uroStackList.length; idx++)
{
var orig_x = uroStackList[idx].x + 'px';
var orig_y = uroStackList[idx].y + 'px';
var fid = uroStackList[idx].fid;
if(markerCollection[fid] != null)
{
markerCollection[fid].icon.imageDiv.style.left = orig_x;
markerCollection[fid].icon.imageDiv.style.top = orig_y;
}
}
uroStackList = [];
uroUnstackedMasterID = null;
uroStackType = null;
}
}
function uroIsIDAlreadyUnstacked(idSrc)
{
if(uroStackList.length === 0) return false;
for(var idx=0; idx<uroStackList.length; idx++)
{
if(uroStackList[idx].fid == idSrc) return true;
}
return false;
}
function uroCheckStacking(stackType, masterID, unstackedX, unstackedY)
{
if(uroIsIDAlreadyUnstacked(masterID) === true) return;
if(uroStackType !== null) return;
if(uroPopupDwellTimer > 0) return;
uroAddLog('checking for marker stack, masterID: '+masterID+', stackType: '+stackType);
var stackList = [];
stackList.push(masterID);
var threshSquared = uroGetElmValue('_inputUnstackSensitivity');
threshSquared *= threshSquared;
var markerCollection = null;
var marker;
if(stackType == 1) markerCollection = W.map.updateRequestLayer.markers;
else if(stackType == 2) markerCollection = W.map.problemLayer.markers;
else if(stackType == 3) markerCollection = W.map.placeUpdatesLayer.markers;
var offset = 1000000000;
if(markerCollection !== null)
{
for(marker in markerCollection)
{
if(markerCollection.hasOwnProperty(marker))
{
var testMarkerObj = markerCollection[marker];
var includeInStack = (testMarkerObj.icon.imageDiv.style.visibility != 'hidden');
var suppressClosed = (testMarkerObj.icon.imageDiv.classList.contains("recently-closed") & (W.map.updateRequestLayer.showHidden === false));
// if multiple markers are stacked exactly on top of one another, WME will always open up the one which it would have rendered on the
// top of the stack in the absence of any URO+ filtering, regardless of which UR pin actually receives the click event. To prevent
// this, we give each pin in the stack a unique set of false coordinates, storing the original coordinates in newly created
// properties so they can be restored later on
//
// originally this fix changed the x coordinate for each UR in the stack to be a unique value that ought to have been well out of the range
// of any real coordinate and therefore unable to clash with any UR marker coordinates that weren't in the current stack. However it now
// appears this could then cause WME to think a completely different UR was being opened - possibly as a result of some change in coordinate
// handling allowing out of range values to be wrapped around back into the normal range? As a workaround for this new WME behaviour, both the
// x and y coordinates are now set to valid values somewhere in the North Atlantic Ocean - the likelihood of there being any real URs in this
// area is so vanishingly small as to be not worth worrying about...
if(testMarkerObj.model.attributes.geometry.realX === undefined)
{
testMarkerObj.model.attributes.geometry.realX = testMarkerObj.model.attributes.geometry.x;
testMarkerObj.model.attributes.geometry.x += offset;
testMarkerObj.model.attributes.geometry.realY = testMarkerObj.model.attributes.geometry.y;
testMarkerObj.model.attributes.geometry.y += offset;
offset += 1000;
}
if((includeInStack) && (!suppressClosed))
{
if(testMarkerObj.id != masterID)
{
var xdiff = unstackedX - uroParsePxString(markerCollection[testMarkerObj.id].icon.imageDiv.style.left);
var ydiff = unstackedY - uroParsePxString(markerCollection[testMarkerObj.id].icon.imageDiv.style.top);
var distSquared = ((xdiff * xdiff) + (ydiff * ydiff));
if(distSquared < threshSquared)
{
stackList.push(testMarkerObj.id);
}
}
}
}
}
}
// as it's the fiddling with .geometry.x which seems to inhibit the autocentering behaviour when a UR/MP marker is clicked, we need to
// allow this to occur even if unstacking isn't required at this zoom level. To then reenable recentering when clicking on the crosshairs
// or feed entry, we need to reinstate the correct .x value once the marker is no longer being highlighted, which means we pretty much need
// to do all of the unstacking *except* for actually unstacking the stack and hiding the other markers...
var inhibitUnstacking = (W.map.getZoom() < uroGetElmValue('_inputUnstackZoomLevel'));
// also inhibit unstacking if there's only a single marker in the list - this will be true if we're highlighting an isolated marker that
// doesn't need to be unstacked, and where we're only using the .geometry.x fiddle to prevent autocentering...
inhibitUnstacking |= (stackList.length == 1);
uroStackType = stackType;
if(stackList.length > 0)
{
if(inhibitUnstacking) uroAddLog('single marker highlighted, adjusting geometry properties to prevent recentering...');
else uroAddLog('markers are stacked!');
if(uroUnstackedMasterID != masterID)
{
uroAddLog('unstacked ID mismatch, relocating markers...');
uroRestackMarkers();
uroUnstackedMasterID = masterID;
uroStackList = [];
// push the highlighted marker onto the stacklist so uroIsIDAlreadyUnstacked() will return true
uroStackList.push(new uroStackListObj(masterID,unstackedX,unstackedY));
for(var shoveIdx=0; shoveIdx < stackList.length; shoveIdx++)
{
var fid = stackList[shoveIdx];
var x = uroParsePxString(markerCollection[fid].icon.imageDiv.style.left);
var y = uroParsePxString(markerCollection[fid].icon.imageDiv.style.top);
// store the unstacked marker positions so they can be reinstated later
uroStackList.push(new uroStackListObj(fid,x,y));
if(!inhibitUnstacking)
{
markerCollection[fid].icon.imageDiv.style.left = unstackedX + 'px';
markerCollection[fid].icon.imageDiv.style.top = unstackedY + 'px';
unstackedX += 10;
unstackedY -= 30;
}
}
if(!inhibitUnstacking)
{
// hide other markers to prevent confusion with the unstacked markers
for(marker in markerCollection)
{
if(markerCollection.hasOwnProperty(marker))
{
var toHideID = markerCollection[marker].id;
if(uroIsIDAlreadyUnstacked(toHideID) === false)
{
markerCollection[toHideID].icon.imageDiv.style.visibility = 'hidden';
}
}
}
}
}
}
else
{
uroRestackMarkers();
}
}
function uroGetVenueNavPoint(uroFID)
{
for(var vObj in W.model.venues.objects)
{
if(W.model.venues.objects.hasOwnProperty(vObj))
{
if(uroFID == vObj)
{
return W.model.venues.objects[vObj].getNavigationPoint().point.toLonLat();
}
}
}
// just in case... return a safe value if the requested venue object wasn't found
return W.map.getCenter();
}
function uroOpenNewTab()
{
// flush the current settings into localStorage before the new tab opens, so that when its instance of
// URO+ fires up it'll have the same settings as this one
uroSaveSettings();
return true;
}
function uroEditTBR()
{
if(uroTBRObj === null)
{
return;
}
uroTBRObj.click();
return false;
}
function uroKillCentering()
{
return W.map.getExtent();
}
function uroRestoreCentering()
{
if(uroAutoCentreDisabledOn.length > 0)
{
if(uroAutoCentreDisabledOn[0] == 'PUR')
{
if(W.map.placeUpdatesLayer.markers[uroAutoCentreDisabledOn[1]] != null)
{
W.map.placeUpdatesLayer.markers[uroAutoCentreDisabledOn[1]].model.geometry.getBounds = W.map.placeUpdatesLayer.markers[uroAutoCentreDisabledOn[1]].model.geometry.origGetBounds;
}
}
else if(uroAutoCentreDisabledOn[0] == 'MP')
{
if(W.map.problemLayer.markers[uroAutoCentreDisabledOn[1]] != null)
{
W.map.problemLayer.markers[uroAutoCentreDisabledOn[1]].model.getDisconnectBounds = W.map.problemLayer.markers[uroAutoCentreDisabledOn[1]].model.origGetDisconnectBounds;
}
}
uroAutoCentreDisabledOn = [];
}
}
function uroAddClosureRowToTable(rcObj)
{
var result = '';
if(rcObj.active === true)
{
result += '<tr>';
}
else
{
result += '<tr bgcolor="#C0C0C0">';
}
var startDate = rcObj.startDate;
var endDate = "unknown";
if(rcObj.endDate !== null)
{
endDate = rcObj.endDate;
}
var provider = "---";
if(rcObj.provider !== null)
{
provider = rcObj.provider;
}
else if(rcObj.createdBy !== null)
{
provider = uroGetUserNameAndRank(rcObj.createdBy);
}
var reason = "---";
if(rcObj.reason !== null)
{
reason = rcObj.reason;
}
result += '<td>' + startDate + ' to ' + endDate + '</td>';
result += '<td>' + provider + '</td>';
result += '<td>' + reason + '</td>';
result += '</td></tr>';
return result;
}
function uroNewLookHighlightedItemsCheck(e)
{
if(uroMTEMode) return;
if(!uroInitialised) return;
if(e == 'dwellTimeout')
{
}
else
{
if((uroMouseIsDown) && (e.buttons === 0))
{
uroAddLog('trapped erroneous mousedown state');
uroMouseIsDown = false;
}
}
if(uroMouseIsDown)
{
return;
}
if(OpenLayers === null)
{
if(uroNullOpenLayers === false)
{
uroAddLog('caught null OpenLayers');
uroNullOpenLayers = true;
}
return;
}
uroNullOpenLayers = false;
if(W.map.updateRequestLayer === null)
{
if(uroNullURLayer === false)
{
uroAddLog('caught null UR layer');
uroNullURLayer = true;
}
return;
}
uroNullURLayer = false;
if(W.map.problemLayer === null)
{
if(uroNullProblemLayer === false)
{
uroAddLog('caught null problem layer');
uroNullProblemLayer = true;
}
return;
}
uroNullProblemLayer = false;
if(uroGetCBChecked('_cbMasterEnable') === false)
{
return;
}
var mouseX;
var mouseY;
if(e == 'dwellTimeout')
{
mouseX = uroPrevMouseX;
mouseY = uroPrevMouseY;
}
else
{
mouseX = e.pageX - document.getElementById('map').getBoundingClientRect().left;
mouseY = e.pageY - document.getElementById('map').getBoundingClientRect().top;
var maxJitter = uroGetElmValue('_inputMaxJitter');
if((Math.abs(uroPrevMouseX - mouseX) > maxJitter) || (Math.abs(uroPrevMouseY - mouseY) > maxJitter))
{
uroPopupDwellTimer = uroGetElmValue('_inputPopupDwellTimeout');
}
uroPrevMouseX = mouseX;
uroPrevMouseY = mouseY;
}
var result = '';
var rw;
var rh;
var popupXOffset = uroParsePxString(window.getComputedStyle(document.getElementById('sidebar')).getPropertyValue("width"));
var popupYOffset = $(document.getElementById("WazeMap")).offset().top - 80;
var uroPopupX = mouseX + popupXOffset + 10;
var uroPopupY = mouseY + popupYOffset - 10;
var objHasIgnoreLink = false;
var objHasDeleteLink = false;
var objHasAddWatchLink = false;
var objHasRemoveWatchLink = false;
var objHasUpdateWatchLink = false;
var objHasRecentreSessionLink = false;
var objHasOpenInNewTabLink = false;
var objHasCloneLink = false;
var isVenue = false;
var newPopupType = null;
var markerObj;
var markerPos;
var markerImg;
var ureq;
var idx;
var hovered;
// popup for segment restrictions
if(uroGetCBChecked('_cbInhibitSegPopup') === false)
{
for(var slIdx=0; slIdx < W.map.segmentLayer.features.length; slIdx++)
{
if(W.map.segmentLayer.features[slIdx].renderIntent == 'highlight')
{
if(W.map.getExtent().intersectsBounds(W.map.segmentLayer.features[slIdx].geometry.getBounds()))
{
var doPopUp = false;
var segObj;
var restObj;
if(W.map.segmentLayer.features[slIdx].fid === null) segObj = W.map.segmentLayer.features[slIdx].model;
else segObj = W.map.segmentLayer.features[slIdx];
// generic segment data
if(uroGetCBChecked('_cbInhibitSegGenericPopup') === false)
{
doPopUp = true;
var streetID = segObj.attributes.primaryStreetID;
var streetName = W.model.streets.objects[streetID].name;
if(streetName !== null)
{
result += '<b>'+streetName+'</b><br>';
}
result += '<b>ID: </b>'+segObj.attributes.id+'<br>';
var fwdSpeed = segObj.attributes.fwdMaxSpeed;
var revSpeed = segObj.attributes.revMaxSpeed;
var fwdUnverified = segObj.attributes.fwdMaxSpeedUnverified;
var revUnverified = segObj.attributes.revMaxSpeedUnverified;
if(segObj.attributes.fwdDirection)
{
result += '<b>A-B speed: </b>'+uroGetLocalisedSpeedString(fwdSpeed);
if(fwdUnverified) result += ' (unverified)';
result += '<br>';
}
if(segObj.attributes.revDirection)
{
result += '<b>B-A speed: </b>'+uroGetLocalisedSpeedString(revSpeed);
if(revUnverified) result += ' (unverified)';
result += '<br>';
}
if((segObj.attributes.fwdDirection) && (segObj.attributes.revDirection) && (fwdSpeed != revSpeed) && (!fwdUnverified) && (!revUnverified))
{
result += 'Two-way segment has different verified speed limits...<br>';
}
}
// segment restrictions
result += '<table cellpadding=4 border=1">';
if(segObj.attributes.fwdRestrictions.length > 0)
{
doPopUp = true;
result += '<tr><td colspan=11><b>A-B restrictions:</b></td></tr>';
for(idx = 0; idx < segObj.attributes.fwdRestrictions.length; idx++)
{
restObj = segObj.attributes.fwdRestrictions[idx];
result += uroFormatRestriction(restObj);
}
}
if (segObj.attributes.revRestrictions.length > 0)
{
doPopUp = true;
result += '<tr><td colspan=11><b>B-A restrictions:</b></td></tr>';
for(idx = 0; idx < segObj.attributes.revRestrictions.length; idx++)
{
restObj = segObj.attributes.revRestrictions[idx];
result += uroFormatRestriction(restObj);
}
}
result += '</table>';
if(W.map.closuresMarkerLayer.getVisibility() === true)
{
result += '<table cellpadding=4 border=1" width="100%">';
if(segObj.attributes.hasClosures === true)
{
var hasFwd = false;
var hasRev = false;
var rcObj;
var roadClosure;
for(roadClosure in W.model.roadClosures.objects)
{
if(W.model.roadClosures.objects.hasOwnProperty(roadClosure))
{
rcObj = W.model.roadClosures.objects[roadClosure];
if(rcObj.segID == segObj.attributes.id)
{
if(rcObj.forward === true)
{
if(hasFwd === false)
{
result += '<tr><td colspan=3><b>A-B closures:</b></td></tr>';
hasFwd = true;
}
result += uroAddClosureRowToTable(rcObj);
}
else
{
hasRev = true;
}
}
}
}
if(hasRev === true)
{
result += '<tr><td colspan=3><b>B-A closures:</b></td></tr>';
for(roadClosure in W.model.roadClosures.objects)
{
if(W.model.roadClosures.objects.hasOwnProperty(roadClosure))
{
rcObj = W.model.roadClosures.objects[roadClosure];
if(rcObj.segID == segObj.attributes.id)
{
if(rcObj.forward === false)
{
result += uroAddClosureRowToTable(rcObj);
}
}
}
}
}
if((hasFwd === true) || (hasRev === true))
{
doPopUp = true;
}
}
result += '</table>';
}
if(doPopUp === true)
{
if(segObj.attributes.id === null) uroFID = segObj.id;
else uroFID = segObj.attributes.id;
newPopupType = 'segment_restriction';
}
break;
}
else
{
uroAddLog('segment '+uroFID+' has renderIntent==highlight but is offscreen... blocking popup');
}
}
}
}
// popup for restricted turns
if(newPopupType === null)
{
if(uroGetCBChecked('_cbInhibitTurnsPopup') === false)
{
var turnMarkerCount = W.map.layers[uroTurnsLayerIdx].markers.length;
if(turnMarkerCount > 0)
{
for(idx=0; idx<turnMarkerCount; idx++)
{
markerObj = W.map.layers[uroTurnsLayerIdx].markers[idx];
var arrowElm = markerObj.icon.imageDiv.childNodes[0];
markerImg = window.getComputedStyle(arrowElm).getPropertyValue("background-image");
markerPos = window.getComputedStyle(arrowElm).getPropertyValue("background-position");
markerPos = markerPos.split(' ');
markerPos = parseInt(markerPos[1].substr(0,markerPos[1].length-2));
hovered = false;
if(markerImg.indexOf('turns-se0f8d1e954.png') != -1)
{
if(markerPos == -141)
{
hovered = true;
}
}
if(hovered === true)
{
uroAddLog('hover over restricted turn marker');
uroTBRObj = arrowElm.childNodes[0];
var trObj = ($(arrowElm).data('model'));
var resObj = null;
if(trObj.fromSeg.attributes.fromRestrictions != null)
{
resObj = trObj.fromSeg.attributes.fromRestrictions[trObj.toSeg.attributes.id];
}
if(resObj === null)
{
if(trObj.fromSeg.attributes.toRestrictions != null)
{
resObj = trObj.fromSeg.attributes.toRestrictions[trObj.toSeg.attributes.id];
}
}
result += '<label id="_editTBR">Click to edit</label><br>';
result += '<table cellpadding=4 border=1">';
for(var resIdx=0; resIdx < resObj.length; resIdx++)
{
result += uroFormatRestriction(resObj[resIdx]);
}
result += '</table>';
uroFID = markerObj.icon.imageDiv._eventCacheID;
newPopupType = 'turn_restriction';
break;
}
}
}
}
}
var targetTab = '';
// popup for landmarks
if((newPopupType === null) && (uroGetCBChecked('_cbInhibitLandmarkPopup') === false))
{
uroPlaceSelected = false;
var venueObj = null;
var renderIntent = null;
var navpointPos=new OpenLayers.LonLat();
for(var llFeatureIdx=0; llFeatureIdx < W.map.landmarkLayer.features.length; llFeatureIdx++)
{
renderIntent = W.map.landmarkLayer.features[llFeatureIdx].renderIntent;
if(renderIntent == 'highlight')
{
if(W.map.getExtent().intersectsBounds(W.map.landmarkLayer.features[llFeatureIdx].geometry.getBounds()))
{
if(W.map.landmarkLayer.features[llFeatureIdx].fid === null) venueObj = W.map.landmarkLayer.features[llFeatureIdx].model;
else venueObj = W.map.landmarkLayer.features[llFeatureIdx];
if(newPopupType === null)
{
if(venueObj.attributes.id === null) uroFID = venueObj.id;
else uroFID = venueObj.attributes.id;
navpointPos = uroGetVenueNavPoint(uroFID);
navpointPos.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326"));
result += '<b>';
if(venueObj.attributes.name === '')
{
if(venueObj.attributes.residential === true) result += '<i>Residential</i>';
else result += '<i>Unnamed</i>';
}
else result += venueObj.attributes.name;
if(venueObj.attributes.externalProviderIDs.length > 0)
{
result += ' <i>(linked)</i>';
}
if(venueObj.attributes.adLocked)
{
result += ' <i>(AdLocked)</i>';
}
result += '</b><br>';
result += '<ul>';
for(idx = 0; idx < venueObj.attributes.categories.length; idx++)
{
result += '<li>' + I18n.lookup("venues.categories." + venueObj.attributes.categories[idx]);
}
result += '</ul>';
if(venueObj.attributes.residential === true)
{
if(venueObj.geometry.CLASS_NAME == 'OpenLayers.Geometry.Point')
{
result += '<a href="#" id="_cloneRP">Clone place</a>';
objHasCloneLink = true;
}
}
var npLink = document.location.href;
var npLayers = '&layers='+uroGetVisibilityBitmask();
npLink = npLink.substr(0,npLink.indexOf('?zoom'));
npLink += '?zoom=5&lat='+navpointPos.lat+'&lon='+navpointPos.lon+npLayers;
targetTab = "_uroTab_" + Math.round(Math.random()*1000000);
result += '<hr>Jump to nav point: <a href="'+npLink+'" id="_openInNewTab" target="'+targetTab+'">in new tab</a> - ';
objHasOpenInNewTabLink = true;
result += '<a href="#" id="_recentreSession">in this tab</a>';
objHasRecentreSessionLink = true;
newPopupType = 'venue';
isVenue = true;
break;
}
else
{
var otherID;
if(venueObj.attributes.id === null) otherID = venueObj.id;
else otherID = venueObj.attributes.id;
uroAddLog('venue '+otherID+' is also highlighted');
}
}
else
{
uroAddLog('landmark '+uroFID+' has renderIntent==highlight but is offscreen... blocking popup');
}
}
else if((renderIntent == 'select') || (renderIntent == 'highlightselected'))
{
uroPlaceSelected = true;
}
}
}
var unstackedX;
var unstackedY;
var ureqID = null;
var isUR = false;
var isProblem = false;
var isTurnProb = false;
var isPlaceUpdate = false;
// look for URs, place updates and problems
if(newPopupType === null)
{
var idSrc = null;
if(uroGetCBChecked('_cbInhibitURPopup') === false)
{
hovered = false;
for(var markerURL in W.map.updateRequestLayer.markers)
{
if(W.map.updateRequestLayer.markers.hasOwnProperty(markerURL))
{
markerObj = W.map.updateRequestLayer.markers[markerURL];
markerImg = markerObj.icon.$div.css('background-image');
markerPos = markerObj.icon.$div.css('background-position');
markerPos = markerPos.split(' ');
markerPos = parseInt(markerPos[1].substr(0,markerPos[1].length-2));
var urIDSrc = markerObj.id;
if((markerPos == -403) || (markerPos == -483) || (markerPos == -563) || (markerPos == -643))
{
hovered = true;
isUR = true;
newPopupType = 'ur';
uroAddLog('hover over UR ID '+urIDSrc);
unstackedX = uroParsePxString(W.map.updateRequestLayer.markers[urIDSrc].icon.imageDiv.style.left);
unstackedY = uroParsePxString(W.map.updateRequestLayer.markers[urIDSrc].icon.imageDiv.style.top);
// override popup base position
uroPopupX = unstackedX + popupXOffset + 6;
uroPopupY = unstackedY + popupYOffset + 66;
uroPopupX -= uroParsePxString(W.map.segmentLayer.div.style.left);
uroPopupY -= uroParsePxString(W.map.segmentLayer.div.style.top);
// check for stacking...
if(uroShownFID != idSrc)
{
uroCheckStacking(1,urIDSrc, unstackedX, unstackedY);
}
idSrc = urIDSrc;
break;
}
}
}
if((hovered === false) && (uroStackType == 1))
{
uroRestackMarkers();
uroFilterURs();
}
}
if((newPopupType === null) && (uroGetCBChecked('_cbInhibitPUPopup') === false))
{
hovered = false;
for(var markerPUL in W.map.placeUpdatesLayer.markers)
{
if(W.map.placeUpdatesLayer.markers.hasOwnProperty(markerPUL))
{
markerObj = W.map.placeUpdatesLayer.markers[markerPUL];
markerImg = markerObj.icon.$div.css('background-image');
markerPos = markerObj.icon.$div.css('background-position');
markerPos = markerPos.split(' ');
markerPos = parseInt(markerPos[1].substr(0,markerPos[1].length-2));
if(markerImg.indexOf('placeUpdates-sb30471988c.png') != -1)
{
// absolute offsets: 0 = new place, -120 = flagged, -240 = new photo, -360 = updated details
// relative offsets: 0 = green, -40 = highlighted, -80 = default
if(((markerPos + 40) % 120) === 0)
{
hovered = true;
uroAddLog('PUR marker type 1');
}
}
else if((markerImg.indexOf('placeUpdates-s2e8d9c5ce4.png') != -1)||(markerImg.indexOf('placeUpdates-s58d24ce3b0.png') != -1))
{
if
(
(markerObj.icon.$div.css("filter") == "brightness(110%)") ||
(markerObj.icon.$div.css("webkit-filter") == "brightness(1.1)")
)
{
hovered = true;
uroAddLog('PUR marker type 2');
}
}
if(hovered === true)
{
idSrc = markerObj.id;
unstackedX = uroParsePxString(W.map.placeUpdatesLayer.markers[idSrc].icon.imageDiv.style.left);
unstackedY = uroParsePxString(W.map.placeUpdatesLayer.markers[idSrc].icon.imageDiv.style.top);
// override popup base position
uroPopupX = unstackedX + popupXOffset + 6;
uroPopupY = unstackedY + popupYOffset + 66;
uroPopupX -= uroParsePxString(W.map.segmentLayer.div.style.left);
uroPopupY -= uroParsePxString(W.map.segmentLayer.div.style.top);
if(uroShownFID != idSrc)
{
// check for stacking...
uroCheckStacking(3,idSrc, unstackedX, unstackedY);
}
isPlaceUpdate = true;
newPopupType = 'pur';
uroAddLog('hover over placeUpdate ID '+idSrc);
// to inhibit auto-centering only when the PUR marker is clicked, we wait for the marker to get highlighted, then
// make a copy of the original getBounds() function before replacing it with a call to W.map.getExtent(). Clicking
// the marker causes a call to getBounds() which will then return the current map extent, and thus no change in the
// map view will occur...
uroRestoreCentering();
W.map.placeUpdatesLayer.markers[markerPUL].model.geometry.origGetBounds = W.map.placeUpdatesLayer.markers[markerPUL].model.geometry.getBounds;
W.map.placeUpdatesLayer.markers[markerPUL].model.geometry.getBounds = uroKillCentering;
uroAutoCentreDisabledOn.push('PUR', markerPUL);
break;
}
}
}
if((hovered === false) && (uroStackType == 3))
{
uroRestackMarkers();
uroFilterPlaces();
}
}
if((newPopupType === null) && (uroGetCBChecked('_cbInhibitMPPopup') === false))
{
hovered = false;
for(var markerPL in W.map.problemLayer.markers)
{
if(W.map.problemLayer.markers.hasOwnProperty(markerPL))
{
markerObj = W.map.problemLayer.markers[markerPL];
markerImg = markerObj.icon.$div.css('background-image');
markerPos = markerObj.icon.$div.css('background-position');
markerPos = markerPos.split(' ');
markerPos = parseInt(markerPos[1].substr(0,markerPos[1].length-2));
if((markerPos == -65) || (markerPos == -145) || (markerPos == -225) || (markerPos == -305))
{
hovered = true;
idSrc = null;
if(markerObj.model.fid === null) idSrc = markerObj.id;
else idSrc = markerObj.model.fid;
unstackedX = uroParsePxString(W.map.problemLayer.markers[idSrc].icon.imageDiv.style.left);
unstackedY = uroParsePxString(W.map.problemLayer.markers[idSrc].icon.imageDiv.style.top);
// override popup base position
uroPopupX = unstackedX + popupXOffset + 6;
uroPopupY = unstackedY + popupYOffset + 66;
uroPopupX -= uroParsePxString(W.map.segmentLayer.div.style.left);
uroPopupY -= uroParsePxString(W.map.segmentLayer.div.style.top);
// check for stacking...
if(uroShownFID != idSrc)
{
uroCheckStacking(2,idSrc, unstackedX, unstackedY);
}
isProblem = true;
newPopupType = 'map_problem';
uroAddLog('hover over problem ID '+idSrc);
// same method of disabling the on-click auto-centre behaviour as for PURs above...
uroRestoreCentering();
W.map.problemLayer.markers[markerPL].model.origGetDisconnectBounds = W.map.problemLayer.markers[markerPL].model.getDisconnectBounds;
W.map.problemLayer.markers[markerPL].model.getDisconnectBounds = uroKillCentering;
uroAutoCentreDisabledOn.push('MP', markerPL);
break;
}
}
}
if((hovered === false) && (uroStackType == 2))
{
uroRestackMarkers();
uroFilterProblems();
}
}
if (idSrc !== null)
{
ureq = null;
if(isUR) ureq = W.model.mapUpdateRequests.objects[idSrc];
else if(isProblem)
{
ureq = W.model.problems.objects[idSrc];
if(ureq === undefined)
{
if(uroDOMHasTurnProblems)
{
ureq = W.model.turnProblems.objects[idSrc];
if(ureq != null) isTurnProb = true;
}
}
}
else if(isPlaceUpdate) ureq = W.map.placeUpdatesLayer.markers[idSrc].model;
if(ureq.fid !== null) ureqID = ureq.fid;
else if(ureq.id !== null) ureqID = ureq.id;
else if(ureq.attributes.id !== null) ureqID = ureq.attributes.id;
uroFID = ureqID;
if(isUR)
{
uroHoveredURID = uroFID;
}
else
{
uroHoveredURID = null;
}
}
else
{
if(uroFID != -1)
{
uroFID = -1;
}
}
if(uroFID != -1)
{
var uroDaysResolved;
if(isUR)
{
uroAddLog('building popup for UR '+idSrc);
result = '<b>Update Request ('+idSrc+'): ' + I18n.lookup("update_requests.types." + ureq.attributes.type) + '</b><br>';
if(ureq.attributes.description !== null)
{
var desc = ureq.attributes.description.replace(/<\/?[^>]+(>|$)/g, "");
if(desc != "null")
{
desc = uroClickify(desc);
result += desc + '<br>';
}
}
var uroDaysOld = uroGetURAge(ureq,0,false);
var uroSubmittedTS = uroGetURAge(ureq,0,true);
if(uroSubmittedTS != -1)
{
uroSubmittedTS = uroGetDateTimeString(uroSubmittedTS);
}
if(uroDaysOld != -1)
{
result += '<i>Submitted ' + uroParseDaysAgo(uroDaysOld) + ' ';
if(uroSubmittedTS != -1) result += '(' + uroSubmittedTS + ') ';
if(ureq.attributes.guestUserName != null)
{
result += 'via Livemap';
if(ureq.attributes.guestUserName !== '')
{
result += ' by '+ureq.attributes.guestUserName.replace(/<\/?[^>]+(>|$)/g, "");
}
}
result += '</i>';
}
if(ureq.attributes.resolvedOn !== null)
{
uroDaysResolved = uroGetURAge(ureq,1,false);
var uroResolvedTS = uroGetURAge(ureq,1,true);
if(uroResolvedTS != -1)
{
uroResolvedTS = uroGetDateTimeString(uroResolvedTS);
}
if(uroDaysResolved != -1)
{
result += '<br><i>Closed ' + uroParseDaysAgo(uroDaysResolved) + ' ';
if(uroResolvedTS != -1) result += '(' + uroResolvedTS + ')</i>';
result += '<br><i>Marked as ';
if(ureq.attributes.resolution === 0) result += 'solved';
else if(ureq.attributes.resolution == 1) result += 'not identified';
else result += 'unknown';
if(ureq.attributes.resolvedBy !== null)
{
result += ' by '+uroGetUserNameAndRank(ureq.attributes.resolvedBy);
}
result += '</i>';
}
}
if(W.model.updateRequestSessions.objects[ureqID] != null)
{
var hasMyComments = uroURHasMyComments(ureqID);
var nComments = W.model.updateRequestSessions.objects[ureqID].comments.length;
result += '<br>' + nComments + ' comment';
if(nComments != 1) result += 's';
if((hasMyComments === false) && (nComments > 0)) result += ' (none by me)';
if(nComments > 0)
{
var commentDaysOld = uroGetCommentAge(W.model.updateRequestSessions.objects[ureqID].comments[nComments-1]);
if(commentDaysOld != -1)
{
result += ', last update '+uroParseDaysAgo(commentDaysOld);
}
}
}
}
else if(isProblem)
{
uroAddLog('building popup for problem '+idSrc);
if(isTurnProb) result = '<b>Turn Problem ('+idSrc+'): ' + I18n.lookup("problems.types.turn.title");
else
{
result = '<b>Map Problem ('+idSrc+'): ';
var problemType = null;
if(uroDOMHasTurnProblems)
{
problemType = ureq.attributes.problemType;
}
else
{
problemType = ureq.attributes.subType;
}
if(problemType == 300)
{
result += I18n.lookup("problems.panel.closure.title");
}
else
{
if(I18n.lookup("problems.types." + problemType) === undefined) result += 'Unknown problem type ('+problemType+')';
else result += I18n.lookup("problems.types." + problemType + ".title");
}
}
result += '</b><br>';
if(ureq.attributes.description != null)
{
result += 'Description: ' + ureq.attributes.description + '<br>';
}
if(ureq.attributes.extraInfo != null)
{
result += 'ExtraInfo: ' + ureq.attributes.extraInfo + '<br>';
}
if(ureq.attributes.provider != null)
{
result += 'Provider: ' + ureq.attributes.provider + '<br>';
}
if(ureq.attributes.resolvedOn != null)
{
uroDaysResolved = uroGetURAge(ureq,1,false);
if(uroDaysResolved != -1)
{
result += '<br><i>Closed ' + uroParseDaysAgo(uroDaysResolved) + ' ';
if(ureq.attributes.resolvedBy != null)
{
result += ' by '+uroGetUserNameAndRank(ureq.attributes.resolvedBy);
}
if((ureq.attributes.open === true) && (ureq.attributes.resolvedOn != null))
{
result += '<br>Reopened by Waze';
}
result += '</i>';
}
}
}
else if(isPlaceUpdate)
{
uroAddLog('building popup for placeUpdate '+idSrc);
result = '<b>';
if(ureq.attributes.name === '') result += 'Unnamed landmark';
else result += ureq.attributes.name;
result += '</b><br>';
result += '<ul>';
for(idx = 0; idx < ureq.attributes.categories.length; idx++)
{
result += '<li>' + I18n.lookup("venues.categories." + ureq.attributes.categories[idx]);
}
result += '</ul>';
if(ureq.attributes.residential === true)
{
result += '<i>Residential</i>';
}
var daysOld = uroGetPURAge(ureq);
if(daysOld != -1)
{
result += '<br><i>Submitted '+uroParseDaysAgo(daysOld)+'</i>';
}
}
// add "open new WME tab" link
var urPos=new OpenLayers.LonLat();
if(isPlaceUpdate)
{
urPos=ureq.geometry.bounds.centerLonLat.clone();
}
else
{
if(ureq.geometry.realX === undefined)
{
urPos.lon = ureq.geometry.x;
urPos.lat = ureq.geometry.y;
}
else
{
urPos.lon = ureq.geometry.realX;
urPos.lat = ureq.geometry.realY;
}
}
urPos.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326"));
var urLink = document.location.href;
var urLayers = '&layers='+uroGetVisibilityBitmask();
urLink = urLink.substr(0,urLink.indexOf('?zoom'));
urLink += '?zoom=5&lat='+urPos.lat+'&lon='+urPos.lon+urLayers;
if(isUR) urLink += '&mapUpdateRequest='+idSrc;
else if(isTurnProb) urLink += '&showturn='+idSrc+'&endshow';
else if(isProblem) urLink += '&mapProblem='+idSrc;
else if(isPlaceUpdate) urLink += '&showpur='+idSrc+'&endshow';
targetTab = "_uroTab_" + Math.round(Math.random()*1000000);
result += '<hr><ul><li><a href="'+urLink+'" id="_openInNewTab" target="'+targetTab+'">Open in new tab</a> - ';
objHasOpenInNewTabLink = true;
result += '<a href="#" id="_recentreSession">centre in current tab</a>';
objHasRecentreSessionLink = true;
// add "open new livemap tab" link
var lmLink = null;
if(document.getElementById("livemap-link") != null)
{
uroAddLog('Livemap link in livemap-link id element');
lmLink = document.getElementById("livemap-link").href;
}
else if(document.getElementsByClassName("livemap-link") != null)
{
uroAddLog('Livemap link in livemap-link class element');
lmLink = document.getElementsByClassName("livemap-link")[0].href;
}
else
{
uroAddLog('Livemap link not found...');
}
if(lmLink !== null)
{
var zpos = lmLink.indexOf('?');
if(zpos > -1) lmLink = lmLink.substr(0,zpos);
lmLink += '?zoom=17&lat='+urPos.lat+'&lon='+urPos.lon+'&layers=BTTTT';
result += '<li><a href="'+lmLink+'" target="_lmTab">Open in new livemap tab</a>';
}
if(!isPlaceUpdate)
{
// add "ignore for this session" link
result += '<li><a href="#" id="_addtoignore">Hide for this session</a></ul>';
objHasIgnoreLink = true;
}
}
}
if((newPopupType != 'map_problem') && (newPopupType != 'pur'))
{
uroRestoreCentering();
}
// look for cameras
if((newPopupType === null) && (uroGetCBChecked('_cbInhibitCamPopup') === false))
{
for(var clFeatureIdx = 0; clFeatureIdx < W.map.camerasLayer.features.length; clFeatureIdx++)
{
if(W.map.camerasLayer.features[clFeatureIdx].renderIntent == 'highlight')
{
if(W.map.camerasLayer.features[clFeatureIdx].fid === null) ureq = W.map.camerasLayer.features[clFeatureIdx].model;
else ureq = W.map.camerasLayer.features[clFeatureIdx];
if(ureq.fid === null) ureqID = ureq.attributes.id;
else ureqID = ureq.fid;
// test isSelected() so that we only do overview data on cameras that are being hovered over
if(ureq.isSelected() === false)
{
uroPopupY -= 20;
newPopupType = 'camera';
uroFID = ureqID;
uroAddLog('generating popup for camera '+uroFID);
if(I18n.lookup("edit.camera.fields.type") === undefined)
{
result += '<b>Camera: ' + ureq.TYPES[ureq.attributes.type] + '</b><br>';
}
else
{
result += '<b>Camera: ' + I18n.lookup("edit.camera.fields.type." + ureq.attributes.type) + '</b><br>';
}
result += 'ID: '+uroFID+'<br>';
result += 'Created by ';
var userID;
if(W.model.users.get(ureq.attributes.createdBy) != null)
{
userID = ureq.attributes.createdBy;
result += uroGetUserNameAndRank(userID);
}
else result += 'unknown';
result += ', ';
var camAge = uroGetCameraAge(ureq,1);
if(camAge != -1)
{
result += uroParseDaysAgo(camAge);
}
else result += 'unknown days ago';
result += '<br>Updated by ';
if(W.model.users.get(ureq.attributes.updatedBy) != null)
{
userID = ureq.attributes.updatedBy;
var userName = W.model.users.objects[userID].userName;
var userLevel = W.model.users.objects[userID].rank + 1;
result += userName + ' (' + userLevel + ')';
}
else result += 'unknown';
result += ', ';
camAge = uroGetCameraAge(ureq,0);
if(camAge != -1)
{
result += uroParseDaysAgo(camAge);
}
else result += 'unknown days ago';
result += '<br>Speed data: ';
result += uroGetLocalisedSpeedString(ureq.attributes.speed);
result += '<hr><ul>';
if(uroIsCamOnWatchList(uroFID) != -1)
{
result += '<li><a href="#" id="_updatewatchlist">Update watchlist entry</a>';
result += '<li><a href="#" id="_removefromwatchlist">Remove from watchlist</a>';
objHasUpdateWatchLink = true;
objHasRemoveWatchLink = true;
}
else
{
result += '<li><a href="#" id="_addtowatchlist">Add to watchlist</a>';
objHasAddWatchLink = true;
}
if(ureq.attributes.permissions !== 0)
{
result += '<li><a href="#" id="_deleteobject">Delete Camera</a>';
objHasDeleteLink = true;
}
result += '</ul>';
}
break;
}
}
}
if((newPopupType !== null) && (uroPopupDwellTimer === 0) && (uroPopupSuppressed === false))
{
if((uroFID != uroShownFID) || (newPopupType != uroShownPopupType))
{
if(uroFID != uroShownFID) uroAddLog('FID mismatch, show popup: '+uroFID+'/'+uroShownFID);
else uroAddLog('Popup type mismatch: '+newPopupType+'/'+uroShownPopupType);
uroShownFID = uroFID;
uroShownPopupType = newPopupType;
uroPopupShown = false;
}
if(uroPopupShown === false)
{
uroAddLog('display popup at '+uroPopupX+','+uroPopupY);
uroPopupShown = true;
uroDiv.style.height = "auto";
uroDiv.style.width = "auto";
uroDiv.innerHTML = result;
if((uroFID != -1) && (objHasIgnoreLink === true))
{
uroAddEventListener('_addtoignore','click', uroAddToIgnoreList, true);
}
if(objHasDeleteLink === true)
{
uroAddEventListener('_deleteobject','click', uroDeleteObject, true);
}
if(objHasRemoveWatchLink === true)
{
uroAddEventListener('_removefromwatchlist','click', uroRemoveCamFromWatchList, true);
}
if(objHasAddWatchLink === true)
{
uroAddEventListener('_addtowatchlist','click', uroAddCamToWatchList, true);
}
if(objHasUpdateWatchLink === true)
{
uroAddEventListener('_updatewatchlist','click', uroUpdateCamWatchList, true);
}
if(objHasOpenInNewTabLink === true)
{
uroAddEventListener('_openInNewTab','mouseup', uroOpenNewTab, true);
}
if(objHasRecentreSessionLink === true)
{
if(isUR) uroAddEventListener('_recentreSession', 'click', uroRecentreSessionOnUR, true);
else if((isProblem)||(isTurnProb)) uroAddEventListener('_recentreSession', 'click', uroRecentreSessionOnMP, true);
else if(isPlaceUpdate) uroAddEventListener('_recentreSession', 'click', uroRecentreSessionOnPUR, true);
else if(isVenue) uroAddEventListener('_recentreSession', 'click', uroRecentreSessionOnVenueNavPoint, true);
}
if(objHasCloneLink === true)
{
uroAddEventListener('_cloneRP', 'click', uroCloneResidentialPlace, true);
}
if(newPopupType == 'turn_restriction')
{
uroAddEventListener('_editTBR','click', uroEditTBR, true);
}
// restrict the popup width to be no wider than just under half the window width to avoid it
// completely overlapping the marker it's associated with - by keeping it to just below half
// the window width we guarantee that it'll fit either to the left or the right of the marker
// no matter how far across the screen the marker is located...
rw = parseInt(uroDiv.clientWidth);
if(rw > (window.innerWidth * 0.45))
{
rw = (window.innerWidth * 0.45);
uroDiv.style.width = rw+'px';
}
// get the div height after any adjustment of the width above, to account for whatever content
// reflow may have occurred as a result of reducing the width...
rh = parseInt(uroDiv.clientHeight);
if((uroPopupX + rw) > window.innerWidth)
{
// where the popup would be off the right hand side of the screen, move it completely over to the
// other side of the mouse pointer
uroPopupX -= (rw + 20);
if(uroPopupX < 0) uroPopupX = 0;
}
if((uroPopupY + rh) > window.innerHeight)
{
// where the popup would be off the bottom of the screen, shift it up just far enough to be
// fully visible
uroPopupY -= (((uroPopupY + rh) - window.innerHeight) + 30);
if(uroPopupY < 0) uroPopupY = 0;
}
uroDiv.style.top = uroPopupY+'px';
uroDiv.style.left = uroPopupX+'px';
uroDiv.style.visibility = 'visible';
}
uroPopupTimer = -1;
}
else if((newPopupType === null) && (uroPopupDwellTimer !== 0) && (uroPopupShown === true))
{
uroHidePopup();
}
else
{
if((uroPopupTimer == -1) && (uroFID != uroShownFID))
{
uroPopupTimer = uroGetElmValue('_inputPopupEntryTimeout');
}
}
}
function uroExclusiveCB()
{
var cbChecked = uroGetCBChecked(this.id);
if(cbChecked === true)
{
var pairedList = this.attributes.pairedWith.value.split(',');
for(var i=0; i<pairedList.length; i++)
{
uroSetCBChecked(pairedList[i], false);
}
}
}
function uroGetAMs(e)
{
if(uroMTEMode) return;
if(!uroFilterPreamble) return;
if(!uroInitialised) return;
var amList = '';
if(W.map.managedAreasLayer.getVisibility() === true)
{
var mouseX = e.pageX - document.getElementById('map').getBoundingClientRect().left;
var mouseY = e.pageY - document.getElementById('map').getBoundingClientRect().top - document.getElementById('toolbar').clientHeight;
var mousePixel = new OL.Pixel(mouseX, mouseY);
var mousePoint = W.map.getLonLatFromPixel(mousePixel).toPoint();
for(var amObj in W.model.managedAreas.objects)
{
if(W.model.managedAreas.objects[amObj].geometry.containsPoint(mousePoint))
{
if(amList !== '') amList += ', ';
amList += uroGetUserNameAndRank(W.model.managedAreas.objects[amObj].userID);
}
}
if(amList === '')
{
amList = 'none';
}
amList = "<b>Area Managers:</b> "+amList;
}
document.getElementById("uroAMList").innerHTML = amList;
}
function uroMouseDown()
{
uroMouseIsDown = true;
}
function uroMouseUp()
{
uroMouseIsDown = false;
}
function uroMouseOut()
{
//console.debug('Elvis has left the building...');
}
function uroUREvent_onObjectsChanged()
{
}
function uroUREvent_onObjectsAdded()
{
if(uroGetCBChecked('_cbURResolverIDFilter') === true)
{
uroUpdateResolverList();
}
uroFilterURs();
}
function uroUREvent_onObjectsRemoved()
{
}
function uroGetSelectedURCommentCount()
{
if(W.model.updateRequestSessions.objects[uroSelectedURID] != null)
{
var cachedCommentCount = W.model.updateRequestSessions.objects[uroSelectedURID].comments.length;
uroAddLog(uroSelectedURID+':'+cachedCommentCount+' '+uroExpectedCommentCount);
// if there aren't the same number of cached comments as there are comments in the UR dialog list, initiate
// a refresh of the comment data...
if(cachedCommentCount != uroExpectedCommentCount)
{
if(uroPendingCommentDataRefresh === true)
{
if(cachedCommentCount > 0)
{
uroCachedLastCommentID = W.model.updateRequestSessions.objects[uroSelectedURID].comments[cachedCommentCount-1].id;
}
else
{
uroCachedLastCommentID = null;
}
uroAddLog('updateRequestSessions refresh required for UR '+uroSelectedURID);
if(uroCachedLastCommentID !== null)
{
uroAddLog('last comment ID for this UR is '+uroCachedLastCommentID);
}
else
{
uroAddLog('first comment for this UR, no previous comment to ID');
}
var idList = [];
idList.push(uroSelectedURID);
// need to delete the existing cache object first, as .get() is only capable of creating new objects,
// it doesn't seem able to update an existing object with new data
W.model.updateRequestSessions.remove(W.model.updateRequestSessions.objects[uroSelectedURID]);
W.model.updateRequestSessions.get(idList);
// the call to .get() initiates a XMLHttpRequest for the data, so we now need to switch modes - the
// refresh process has started so we're no longer pending, but we are now waiting for the XMLHttpRequest
// to return something...
uroPendingCommentDataRefresh = false;
uroWaitingCommentDataRefresh = true;
}
else
{
if(cachedCommentCount > 0)
{
var currentLastCommentID = W.model.updateRequestSessions.objects[uroSelectedURID].comments[cachedCommentCount-1].id;
if(currentLastCommentID == uroCachedLastCommentID)
{
// most recent comment loaded for this UR is the same one that was present at the start of this
// refresh process, so kick back into pending mode so we can retry the .get()...
uroAddLog('latest comment ID still the same, reverting to pending mode...');
uroPendingCommentDataRefresh = true;
}
else
{
// something may have gone awry here - the most recent comment loaded for this UR doesn't have the
// same ID as the one present at the start of the refresh process, yet the comment counts still don't
// match up, which suggests either a comment got lost along the way or someone else has commented on
// the same UR at almost the same time. To get out of the loop this would create, assume that a
// mismatch in the IDs means the .get() has completed successfully no matter what the new comment
// count is, and take this new count to be the count we were expecting all along...
uroAddLog('latest comment ID different, but expected count not correct...');
uroExpectedCommentCount = cachedCommentCount;
}
}
else
{
uroAddLog('first comment on this UR not received yet, reverting to pending mode...');
uroPendingCommentDataRefresh = true;
}
}
}
else
{
// if the WME session is loaded with a UR already selected, such that WME has opened the UR dialog as part
// of the session startup process, adding new comments to the UR cause the cached data to be updated immediately.
// This prevents URO+ from switching into waiting mode in the above block of code, so we have to instead do
// it here by comparing the cached count against the expected count following the Send click event.
if(cachedCommentCount >= uroExpectedCommentCount)
{
uroPendingCommentDataRefresh = false;
uroWaitingCommentDataRefresh = true;
uroExpectedCommentCount = null;
}
// once the cached data has been updated, refilter the URs so that the new comment count is taken into account
// immediately for filtering and display purposes
if(uroWaitingCommentDataRefresh === true)
{
uroWaitingCommentDataRefresh = false;
uroFilterURs();
uroAddLog('refresh complete');
}
}
}
}
function uroAddedComment()
{
// when the user clicks the Send button to submit a new UR comment, this event handler fires before the new comment is
// posted to the server and thus also before the comment list gets updated in the UR dialog. So we take the current
// comment count and, if the new comment edit box isn't empty, increment it by 1 to get the expected count. Then we
// set the pending flag true to initiate a session refresh on the next 100ms tick
uroExpectedCommentCount = W.map.panelRegion.currentView.conversationView.viewModel.attributes.commentCount;
if(document.getElementsByClassName('new-comment-text')[0].value !== '')
{
uroExpectedCommentCount++;
uroAddLog('new comment added to UR '+uroSelectedURID+', cache refresh required...');
uroPendingCommentDataRefresh = true;
}
else
{
uroPendingCommentDataRefresh = false;
}
}
function uroInhibitNextUpdateRequestButton(e)
{
var doClick = true;
e.stopPropagation();
if(document.getElementsByClassName('form-control new-comment-text').length > 0)
{
if(document.getElementsByClassName('form-control new-comment-text')[0].textLength > 0)
{
doClick = (confirm('Comment not sent, close report panel anyway?'));
}
}
if(doClick)
{
document.getElementsByClassName('close-panel')[0].click();
}
}
function uroAddLZ(valueToPad, newLength)
{
var padString = '';
for(var i=0; i<newLength; i++)
{
padString += '0';
}
padString += valueToPad.toString();
return padString.slice(-newLength);
}
function uroIncrementClosureDate(oldDate, incByDays)
{
var dateBits = oldDate.split('-');
var year = parseInt(dateBits[0]);
var month = parseInt(dateBits[1])-1;
var date = parseInt(dateBits[2])+1;
var incrementedDate = new Date(year, month, date);
return (uroAddLZ(incrementedDate.getFullYear(),4) + '-' + uroAddLZ(incrementedDate.getMonth()+1,2) + '-' + uroAddLZ(incrementedDate.getDate(),2));
}
function uroGetElementProperty(elmName, elmOffset, elmProperty)
{
var retval = null;
if(document.getElementsByName(elmName).length !== 0)
{
retval = document.getElementsByName(elmName)[elmOffset][elmProperty];
}
return retval;
}
// Residential Place Cloning
//{
var uroCRPStreetID;
var uroCRPHouseNumber;
function uroCompleteRPClone()
{
// as with closure cloning, the place details edit form requires us to push the new value into the relevant
// edit field and then generate a change event on that field, otherwise WME doesn't bother reading the value...
// street name
var streetObj = W.model.streets.get(uroCRPStreetID);
if(streetObj !== undefined)
{
document.getElementsByClassName('street-name')[0].value = streetObj.name;
document.getElementsByClassName('street-name')[0].dispatchEvent(new Event('change', { 'bubbles': true }));
// city name
var cityObj = W.model.cities.get(streetObj.cityID);
if(cityObj !== undefined)
{
document.getElementsByClassName('city-name')[0].value = cityObj.name;
document.getElementsByClassName('city-name')[0].dispatchEvent(new Event('change', { 'bubbles': true }));
// county
document.getElementsByClassName('state-id')[0].value = cityObj.stateID;
document.getElementsByClassName('state-id')[0].dispatchEvent(new Event('change', { 'bubbles': true }));
// country
document.getElementsByClassName('country-id')[0].value = cityObj.countryID;
document.getElementsByClassName('country-id')[0].dispatchEvent(new Event('change', { 'bubbles': true }));
}
}
// house number
document.getElementsByClassName('house-number')[0].value = parseInt(uroCRPHouseNumber);
document.getElementsByClassName('house-number')[0].dispatchEvent(new Event('change', { 'bubbles': true }));
// now wait for the user to confirm everything and click Apply...
}
function uroConvertToRP()
{
// panel isn't open yet, which means the user either hasn't clicked yet or WME is still processing the
// placement of the venue, so wait a while and then check again...
if(document.getElementById('edit-panel').getElementsByClassName('landmark').length === 0)
{
setTimeout(uroConvertToRP, 100);
return;
}
// panel is open, so move to the next step of the cloning procedure by converting the newly created
// place to residential by generating a click event on the "convert to residential" link...
document.getElementsByClassName("toggle-residential")[0].click();
// and then click on the address edit icon...
document.getElementsByClassName('waze-icon-edit')[0].click();
// now click on the "none" checkbox for the street name edit field so we can enter the street name
document.getElementById('empty-street').click();
// WME automatically clears the checkbox associated with the city name edit field if we set the street
// name to be one that has a city associated with it, which is nice :-)
// the click event seems to take a while to execute, and if we call dispatchEvent on the edit field whilst
// it's still tagged as disabled then it gets ignored, causing the value in that field to be dropped when
// we apply the changes to the place. Trying to programatically detect when the field has been activated
// doesn't seem to be reliable, however a fixed delay of 1s seems to work nicely
setTimeout(uroCompleteRPClone, 1000);
}
function uroCloneResidentialPlace()
{
// trying to clone a RPP when one is already selected causes the selected one to be changed back to
// a non-residential, as uroConvertToRP() thinks the user has already clicked to place the new RPP...
if(document.getElementById('edit-panel').getElementsByClassName('landmark').length === 0)
{
var venueObj = W.model.venues.objects[uroFID];
if(venueObj !== undefined)
{
// copy address from highlighted residential place
uroCRPHouseNumber = venueObj.attributes.houseNumber;
uroCRPStreetID = venueObj.attributes.streetID;
// generate a click event on the first new point venue entry in the menu in order to generate a
// new point venue object that we can manipulate...
document.getElementsByClassName("drawing-control main-control point")[0].click();
// now wait for the user to click on the map to place the new point venue
uroConvertToRP();
}
}
}
//}
// Closure Cloning
//{
var uroConfirmClosureDelete = true;
var uroClosuresToDelete = 0;
function uroCloneClosure()
{
var closureOffset = parseInt(this.id.split('-')[1]);
// grab the current closure details from the UI...
document.getElementsByClassName('closure-item')[closureOffset].children[0].children[0].children[1].click();
var cLocation = uroGetElementProperty('closure_location', 0, 'value');
var cReason = uroGetElementProperty('closure_reason', 0, 'value');
var cEvent = uroGetElementProperty('closure_mteId', 0, 'selectedIndex');
var cDirection = uroGetElementProperty('closure_direction', 0, 'selectedIndex');
var cHasStartDate = uroGetElementProperty('closure_hasStartDate', 0, 'checked');
var cStartDate = uroGetElementProperty('closure_startDate', 0, 'value');
var cStartTime = uroGetElementProperty('closure_startTime', 0, 'value');
var cEndDate = uroGetElementProperty('closure_endDate', 0, 'value');
var cEndTime = uroGetElementProperty('closure_endTime', 0, 'value');
var cIgnoreTraffic = uroGetElementProperty('closure_permanent', 0, 'checked');
document.getElementsByClassName('closures')[0].getElementsByClassName('cancel-button')[0].click();
// auto-increment the start and end dates...
cStartDate = uroIncrementClosureDate(cStartDate,1);
cEndDate = uroIncrementClosureDate(cEndDate,1);
// now open the add closure UI and populate it with the values we've just grabbed...
document.getElementsByClassName('add-closure-button')[0].click();
// need to generate a change event on each of the form fields, because WME appears to be silently populating some hidden
// closure object with the details as they're entered manually, and if we just set the form values without then forcing
// the change event as well then WME will end up using its default values instead of the ones we've so lovingly copied...
if(cLocation !== null)
{
document.getElementsByName('closure_location')[0].value = cLocation;
document.getElementsByName('closure_location')[0].dispatchEvent(new Event('change', { 'bubbles': true }));
}
if(cReason !== null)
{
document.getElementsByName('closure_reason')[0].value = cReason;
document.getElementsByName('closure_reason')[0].dispatchEvent(new Event('change', { 'bubbles': true }));
}
if(cEvent !== null)
{
document.getElementsByName('closure_mteId')[0].selectedIndex = cEvent;
document.getElementsByName('closure_mteId')[0].dispatchEvent(new Event('change', { 'bubbles': true }));
}
if(cDirection !== null)
{
document.getElementsByName('closure_direction')[0].selectedIndex = cDirection;
document.getElementsByName('closure_direction')[0].dispatchEvent(new Event('change', { 'bubbles': true }));
}
if(cHasStartDate !== null)
{
document.getElementsByName('closure_hasStartDate')[0].checked = cHasStartDate;
document.getElementsByName('closure_hasStartDate')[0].dispatchEvent(new Event('change', { 'bubbles': true }));
}
if(cStartDate !== null)
{
document.getElementsByName('closure_startDate')[0].value = cStartDate;
document.getElementsByName('closure_startDate')[0].dispatchEvent(new Event('change', { 'bubbles': true }));
}
if(cStartTime !== null)
{
document.getElementsByName('closure_startTime')[0].value = cStartTime;
document.getElementsByName('closure_startTime')[0].dispatchEvent(new Event('change', { 'bubbles': true }));
}
if(cEndDate !== null)
{
document.getElementsByName('closure_endDate')[0].value = cEndDate;
document.getElementsByName('closure_endDate')[0].dispatchEvent(new Event('change', { 'bubbles': true }));
}
if(cEndTime !== null)
{
document.getElementsByName('closure_endTime')[0].value = cEndTime;
document.getElementsByName('closure_endTime')[0].dispatchEvent(new Event('change', { 'bubbles': true }));
}
if(cIgnoreTraffic !== null)
{
document.getElementsByName('closure_permanent')[0].checked = cIgnoreTraffic;
document.getElementsByName('closure_permanent')[0].dispatchEvent(new Event('change', { 'bubbles': true }));
}
}
function uroDeleteNextClosureOnList()
{
var nClosures = document.getElementsByClassName('closure-item').length;
if(nClosures > 0)
{
if (nClosures != uroClosuresToDelete)
{
uroClosuresToDelete = nClosures;
document.getElementsByClassName('closure-item')[0].getElementsByClassName('delete')[0].click();
}
setTimeout(uroDeleteNextClosureOnList,100);
}
else
{
uroConfirmClosureDelete = true;
}
}
function uroDeleteAllClosures()
{
uroConfirmClosureDelete = true;
if(window.confirm(I18n.lookup("closures.delete_confirm_no_reason")+' ('+I18n.lookup("closures.apply_to_all")+')'))
{
uroConfirmClosureDelete = false;
var nClosures = document.getElementsByClassName('closure-item').length;
if(nClosures > 0)
{
uroClosuresToDelete = -1;
uroDeleteNextClosureOnList();
}
else
{
uroConfirmClosureDelete = true;
}
}
}
//}
// Feed Filtering
//{
function uroToggleFFCtrls()
{
if(uroShowFeedFilter === false)
{
uroShowFeedFilter = true;
document.getElementById('_uroFFCtrlVisibility').className = "fa fa-minus-square-o";
document.getElementById('uroFFCtrls').style.display = "block";
}
else
{
uroShowFeedFilter = false;
document.getElementById('_uroFFCtrlVisibility').className = "fa fa-plus-square-o";
document.getElementById('uroFFCtrls').style.display = "none";
}
}
function uroAddFeedFilterControls()
{
if(document.getElementById('sidepanel-feed') != null)
{
if(document.getElementById('sidepanel-feed').childNodes[0] != null)
{
var nDiv = document.createElement('div');
var iHTML = '';
nDiv.id = "uroFeedFilter";
iHTML += '<i class="fa fa-plus-square-o" style="cursor:pointer;font-size:14px;" id="_uroFFCtrlVisibility"> </i><b>Feed Filter Controls</b><br>';
iHTML += '<div id="uroFFCtrls">';
iHTML += '<b>Filter feed by listing type:</b><br>';
iHTML += '<input type="checkbox" id="_cbFeedFilter_TypeUR" />UR<br>';
iHTML += '<input type="checkbox" id="_cbFeedFilter_TypePUR" />PUR<br>';
iHTML += '<input type="checkbox" id="_cbFeedFilter_TypePM" />PM notifications<br>';
iHTML += '<br><b>Filter feed by listing reason:</b><br>';
iHTML += '<input type="checkbox" id="_cbFeedFilter_MotCBSBR" />'+I18n.lookup("feed.issues.motivations.CAN_BE_SOLVED_BY_RANK")+'<br>';
iHTML += '<input type="checkbox" id="_cbFeedFilter_MotCTF" />'+I18n.lookup("feed.issues.motivations.CLOSE_TO_FAVORITES")+'<br>';
iHTML += '<input type="checkbox" id="_cbFeedFilter_MotIA" />'+I18n.lookup("feed.issues.motivations.ISSUE_AGE")+'<br>';
iHTML += '<input type="checkbox" id="_cbFeedFilter_MotIR" />'+I18n.lookup("feed.issues.motivations.ISSUE_REOPENED")+'<br>';
iHTML += '<input type="checkbox" id="_cbFeedFilter_MotND" />'+I18n.lookup("feed.issues.motivations.NEAR_DRIVES")+'<br>';
iHTML += '<input type="checkbox" id="_cbFeedFilter_MotRBU" />'+I18n.lookup("feed.issues.motivations.REPORTED_BY_USER")+'<br>';
iHTML += '<input type="checkbox" id="_cbFeedFilter_MotUFI" />'+I18n.lookup("feed.issues.motivations.USER_FOLLOWS_ISSUE")+'<br>';
iHTML += '<input type="checkbox" id="_cbFeedFilter_MotUFILC" />'+I18n.lookup("feed.issues.motivations.USER_FOLLOWS_ISSUE_LAST_COMMENT")+'<br>';
iHTML += '<input type="checkbox" id="_cbFeedFilter_MotNone" />None of the above...<br>';
iHTML += '<br><input type="checkbox" id="_cbFeedFilter_Invert" />Invert behaviour of above filters<br>';
iHTML += '<br><b>Filter feed by keyword/phrase:</b><br>';
iHTML += '<input type="checkbox" id="_cbFeedFilter_HideKeyword" pairedWith="_cbFeedFilter_ShowKeyword" />Hide or ';
iHTML += '<input type="checkbox" id="_cbFeedFilter_ShowKeyword" pairedWith="_cbFeedFilter_HideKeyword" />show if keyword is present<br>';
iHTML += '<input type="text" id="_cbFeedFilter_Keyword" />';
iHTML += '</div>';
nDiv.innerHTML = iHTML;
document.getElementById('sidepanel-feed').insertBefore(nDiv,document.getElementById('sidepanel-feed').childNodes[0]);
uroAddEventListener('_uroFFCtrlVisibility','click',uroToggleFFCtrls, true);
uroShowFeedFilter = true;
uroToggleFFCtrls();
}
}
}
function uroTSTFeedFilter()
{
var feedEntries = document.getElementsByClassName('feed-item');
var feedLength = feedEntries.length;
if(feedLength === 0) return;
if(document.getElementById('uroFeedFilter') === null) return;
var hideFI;
var iHTML;
var fClass;
var ffKeyword = uroGetElmValue('_cbFeedFilter_Keyword');
var ffShowKW = uroGetCBChecked('_cbFeedFilter_ShowKeyword');
var ffHideKW = uroGetCBChecked('_cbFeedFilter_HideKeyword');
var kwPresent;
var transMotCBSBR = I18n.lookup("feed.issues.motivations.CAN_BE_SOLVED_BY_RANK");
var transMotCTF = I18n.lookup("feed.issues.motivations.CLOSE_TO_FAVORITES");
var transMotIA = I18n.lookup("feed.issues.motivations.ISSUE_AGE");
var transMotIR = I18n.lookup("feed.issues.motivations.ISSUE_REOPENED");
var transMotND = I18n.lookup("feed.issues.motivations.NEAR_DRIVES");
var transMotRBU = I18n.lookup("feed.issues.motivations.REPORTED_BY_USER");
var transMotUFI = I18n.lookup("feed.issues.motivations.USER_FOLLOWS_ISSUE");
var transMotUFILC = I18n.lookup("feed.issues.motivations.USER_FOLLOWS_ISSUE_LAST_COMMENT");
var isChecked_cbFeedFilter_TypeUR = uroGetCBChecked('_cbFeedFilter_TypeUR');
var isChecked_cbFeedFilter_TypePUR = uroGetCBChecked('_cbFeedFilter_TypePUR');
var isChecked_cbFeedFilter_TypePM = uroGetCBChecked('_cbFeedFilter_TypePM');
var isChecked_cbFeedFilter_MotCBSBR = uroGetCBChecked('_cbFeedFilter_MotCBSBR');
var isChecked_cbFeedFilter_MotCTF = uroGetCBChecked('_cbFeedFilter_MotCTF');
var isChecked_cbFeedFilter_MotIA = uroGetCBChecked('_cbFeedFilter_MotIA');
var isChecked_cbFeedFilter_MotIR = uroGetCBChecked('_cbFeedFilter_MotIR');
var isChecked_cbFeedFilter_MotND = uroGetCBChecked('_cbFeedFilter_MotND');
var isChecked_cbFeedFilter_MotRBU = uroGetCBChecked('_cbFeedFilter_MotRBU');
var isChecked_cbFeedFilter_MotUFI = uroGetCBChecked('_cbFeedFilter_MotUFI');
var isChecked_cbFeedFilter_MotUFILC = uroGetCBChecked('_cbFeedFilter_MotUFILC');
var isChecked_cbFeedFilter_MotNone = uroGetCBChecked('_cbFeedFilter_MotNone');
var isChecked_cbFeedFilter_Invert = uroGetCBChecked('_cbFeedFilter_Invert');
for(var i=0; i<feedLength; i++)
{
hideFI = false;
iHTML = feedEntries[i].innerHTML;
fClass = feedEntries[i].className;
if(isChecked_cbFeedFilter_TypeUR)
{
hideFI |= (fClass.indexOf('feed-issue-ur') != -1);
}
if(isChecked_cbFeedFilter_TypePUR)
{
hideFI |= (fClass.indexOf('feed-issue-pu') != -1);
}
if(isChecked_cbFeedFilter_TypePM)
{
hideFI |= (fClass.indexOf('feed-notification-pm') != -1);
}
if(isChecked_cbFeedFilter_MotCBSBR)
{
hideFI |= (iHTML.indexOf(transMotCBSBR) != -1);
}
if(isChecked_cbFeedFilter_MotCTF)
{
hideFI |= (iHTML.indexOf(transMotCTF) != -1);
}
if(isChecked_cbFeedFilter_MotIA)
{
hideFI |= (iHTML.indexOf(transMotIA) != -1);
}
if(isChecked_cbFeedFilter_MotIR)
{
hideFI |= (iHTML.indexOf(transMotIR) != -1);
}
if(isChecked_cbFeedFilter_MotND)
{
hideFI |= (iHTML.indexOf(transMotND) != -1);
}
if(isChecked_cbFeedFilter_MotRBU)
{
hideFI |= (iHTML.indexOf(transMotRBU) != -1);
}
if(isChecked_cbFeedFilter_MotUFI)
{
hideFI |= (iHTML.indexOf(transMotUFI) != -1);
}
if(isChecked_cbFeedFilter_MotUFILC)
{
hideFI |= (iHTML.indexOf(transMotUFILC) != -1);
}
if(isChecked_cbFeedFilter_MotNone)
{
hideFI |= (iHTML.indexOf('motivation') == -1);
}
if(isChecked_cbFeedFilter_Invert)
{
hideFI = !hideFI;
}
if((ffShowKW) || (ffHideKW))
{
kwPresent = (iHTML.indexOf(ffKeyword) != -1);
hideFI |= (kwPresent & ffHideKW);
hideFI |= ((!kwPresent) & ffShowKW);
}
if(hideFI) feedEntries[i].style.display = 'none';
else feedEntries[i].style.display = 'block';
}
}
//}
function uroFinalizeListenerSetup()
{
uroFinalisingListenerSetup = true;
// filter markers when the marker objects are modified (this happens whenever WME needs to load fresh marker data
// due to having panned/zoomed the map beyond the extents of the previously loaded data)
W.model.mapUpdateRequests.on("objectschanged", uroFilterURs_onObjectsChanged);
W.model.mapUpdateRequests.on("objectsadded", uroFilterURs_onObjectsAdded);
W.model.mapUpdateRequests.on("objectsremoved", uroFilterURs_onObjectsRemoved);
W.model.updateRequestSessions.on("objectschanged", uroUREvent_onObjectsChanged);
W.model.updateRequestSessions.on("objectsadded", uroUREvent_onObjectsAdded);
W.model.updateRequestSessions.on("objectsremoved", uroUREvent_onObjectsRemoved);
W.model.cameras.on("objectschanged", uroFilterCameras);
W.model.cameras.on("objectsadded", uroFilterCameras);
W.model.cameras.on("objectsremoved", uroFilterCameras);
W.model.problems.on("objectschanged", uroFilterProblems);
W.model.problems.on("objectsadded", uroFilterProblems);
W.model.problems.on("objectsremoved", uroFilterProblems);
W.model.venues.on("objectschanged", uroFilterPlaces);
W.model.venues.on("objectsadded", uroFilterPlaces);
W.model.venues.on("objectsremoved", uroFilterPlaces);
var userTabs = document.getElementById(uroUserTabId);
var tabContent = null;
var navTabs = userTabs.getElementsByClassName('nav-tabs')[0];
tabContent = document.getElementById('user-info').getElementsByClassName('tab-content')[0];
var newtabUR = document.createElement('li');
newtabUR.innerHTML = '<a href="#sidepanel-uroverview" data-toggle="tab">URO+</a>';
navTabs.appendChild(newtabUR);
uroControls.id = "sidepanel-uroverview";
uroControls.className = "tab-pane";
tabContent.appendChild(uroControls);
uroAddEventListener('_btnUndoLastHide',"click", uroRemoveLastAddedIgnore, true);
uroAddEventListener('_btnClearSessionHides',"click", uroRemoveAllIgnores, true);
uroEnableIgnoreListControls();
uroAddEventListener('_btnClearCamWatchList',"click", uroClearCamWatchList, true);
uroAddEventListener('_btnSettingsToText',"click", uroSettingsToText, true);
uroAddEventListener('_btnTextToSettings',"click", uroTextToSettings, true);
uroAddEventListener('_btnResetSettings',"click", uroDefaultSettings, true);
uroAddEventListener('_btnClearSettingsText',"click", uroClearSettingsText, true);
uroAddEventListener('_cbMasterEnable',"click", uroFilterItems_MasterEnableClick, true);
/*
uroAddEventListener('_btnDebugToScreen',"click", uroDumpDebug, true);
*/
uroAddEventListener('uroDiv',"dblclick",uroSuppressPopup,true);
uroAddEventListener('_selectCameraUserID',"change", uroCamEditorSelected, true);
uroAddEventListener('uroAlertTickBtn','click',uroCloseAlertBoxWithTick,true);
uroAddEventListener('uroAlertCrossBtn','click',uroCloseAlertBoxWithCross,true);
uroSetOnClick("_linkSelectUserRequests",uroShowURTab);
uroSetOnClick("_linkSelectMapProblems",uroShowMPTab);
uroSetOnClick("_linkSelectPlaces",uroShowPlacesTab);
uroSetOnClick("_linkSelectCameras",uroShowCameraTab);
uroSetOnClick("_linkSelectMisc",uroShowMiscTab);
uroSetOnClick("_linkSelectOWL",uroShowOWLTab);
for(var idx=0;idx<W.Config.venues.categories.length;idx++)
{
uroSetOnClick('_uroPlacesGroupState-'+idx,uroPlacesGroupCollapseExpand);
}
uroAddLog('finalise onload');
uroLoadSettings();
uroNewLookCheckDetailsRequest();
if(uroGetCBChecked('_cbEnableDTE'))
{
if(dteControlsIdx != -1)
{
dteSetNewTabLength();
}
else
{
uroAddLog('ERROR - archive panel not found!');
uroSetStyleDisplay(uroUserTabId,'');
}
}
// filter markers as and when the map is moved
W.map.events.register("moveend", null, uroFilterItems);
W.map.events.register("mousemove", null, uroGetAMs);
W.map.events.register("mousemove", null, uroNewLookHighlightedItemsCheck);
W.map.events.registerPriority("mousedown", null, uroMouseDown);
// trap mousedown on Streetview marker drag
document.getElementsByClassName('street-view-control')[0].onmousedown = uroMouseDown;
W.map.events.register("mouseup", null, uroMouseUp);
W.map.events.register("mouseout", null, uroMouseOut);
uroSetStyles(uroCtrlURs);
uroSetStyles(uroCtrlMPs);
uroSetStyles(uroCtrlPlaces);
uroSetStyles(uroCtrlCameras);
uroSetStyles(uroCtrlMisc);
uroSetStyles(uroOWL);
uroAddFeedFilterControls();
uroShowURTab();
uroUserID = W.loginManager.getLoggedInUser().id;
uroFilterItems();
uroShowDebugOutput = uroPersistentDebugOutput;
var dbgMode = "none";
if(uroShowDebugOutput)
{
dbgMode = "inline";
}
document.getElementById('_uroDebugMode').style.display = dbgMode;
uroAddEventListener('_uroVersion',"click", uroToggleDebug, true);
// add exclusiveCB click handlers to all checkboxes with a pairedWith attribute
var cbList = document.getElementsByTagName('input');
for (var optIdx=0;optIdx<cbList.length;optIdx++)
{
if((cbList[optIdx].id.indexOf('_cb') === 0) && (cbList[optIdx].attributes.pairedWith != null))
{
uroSetOnClick(cbList[optIdx].id,uroExclusiveCB);
}
}
uroSetupListeners = false;
uroInitialised = true;
}
function uroTSTPopupHandler()
{
if(document.getElementsByClassName('panel')[0] === undefined)
{
uroHidePopupOnPanelOpen = true;
}
if(uroPopupShown === true)
{
var hidePopup = false;
if(document.getElementsByClassName('dropdown action open').length > 0.5)
{
hidePopup = true;
}
else
{
if(window.getComputedStyle(document.getElementById('layer-switcher-list').parentNode).getPropertyValue('opacity') > 0.5)
{
hidePopup = true;
}
else
{
if(window.getComputedStyle(document.getElementsByClassName('toolbar-group-drawing')[0].childNodes[0]).getPropertyValue('opacity')> 0.5)
{
hidePopup = true;
}
else
{
if(window.getComputedStyle(document.getElementsByClassName('toolbar-group-venues')[0].childNodes[0]).getPropertyValue('opacity') > 0.5)
{
hidePopup = true;
}
}
}
}
if(document.getElementsByClassName('panel')[0] != null)
{
if(uroHidePopupOnPanelOpen === true)
{
hidePopup = true;
uroHidePopupOnPanelOpen = false;
}
}
if(hidePopup === true)
{
uroHidePopup();
}
}
if((uroAreaNameHoverObj !== null) && (uroAreaNameHoverTime != -1) && (uroAreaNameOverlayShown === false))
{
if(++uroAreaNameHoverTime > 5)
{
uroAreaNameOverlaySetup();
}
}
uroReplaceAreaNames(false);
if(uroPopupTimer > 0)
{
if(uroMouseInPopup === false)
{
uroPopupTimer--;
}
}
if(uroPopupTimer === 0)
{
uroHidePopup();
}
if(uroPopupDwellTimer > 0)
{
uroPopupDwellTimer--;
if(uroPopupDwellTimer === 0)
{
uroNewLookHighlightedItemsCheck('dwellTimeout');
}
}
}
function uroTSTDTEHandler()
{
if(document.getElementsByClassName("archive-panel")[0] === undefined)
{
if(dteClearHighlightsOnPanelClose)
{
dteClearListHighlight();
dteClearHighlightsOnPanelClose = false;
}
}
else
{
if(dteArmClearHighlightsOnPanelClose)
{
dteArmClearHighlightsOnPanelClose = false;
dteClearHighlightsOnPanelClose = true;
}
}
}
function uroTSTNextBtnHandler()
{
// replace the "next xxx" button on UR, MP and PUR editing UIs
if(W.map.panelRegion.hasView() === true)
{
var nurButton = W.map.panelRegion.$el[0].getElementsByClassName('btn btn-block')[0];
if(nurButton != null)
{
var doneString = I18n.lookup('problems.panel.done');
var nextURString = (nurButton.innerHTML.indexOf(I18n.lookup('update_requests.panel.next')) !== -1);
var nextMPString = (nurButton.innerHTML.indexOf(I18n.lookup('problems.panel.next')) !== -1);
var nextPURString = (nurButton.innerHTML.indexOf(I18n.lookup('venues.update_requests.panel.next_venue')) !== -1);
var nextIssueString = (nurButton.innerHTML.indexOf(I18n.lookup('feed.issues.next')) !== -1);
var updateButton = false;
var panelClass = W.map.panelRegion.$el[0].childNodes[0].childNodes[0].className;
var isURorMPPanel = (panelClass.indexOf('problem-edit') !== -1);
var isPURPanel = (panelClass.indexOf('place-update') !== -1);
// "next" button class used for UR and MP edit panel
if(isURorMPPanel === true)
{
// user has enabled UR button mod?
if(uroGetCBChecked('_cbInhibitNURButton') === true)
{
// mod the button if this is a UR/MP panel rather than a PUR panel, and if the "Next update request" or "Next issue"
// text is currently being used on the button - WME uses the former text when a UR is selected directly from the map
// pin, and the latter text when a UR is selected from the feed. However, it *also* uses the latter text for PURs
// selected from the feed, hence the need to test the panel type here as well - having to work around odd
// inconsistencies in WME behaviour, whatever next...
updateButton = updateButton || ((nextURString === true) || (nextIssueString === true));
}
// user has enabled MP button mod?
if(uroGetCBChecked('_cbInhibitNMPButton') === true)
{
// although there's no easy way to determine whether the panel is opened for a UR or MP, since the feed doesn't yet seem
// to provide a means of accessing MPs then we don't yet have to worry about finding the "Next issue" text in a MP panel,
// which makes life slightly easier here...
updateButton = updateButton || (nextMPString === true);
}
}
else if(isPURPanel === true)
{
// "next-venue" class only used for PUR edit panel
if(uroGetCBChecked('_cbInhibitNPURButton') === true)
{
// as noted above, PURs opened from the feed may also use the "Next issue" text, so we need to test for that as well,
// knowing that in order to get this far we've already determined that the user really does want to mod the PUR
// next button *and* that the currently open panel is a PUR panel...
updateButton = updateButton || ((nextPURString === true) || (nextIssueString === true));
}
}
if(updateButton === true)
{
// if we need to change the button label back to "Done", do it here...
nurButton.innerHTML = doneString;
uroAddLog('inhibit Next UR/MP/PUR button');
}
// if updateButton isn't already set here, it suggests the panel is using the native "Done" button...
if(updateButton === false)
{
nurButton = W.map.panelRegion.$el[0].getElementsByClassName('btn btn-block done')[0];
if(nurButton != null)
{
updateButton = true;
}
}
if(updateButton === true)
{
// Add a new click handler to override the native one - this acts both to prevent the normal action of the "Next UR/MP/PUR" button in
// moving to the next UR/MP/PUR, and also allows us to warn about closing the UR panel if there's an unsent comment...
nurButton.addEventListener("click", uroInhibitNextUpdateRequestButton, false);
}
}
}
}
function uroTSTCommentAddedHandler()
{
// test for the opening or closing of the UR editing dialog so we can detect when a new comment is added
var URDialogIsOpen = (document.getElementsByClassName('new-comment-form').length == 1);
if(URDialogIsOpen)
{
var thisSelectedURID = document.getElementsByClassName('permalink')[0].href.split('&mapUpdateRequest=')[1].split('&')[0];
if(thisSelectedURID != uroSelectedURID)
{
// if the user selects a new UR whilst the editing dialog is still open, treat it in the
// same way as if the user had selected that UR with the dialog closed
uroURDialogIsOpen = false;
}
if(uroURDialogIsOpen === false)
{
// user is editing a new UR
uroSelectedURID = thisSelectedURID;
// add our own click event handler to the Send button, so we can do stuff whenever a new comment is added
document.getElementsByClassName('new-comment-form')[0].getElementsByClassName('btn')[0].addEventListener("click", uroAddedComment, false);
uroAddLog('user is editing UR '+uroSelectedURID);
uroExpectedCommentCount = W.model.updateRequestSessions.objects[uroSelectedURID].comments.length;
if((uroHoveredURID !== null) && (uroSelectedURID !== null) && (parseInt(uroHoveredURID) !== parseInt(uroSelectedURID)))
{
if(++uroURReclickAttempts < 3)
{
uroAddLog('DANGER, WILL ROBINSON! You clicked on UR ID '+uroHoveredURID+' but WME has loaded the details for UR ID '+uroSelectedURID+' instead, attempting to fix...');
W.map.updateRequestLayer.markers['+uroHoveredURID+'].icon.$div.click();
return;
}
else
{
uroAddLog('Woe is me, attempting to open UR ID '+uroHoveredURID+' has failed...');
uroShowAlertBox('fa-warning', 'URO+ Warning', 'WME may have opened the details panel for a different UR to the one you selected, proceed with caution', false, "OK", "", null, null);
}
}
uroURReclickAttempts = 0;
}
}
else if(uroURDialogIsOpen === true)
{
// dialog was open and has now been closed
uroSelectedURID = null;
}
uroURDialogIsOpen = URDialogIsOpen;
if(((uroPendingCommentDataRefresh === true) || (uroWaitingCommentDataRefresh === true)) && (uroSelectedURID !== null))
{
uroAddLog('check completion of comment data refresh for UR '+uroSelectedURID+' ('+uroPendingCommentDataRefresh+','+uroWaitingCommentDataRefresh+')');
uroGetSelectedURCommentCount();
}
}
function uroTSTOWLHandler()
{
/*
var selectedTotal = W.selectionManager.selectedItems.length;
if((selectedTotal > 0) && (document.getElementById('_uroDivOWLBtns') === null))
{
var selectedClass = W.selectionManager.selectedItems[0].model.CLASS_NAME;
var displayAddToOWLBtn = false;
var displayUpdateOWLBtn = false;
var displayRemoveFromOWLBtn = false;
var selectedSegments = false;
var selectedLandmarks = false;
var fid;
var loop;
// WME only seems to allow multi-object selections for segments, so testing the class of the first object in the
// selection list tells us the class of any other objects in the list too...
if(selectedClass == "Waze.Feature.Vector.Segment")
{
selectedSegments = true;
for(loop=0; loop<selectedTotal; loop++)
{
fid = W.selectionManager.selectedItems[loop].model.attributes.id;
var segIdx = uroIsSegOnWatchList(fid);
if(segIdx == -1)
{
displayAddToOWLBtn = true;
}
else
{
if(uroSegDataChanged(segIdx))
{
displayUpdateOWLBtn = true;
}
displayRemoveFromOWLBtn = true;
}
}
}
else if(selectedClass == "Waze.Feature.Vector.Landmark")
{
selectedLandmarks = true;
for(loop=0; loop<selectedTotal; loop++)
{
fid = W.selectionManager.selectedItems[loop].model.attributes.id;
var placeIdx = uroIsPlaceOnWatchList(fid);
if(placeIdx == -1)
{
displayAddToOWLBtn = true;
}
else
{
if(uroPlaceDataChanged(placeIdx))
{
displayUpdateOWLBtn = true;
}
displayRemoveFromOWLBtn = true;
}
}
}
var btnHTML = '<div id="_uroDivOWLBtns">';
if((displayAddToOWLBtn === true) && (displayUpdateOWLBtn === false))
{
btnHTML += '<button class="btn btn-default" id="_btnAddUpdateOWL">Add to OWL</button>';
}
else if((displayUpdateOWLBtn === true) && (displayAddToOWLBtn === false))
{
btnHTML += '<button class="btn btn-default" id="_btnAddUpdateOWL">Update OWL</button>';
}
else if((displayAddToOWLBtn === true) && (displayUpdateOWLBtn === true))
{
btnHTML += '<button class="btn btn-default" id="_btnAddUpdateOWL">Add to & Update OWL</button>';
}
if(displayRemoveFromOWLBtn === true)
{
btnHTML += '<button class="btn btn-default" id="_btnRemoveOWL">Remove from OWL</button>';
}
btnHTML += '</div>';
// note to self... altering the inner HTML of the segment-edit-general panel when the selected
// segment is part of a roundabout always used to disable the onclick handler for the select
// roundabout button. will need to see how this behaves in the current WME given the changes in
// panel arrangement and the introduction of the native select roundabout button
if(selectedSegments === true)
{
document.getElementById("segment-edit-general").innerHTML += btnHTML;
}
else if(selectedLandmarks === true)
{
document.getElementById("landmark-edit-general").innerHTML += btnHTML;
}
if((displayAddToOWLBtn === true)||(displayUpdateOWLBtn === true))
{
if(selectedSegments === true)
{
uroAddEventListener('_btnAddUpdateOWL','click', uroAddUpdateSegWatchList, true);
}
else
{
uroAddEventListener('_btnAddUpdateOWL','click', uroAddUpdatePlaceWatchList, true);
}
}
if(displayRemoveFromOWLBtn === true)
{
if(selectedSegments === true)
{
uroAddEventListener('_btnRemoveOWL','click', uroRemoveSegFromWatchList, true);
}
else
{
uroAddEventListener('_btnRemoveOWL','click', uroRemovePlaceFromWatchList, true);
}
}
}
*/
}
function uroTSTClosureCloningHandler()
{
// closure cloning support...
//
// has the closures tab been generated?
if(document.getElementById('segment-edit-closures') !== null)
{
// and is it active?
if(document.getElementById('segment-edit-closures').className === 'tab-pane active')
{
// and are there any closures defined for all of the selected segment(s)...
var nClosures = document.getElementsByClassName('full-closures')[0].childNodes.length;
if(nClosures > 0)
{
// and last but by no means least, have we already added the clone icon to this closure?
for(var cLoop = 0; cLoop < nClosures; cLoop++)
{
var btnElm = document.getElementsByClassName('full-closures')[0].childNodes[cLoop].children[0].children[0];
if(btnElm.innerHTML.indexOf('_uroCloneClosure-') == -1)
{
var newAnchor = document.createElement('a');
var anchorID = '_uroCloneClosure-'+cLoop;
newAnchor.href="#";
newAnchor.innerHTML = "<i class='fa fa-copy'></i>";
newAnchor.id = anchorID;
btnElm.appendChild(newAnchor);
uroAddEventListener(anchorID,"click",uroCloneClosure,false);
}
}
}
// if there's more than one closure (full or partial) listed, also add the delete all button if not already present...
if(document.getElementsByClassName('closure-item').length > 1)
{
if(document.getElementById('_btnDeleteAllClosures') === null)
{
var daDiv = document.createElement('div');
daDiv.className = 'delete-all-button btn btn-primary';
daDiv.id = '_btnDeleteAllClosures';
daDiv.innerHTML = '<i class="fa fa-trash"></i> '+I18n.lookup("closures.delete_confirm_no_reason")+' ('+I18n.lookup("closures.apply_to_all")+')';
daDiv.style.width = '100%';
daDiv.style.marginBottom = '10px';
var acBtn = document.getElementsByClassName('add-closure-button')[0];
acBtn.parentNode.insertBefore(daDiv, acBtn.nextSibling);
uroAddEventListener('_btnDeleteAllClosures',"click", uroDeleteAllClosures, false);
}
}
}
}
}
function uroMiscUITweaksHandler()
{
if(uroFilterPreamble())
{
// give user the option of setting their own background colour...
{
var mapviewport = document.getElementsByClassName("olMapViewport")[0];
if((uroGetCBChecked('_cbWhiteBackground') === true) && (uroGetCBChecked('_cbMasterEnable') === true))
{
var customColour = '#' + uroToHex(uroGetElmValue('_inputCustomBackgroundRed'),2);
customColour += uroToHex(uroGetElmValue('_inputCustomBackgroundGreen'),2);
customColour += uroToHex(uroGetElmValue('_inputCustomBackgroundBlue'),2);
mapviewport.style.backgroundColor = customColour;
}
else
{
mapviewport.style.backgroundColor = "#C2C2C2";
}
}
// allows user to hide the area managers layer without switching off the layer completely...
{
// ...if this sounds like a weird option - why not just switch off the layer from the layers menu? - then
// remember that in order for URO+ to be able to display in its own tab the list of AMs under the current
// mouse pointer location, which is somewhat more useful than the list given in the topbar, it needs the
// AM layer to be activated so that the AM areas data is loaded into WME. It doesn't however need the layer
// to then be visible, and since having a bunch of purple polygons covering the map can make for a rather
// difficult editing experience, being able to hide the polys whilst retaining the area information is
// of real benefit...
if((uroGetCBChecked('_cbHideAMLayer')) && (uroGetCBChecked('_cbMasterEnable')))
{
W.map.managedAreasLayer.setOpacity(0);
}
else
{
W.map.managedAreasLayer.setOpacity(1);
}
}
// gives user the option of minimising the size of the sidebar tabs to save space
{
if(!uroGetCBChecked('_cbDisableTabStyling'))
{
// The nav-tabs class is now also used for the General/Closures tabs on the segment edit panel, so we have
// to restrict the scope of this code to just those nav-tab classed elements within the user-tabs element.
var navTabs = document.getElementById('user-tabs').getElementsByClassName("nav-tabs")[0].children;
for(var loop = 0; loop<navTabs.length; loop++)
{
navTabs[loop].children[0].style.padding = "4px";
}
}
}
// gives user the option of hiding the somewhat unnecessary editor info panel at the top of the sidebar
{
var panelDisplay = '';
if(uroGetCBChecked('_cbHideEditorInfo'))
{
panelDisplay = "none";
}
document.getElementById("user-details").style.display = panelDisplay;
}
}
}
function uroTenthSecondTick()
{
if(uroMTEMode) return;
if(uroSetupListeners)
{
if(uroFinalisingListenerSetup === false)
{
if(W.loginManager.isLoggedIn())
{
uroFinalizeListenerSetup();
}
}
}
else
{
uroTSTPopupHandler();
uroTSTDTEHandler();
uroTSTNextBtnHandler();
uroTSTCommentAddedHandler();
uroTSTOWLHandler();
uroTSTClosureCloningHandler();
uroTSTFeedFilter();
uroMiscUITweaksHandler();
}
}
function uroActiveTab(_id)
{
var e = document.getElementById(_id);
e.style.backgroundColor = "aliceblue";
e.style.borderTop = "1px solid";
e.style.borderLeft = "1px solid";
e.style.borderRight = "1px solid";
e.style.borderBottom = "0px solid";
}
function uroInactiveTab(_id)
{
var e = document.getElementById(_id);
e.style.backgroundColor = "white";
e.style.borderTop = "0px solid";
e.style.borderLeft = "0px solid";
e.style.borderRight = "0px solid";
e.style.borderBottom = "1px solid";
}
function uroInactiveAllTabs()
{
uroInactiveTab("_tabSelectCameras");
uroInactiveTab("_tabSelectMapProblems");
uroInactiveTab("_tabSelectMisc");
uroInactiveTab("_tabSelectUserRequests");
uroInactiveTab("_tabSelectCWL");
uroInactiveTab("_tabSelectPlaces");
if(!uroCtrlsHidden)
{
uroSetStyleDisplay('uroCtrlURs','none');
uroSetStyleDisplay('uroCtrlMPs','none');
uroSetStyleDisplay('uroCtrlCameras','none');
uroSetStyleDisplay('uroCtrlMisc','none');
uroSetStyleDisplay('uroOWL','none');
uroSetStyleDisplay('uroCtrlPlaces','none');
}
}
function uroShowURTab()
{
uroInactiveAllTabs();
uroActiveTab("_tabSelectUserRequests");
uroCurrentTab = 1;
if(!uroCtrlsHidden) uroSetStyleDisplay('uroCtrlURs','block');
return false;
}
function uroShowMPTab()
{
uroInactiveAllTabs();
uroActiveTab("_tabSelectMapProblems");
uroCurrentTab = 2;
if(!uroCtrlsHidden) uroSetStyleDisplay('uroCtrlMPs','block');
return false;
}
function uroShowPlacesTab()
{
uroInactiveAllTabs();
uroActiveTab("_tabSelectPlaces");
uroCurrentTab = 3;
if(!uroCtrlsHidden) uroSetStyleDisplay('uroCtrlPlaces','block');
for(var idx=0;idx<uroPlacesGroupsCollapsed.length;idx++)
{
uroPlacesGroupCEHandler(idx);
}
return false;
}
function uroShowCameraTab()
{
uroInactiveAllTabs();
uroActiveTab("_tabSelectCameras");
uroCurrentTab = 4;
if(!uroCtrlsHidden) uroSetStyleDisplay('uroCtrlCameras','block');
return false;
}
function uroShowOWLTab()
{
uroInactiveAllTabs();
uroActiveTab("_tabSelectCWL");
uroCurrentTab = 5;
if(!uroCtrlsHidden) uroSetStyleDisplay('uroOWL','block');
uroOWLUpdateHTML();
return false;
}
function uroShowMiscTab()
{
uroInactiveAllTabs();
uroActiveTab("_tabSelectMisc");
uroCurrentTab = 6;
if(!uroCtrlsHidden) uroSetStyleDisplay('uroCtrlMisc','block');
return false;
}
function uroNewLookCheckDetailsRequest()
{
var thisurl = document.location.href;
var doRetry = true;
var urID;
var endmarkerpos = thisurl.indexOf('&endshow');
var showmarkerpos = thisurl.indexOf('&showturn=');
if((endmarkerpos != -1) && (showmarkerpos != -1))
{
showmarkerpos += 10;
uroAddLog('showturn tab opened');
urID = thisurl.substr(showmarkerpos,endmarkerpos-showmarkerpos);
uroAddLog(' turn problem ID = '+urID);
try
{
W.map.problemLayer.markers[urID].icon.imageDiv.click();
doRetry = false;
}
catch(err)
{
uroAddLog('problems not fully loaded, retrying...');
}
if(doRetry) setTimeout(uroNewLookCheckDetailsRequest,500);
}
else
{
showmarkerpos = thisurl.indexOf('&showpur=');
if((endmarkerpos != -1) && (showmarkerpos != -1))
{
showmarkerpos += 9;
uroAddLog('showPUR tab opened');
urID = thisurl.substr(showmarkerpos,endmarkerpos-showmarkerpos);
uroAddLog(' PUR ID = '+urID);
try
{
W.map.placeUpdatesLayer.markers[urID].icon.imageDiv.click();
doRetry = false;
}
catch(err)
{
uroAddLog('PURs not fully loaded, retrying...');
}
if(doRetry) setTimeout(uroNewLookCheckDetailsRequest,500);
}
}
}
function uroUpdateMPSolverList()
{
if(Object.keys(W.model.problems.objects).length === 0)
{
return;
}
var resolverList = [];
var selector = document.getElementById('_selectMPUserID');
var selectedUser = null;
if(selector.selectedOptions[0] != null)
{
selectedUser = parseInt(selector.selectedOptions[0].value);
}
while(selector.options.length > 0)
{
selector.options.remove(0);
}
var selectedIdx = 0;
var idx = 0;
for (var mpobj in W.model.problems.objects)
{
if(W.model.problems.objects.hasOwnProperty(mpobj))
{
var prob = W.model.problems.objects[mpobj];
if(prob.attributes.resolvedBy !== null)
{
var userID = prob.attributes.resolvedBy;
var userName = W.model.users.objects[userID].userName;
if(resolverList.indexOf(userName) == -1)
{
resolverList.push(userName);
selector.options.add(new Option(userName, userID));
if(userID == selectedUser)
{
selectedIdx = idx;
}
idx++;
}
}
}
}
if(selectedIdx !== null)
{
selector.selectedIndex = selectedIdx;
}
}
function uroUpdateResolverList()
{
if(Object.keys(W.model.mapUpdateRequests.objects).length === 0)
{
return;
}
var resolverList = [];
var selector = document.getElementById('_selectURResolverID');
var selectedUser = null;
if(selector.selectedOptions[0] != null)
{
selectedUser = parseInt(selector.selectedOptions[0].value);
}
while(selector.options.length > 0)
{
selector.options.remove(0);
}
var selectedIdx = 0;
var idx = 0;
for (var urobj in W.model.mapUpdateRequests.objects)
{
if(W.model.mapUpdateRequests.objects.hasOwnProperty(urobj))
{
var ureq = W.model.mapUpdateRequests.objects[urobj];
if(ureq.attributes.resolvedBy !== null)
{
var userID = ureq.attributes.resolvedBy;
var userName = W.model.users.objects[userID].userName;
if(resolverList.indexOf(userName) == -1)
{
resolverList.push(userName);
selector.options.add(new Option(userName, userID));
if(userID == selectedUser)
{
selectedIdx = idx;
}
idx++;
}
}
}
}
if(selectedIdx !== null)
{
selector.selectedIndex = selectedIdx;
}
}
function uroUpdateUserList()
{
if(Object.keys(W.model.updateRequestSessions.objects).length === 0) return;
var selector = document.getElementById('_selectURUserID');
var selectedUser = null;
if(selector.selectedOptions[0] != null)
{
selectedUser = parseInt(selector.selectedOptions[0].value);
}
while(selector.options.length > 0)
{
selector.options.remove(0);
}
var selectedIdx = null;
var listedIDs = [];
for(var ursIdx in W.model.updateRequestSessions.objects)
{
if(W.model.updateRequestSessions.objects.hasOwnProperty(ursIdx))
{
var ursObj = W.model.updateRequestSessions.objects[ursIdx];
if(ursObj.comments.length > 0)
{
for(var cidx=0; cidx < ursObj.comments.length; cidx++)
{
var userID = ursObj.comments[cidx].userID;
if((listedIDs.indexOf(userID) == -1) && (userID != -1))
{
listedIDs.push(userID);
}
}
}
}
}
if(listedIDs.length > 0)
{
var users = W.model.users.getByIds(listedIDs);
for(var idx=0; idx<listedIDs.length; idx++)
{
selector.options.add(new Option(users[idx].userName, listedIDs[idx]));
if(listedIDs[idx] == selectedUser)
{
selectedIdx = idx;
}
}
}
if(selectedIdx !== null)
{
selector.selectedIndex = selectedIdx;
}
}
function uroUpdateCamEditorList()
{
if(Object.keys(W.model.cameras.objects).length === 0) return;
var selector = document.getElementById('_selectCameraUserID');
var selectedUser = null;
if(selector.selectedOptions[0] != null)
{
selectedUser = parseInt(selector.selectedOptions[0].value);
}
while(selector.options.length > 0)
{
selector.options.remove(0);
}
var selectedIdx = null;
var listedIDs = [];
for(var camIdx in W.model.cameras.objects)
{
if(W.model.cameras.objects.hasOwnProperty(camIdx))
{
var camObj = W.model.cameras.objects[camIdx].attributes;
var cbID = camObj.createdBy;
var ubID = camObj.updatedBy;
if((cbID !== null) && (listedIDs.indexOf(cbID) == -1))
{
listedIDs.push(cbID);
}
if((ubID !== null) && (ubID !== cbID) && (listedIDs.indexOf(ubID) == -1))
{
listedIDs.push(ubID);
}
}
}
selector.options.add(new Option('<select a user>', null));
if(listedIDs.length > 0)
{
var users = W.model.users.getByIds(listedIDs);
var selectorEntry = '';
for(var idx=0; idx<users.length; idx++)
{
if(users[idx].userName === undefined)
{
selectorEntry = users[idx].id;
}
else
{
selectorEntry = users[idx].userName;
}
selector.options.add(new Option(selectorEntry, users[idx].id));
if(users[idx].id == selectedUser)
{
selectedIdx = idx+1;
}
}
}
if(selectedIdx !== null)
{
selector.selectedIndex = selectedIdx;
}
}
function uroCamEditorSelected()
{
var selector = document.getElementById('_selectCameraUserID');
if(selector.selectedIndex > 0)
{
document.getElementById('_textCameraEditor').value = document.getElementById('_selectCameraUserID').selectedOptions[0].innerHTML;
}
}
function uroSetStyles(obj)
{
obj.style.fontSize = '12px';
obj.style.lineHeight = '100%';
obj.style.overflow = 'auto';
obj.style.height = (window.innerHeight * 0.55) + 'px';
}
function uroPlacesGroupCEHandler(groupidx)
{
if(uroPlacesGroupsCollapsed[groupidx] === false)
{
document.getElementById('_uroPlacesGroup-'+groupidx).style.display = "block";
document.getElementById('_uroPlacesGroupState-'+groupidx).className = "fa fa-minus-square-o";
}
else
{
document.getElementById('_uroPlacesGroup-'+groupidx).style.display = "none";
document.getElementById('_uroPlacesGroupState-'+groupidx).className = "fa fa-plus-square-o";
}
}
function uroPlacesGroupCollapseExpand()
{
var groupidx = this.id.substr(21);
if(uroPlacesGroupsCollapsed[groupidx] === true) uroPlacesGroupsCollapsed[groupidx] = false;
else uroPlacesGroupsCollapsed[groupidx] = true;
uroPlacesGroupCEHandler(groupidx);
return false;
}
function uroPopulatePlacesTab()
{
var tHTML = '';
tHTML += '<b>Filter PURs by category/status:</b><br>';
tHTML += '<input type="checkbox" id="_cbFilterUneditablePlaceUpdates">Ones I can\'t edit</input><br>';
tHTML += '<input type="checkbox" id="_cbFilterLockRankedPlaceUpdates">Ones with non-zero lockRanks</input><br>';
tHTML += '<input type="checkbox" id="_cbFilterNewPlacePUR">Ones for new places</input><br>';
tHTML += '<input type="checkbox" id="_cbFilterUpdatedDetailsPUR">Ones for updated place details</input><br>';
tHTML += '<input type="checkbox" id="_cbFilterNewPhotoPUR">Ones for new photos</input><br>';
tHTML += '<input type="checkbox" id="_cbFilterFlaggedPUR">Ones flagged for attention</input><br>';
tHTML += '<br><input type="checkbox" id="_cbLeavePURGeos">Don\'t hide place polygons/points</input><br>';
tHTML += '<br><input type="checkbox" id="_cbInvertPURFilters">Invert PUR filters</input><br>';
tHTML += '<br><b>Filter PURs by severity:</b><br>';
tHTML += '<input type="checkbox" id="_cbPURFilterLowSeverity">Low</input> ';
tHTML += '<input type="checkbox" id="_cbPURFilterMediumSeverity">Medium</input> ';
tHTML += '<input type="checkbox" id="_cbPURFilterHighSeverity">High</input>';
tHTML += '<br><b>Filter PURs by age of submission:</b><br>';
tHTML += '<input type="checkbox" id="_cbEnablePURMinAgeFilter">Hide PURs less than </input>';
tHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputPURFilterMinDays"> days old<br>';
tHTML += '<input type="checkbox" id="_cbEnablePURMaxAgeFilter">Hide PURs more than </input>';
tHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputPURFilterMaxDays"> days old<br>';
tHTML += '<hr>';
tHTML += '<br><b>Filter Places by state:</b><br>';
tHTML += 'Hide if last edited<br>';
tHTML += '<input type="checkbox" id="_cbPlaceFilterEditedLessThan"> less than </input>';
tHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterPlaceEditMinDays"> days ago<br>';
tHTML += '<input type="checkbox" id="_cbPlaceFilterEditedMoreThan"> more than </input>';
tHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterPlaceEditMaxDays"> days ago<br>';
tHTML += '<br>Hide if locked at level:<br>';
tHTML += ' <input type="checkbox" id="_cbHidePlacesL0">1</input>';
tHTML += ' <input type="checkbox" id="_cbHidePlacesL1">2</input>';
tHTML += ' <input type="checkbox" id="_cbHidePlacesL2">3</input>';
tHTML += ' <input type="checkbox" id="_cbHidePlacesL3">4</input>';
tHTML += ' <input type="checkbox" id="_cbHidePlacesL4">5</input>';
tHTML += ' <input type="checkbox" id="_cbHidePlacesL5">6</input>';
tHTML += ' <input type="checkbox" id="_cbHidePlacesStaff">Staff</input>';
tHTML += '<br> <input type="checkbox" id="_cbHidePlacesAdLocked">AdLocked</input><br>';
tHTML += '<br>Hide by geometry:<br>';
tHTML += ' <input type="checkbox" id="_cbHideAreaPlaces">Areas</input>';
tHTML += ' <input type="checkbox" id="_cbHidePointPlaces">Points</input>';
tHTML += '<br><br><input type="checkbox" id="_cbHidePhotoPlaces" pairedWith="_cbHideNoPhotoPlaces">Hide or </input>';
tHTML += '<input type="checkbox" id="_cbHideNoPhotoPlaces" pairedWith="_cbHidePhotoPlaces">show ones with photos</input><br>';
tHTML += '<input type="checkbox" id="_cbHideLinkedPlaces" pairedWith="_cbHideNoLinkedPlaces">Hide or </input>';
tHTML += '<input type="checkbox" id="_cbHideNoLinkedPlaces" pairedWith="_cbHideLinkedPlaces">show ones with external links</input><br>';
tHTML += '<input type="checkbox" id="_cbHideKeywordPlaces" pairedWith="_cbHideNoKeywordPlaces">Hide or </input>';
tHTML += '<input type="checkbox" id="_cbHideNoKeywordPlaces" pairedWith="_cbHideKeywordPlaces">show ones with a name including</input><br>';
tHTML += '<input type="text" style="font-size:14px; line-height:16px; height:22px; margin-bottom:4px;" id="_textKeywordPlace"><br>';
tHTML += '<br><br><b>Filter Places by category:</b><br>';
var nCategories = W.Config.venues.categories.length;
var i;
if(uroPlacesGroupsCollapsed.length != nCategories)
{
for(i=0; i<nCategories; i++)
{
uroPlacesGroupsCollapsed.push(false);
}
}
for(i=0; i<nCategories; i++)
{
var parentCategory = W.Config.venues.categories[i];
var localisedName = I18n.lookup("venues.categories." + parentCategory);
if(uroPlacesGroupsCollapsed[i] === true)
{
tHTML += '<i class="fa fa-plus-square-o" style="cursor:pointer;font-size:14px;" id="_uroPlacesGroupState-'+i+'"></i>';
}
else
{
tHTML += '<i class="fa fa-minus-square-o" style="cursor:pointer;font-size:14px;" id="_uroPlacesGroupState-'+i+'"></i>';
}
tHTML += ' <input type="checkbox" id="_cbPlacesFilter-'+parentCategory+'"><b>'+localisedName+'</b></input><br>';
tHTML += '<div id="_uroPlacesGroup-'+i+'" style="padding:3px;border-width:2px;border-style:solid;border-color:#FFFFFF">';
for(var ii=0; ii<W.Config.venues.subcategories[parentCategory].length; ii++)
{
var subCategory = W.Config.venues.subcategories[parentCategory][ii];
localisedName = I18n.lookup("venues.categories." + subCategory);
tHTML += ' <input type="checkbox" id="_cbPlacesFilter-'+subCategory+'">'+localisedName+'</input><br>';
}
tHTML += '</div>';
}
tHTML += '<input type="checkbox" id="_cbFilterPrivatePlaces"><b>Residential Places</b></input><br>';
tHTML += '<br><input type="checkbox" id="_cbInvertPlacesFilter">Invert Place filters?</input>';
uroCtrlPlaces.innerHTML = tHTML;
}
function uroWazeBits()
{
// "fake" uroWazeBits() function which only performs layer scan, to stop the uroWazeBits() call in WMETB from
// messing around with other stuff in the actual uroWazeBits() function (now renamed uroRealWazeBits...) that
// really only ought to be called once.
var i;
for(i=0;i<W.map.layers.length;i++)
{
if(W.map.layers[i].name == 'Spotlight') uroMaskLayer = i;
if(W.map.layers[i].CLASS_NAME == 'OpenLayers.Layer.Vector.RootContainer') uroRootContainer = W.map.layers[i].div.id;
if(W.map.layers[i].name == 'Node Connections') uroTurnsLayerIdx = i;
}
uroPlacesRoot = W.map.landmarkLayer.id + '_vroot';
for(i=0;i<W.map.controls.length;i++)
{
if(W.map.controls[i].CLASS_NAME == 'Waze.View.ArchivePanel') dteControlsIdx = i;
else if(W.map.controls[i].CLASS_NAME == 'Waze.Control.Archive') dteControlsIdx = i;
if(W.map.controls[i].id !== null)
{
if(W.map.controls[i].id.indexOf('UpdateRequests') != -1) uroURControlsIdx = i;
if(W.map.controls[i].id.indexOf('MapProblems') != -1) uroProblemControlsIdx = i;
}
}
uroAddLog('uroMaskLayer at idx '+uroMaskLayer);
uroAddLog('Turns layer at idx '+uroTurnsLayerIdx);
uroAddLog('uroRootContainer = '+uroRootContainer);
uroAddLog('Places root layer = '+uroPlacesRoot);
}
function uroRealWazeBits()
{
if(document.getElementsByClassName("sandbox").length > 0)
{
uroAddLog('WME practice mode detected, script is disabled...');
return;
}
if(document.location.href.indexOf('user') !== -1)
{
uroAddLog('User profile page detected, script is disabled...');
return;
}
uroAddLog('adding WazeBits...'+uroToHex(uroWazeBitsPresent,4));
if((uroWazeBitsPresent & 0x0001) === 0)
{
if(typeof W != "undefined")
{
if(typeof W.map != "undefined")
{
uroAddLog(' W.map OK');
uroWazeBitsPresent |= 0x0001;
}
}
}
if((uroWazeBitsPresent & 0x0002) === 0)
{
if(typeof W != "undefined")
{
if(typeof W.model != "undefined")
{
uroAddLog(' W.model OK');
uroWazeBitsPresent |= 0x0002;
}
}
}
if((uroWazeBitsPresent & 0x0004) === 0)
{
if(typeof W != "undefined")
{
if(typeof W.loginManager != "undefined")
{
uroAddLog(' loginManager OK');
uroWazeBitsPresent |= 0x0004;
}
}
}
if((uroWazeBitsPresent & 0x0008) === 0)
{
if(typeof W != "undefined")
{
if(typeof W.selectionManager != "undefined")
{
uroAddLog(' selectionManager OK');
uroWazeBitsPresent |= 0x0008;
}
}
}
if((uroWazeBitsPresent & 0x0010) === 0)
{
if(typeof OpenLayers != "undefined")
{
uroAddLog(' OpenLayers OK');
uroWazeBitsPresent |= 0x0010;
}
}
if((uroWazeBitsPresent & 0x0020) === 0)
{
if(typeof Waze != "undefined")
{
uroAddLog(' Waze OK');
uroWazeBitsPresent |= 0x0020;
}
}
if((uroWazeBitsPresent & 0x0040) === 0)
{
if(document.getElementById('user-tabs') !== null)
{
uroUserTabId = 'user-tabs';
uroAddLog(' user-tabs OK');
uroWazeBitsPresent |= 0x0040;
}
}
if((uroWazeBitsPresent & 0x0080) === 0)
{
if(document.getElementById('sidepanel-drives') !== null)
{
uroAddLog(' sidepanel-drives OK');
uroWazeBitsPresent |= 0x0080;
}
}
if((uroWazeBitsPresent & 0x0100) === 0)
{
if(typeof I18n != "undefined")
{
uroAddLog(' I18n OK');
uroWazeBitsPresent |= 0x0100;
}
}
if(uroWazeBitsPresent !== 0x01FF)
{
setTimeout(uroRealWazeBits,250);
}
else if(W.loginManager.isLoggedIn() === false)
{
uroAddLog('Waiting for user log-in...');
setTimeout(uroRealWazeBits,1000);
}
else
{
uroAddLog('All WazeBits present and correct...');
W.app.modeController.model.bind("change:mode",uroInitialise);
if(W.app.modeController.mode.mteModeState !== undefined)
{
uroMTEMode = true;
uroSetupListeners = true;
uroFinalisingListenerSetup = false;
uroHidePopup();
uroAddLog('MTE mode, sleeping until normal service is resumed...');
return;
}
uroMTEMode = false;
uroSetupUI();
uroDOMHasTurnProblems = (W.model.turnProblems != null);
uroPopulatePlacesTab();
uroControls.appendChild(uroCtrlURs);
uroControls.appendChild(uroCtrlMPs);
uroControls.appendChild(uroCtrlPlaces);
uroControls.appendChild(uroCtrlCameras);
uroControls.appendChild(uroOWL);
uroControls.appendChild(uroCtrlMisc);
uroControls.appendChild(uroCtrlHides);
uroControls.appendChild(uroAMList);
uroCtrlURs.onclick = uroFilterItems_URTabClick;
uroCtrlMPs.onclick = uroFilterItems_MPTabClick;
uroCtrlPlaces.onclick = uroFilterItems_PlacesTabClick;
uroCtrlCameras.onclick = uroFilterItems_CamerasTabClick;
uroCtrlMisc.onclick = uroFilterItems_MiscTabClick;
uroWazeBits();
uroDiv.addEventListener("mouseover", uroEnterPopup, false);
uroDiv.addEventListener("mouseout", uroExitPopup, false);
if(sessionStorage.UROverview_FID_IgnoreList === undefined) sessionStorage.UROverview_FID_IgnoreList = '';
if(sessionStorage.UROverview_FID_WatchList === undefined) sessionStorage.UROverview_FID_WatchList = '';
if(uroConfirmIntercepted === false) uroAddInterceptor();
setInterval(uroTenthSecondTick,100);
}
}
function uroAddInterceptor()
{
uroAddLog('Adding interceptor function...');
// add interceptor function for confirm(), so that we can auto-select the "OK" option when solving URs
// which have pending question...
var _confirm = window.confirm;
window.confirm = function(msg)
{
var cm_delete_confirm = I18n.lookup("closures.delete_confirm").split('"')[0].trimRight(1);
if((I18n.lookup("update_requests.panel.confirm") == msg) && (uroGetCBChecked('_cbDisablePendingQuestions') === true))
{
uroAddLog('Intercepted pending comments confirmation...');
return true;
}
else if(msg.indexOf(cm_delete_confirm) != -1)
{
uroAddLog('intercepted closure delete confirmation...');
if(uroConfirmClosureDelete)
{
return _confirm(msg);
}
else
{
return true;
}
}
else if(typeof(msg) == 'undefined')
{
uroAddLog('Intercepted blank confirmation...');
return true;
}
else
{
return _confirm(msg);
}
};
uroConfirmIntercepted = true;
}
function uroEnterPopup()
{
uroMouseInPopup = true;
}
function uroExitPopup()
{
uroMouseInPopup = false;
}
function uroToggleDebug()
{
uroShowDebugOutput = !uroShowDebugOutput;
var dbgMode = "none";
if(uroShowDebugOutput)
{
dbgMode = "inline";
}
document.getElementById('_uroDebugMode').style.display = dbgMode;
}
function uroInitialise()
{
uroInitialised = false;
if(document.URL.indexOf('beta') != -1) uroBetaEditor = true;
var urlBits = document.URL.split("&mapUpdateRequest=");
if(urlBits.length == 2)
{
uroURIDInURL = parseInt(urlBits[1].split('&')[0]);
uroAddLog('found UR ID '+uroURIDInURL+' in URL');
}
uroRealWazeBits();
}
function uroSetupUI()
{
// create a new div to display the UR details floaty-box
uroDiv = document.createElement('div');
uroDiv.id = "uroDiv";
uroDiv.style.position = 'absolute';
uroDiv.style.visibility = 'hidden';
uroDiv.style.top = '0';
uroDiv.style.left = '0';
uroDiv.style.zIndex = 100;
uroDiv.style.backgroundColor = 'aliceblue';
uroDiv.style.borderWidth = '3px';
uroDiv.style.borderStyle = 'solid';
uroDiv.style.borderRadius = '10px';
uroDiv.style.boxShadow = '5px 5px 10px Silver';
uroDiv.style.padding = '4px';
document.body.appendChild(uroDiv);
// create a new div to display script alerts
uroAlerts = document.createElement('div');
uroAlerts.id = "uroAlerts";
uroAlerts.style.position = 'fixed';
uroAlerts.style.visibility = 'hidden';
uroAlerts.style.top = '50%';
uroAlerts.style.left = '50%';
uroAlerts.style.zIndex = 100;
uroAlerts.style.backgroundColor = 'aliceblue';
uroAlerts.style.borderWidth = '3px';
uroAlerts.style.borderStyle = 'solid';
uroAlerts.style.borderRadius = '10px';
uroAlerts.style.boxShadow = '5px 5px 10px Silver';
uroAlerts.style.padding = '4px';
uroAlerts.style.webkitTransform = "translate(-50%, -50%)";
uroAlerts.style.transform = "translate(-50%, -50%)";
var alertsHTML = '<div id="header" style="padding: 4px; background-color:LightGreen; font-weight: bold;">Alert title goes here...</div>';
alertsHTML += '<div id="content" style="padding: 4px; background-color:White">Alert content goes here...</div>';
alertsHTML += '<div id="controls" style="padding: 4px;">';
alertsHTML += '<span id="uroAlertTickBtn" style="cursor:pointer;font-size:14px;border:thin outset black;padding:2px;">';
alertsHTML += '<i class="fa fa-check"> </i>';
alertsHTML += '<span id="uroAlertTickBtnCaption" style="font-weight: bold;"></span>';
alertsHTML += '</span>';
alertsHTML += ' ';
alertsHTML += '<span id="uroAlertCrossBtn" style="cursor:pointer;font-size:14px;border:thin outset black;padding:2px;">';
alertsHTML += '<i class="fa fa-times"> </i>';
alertsHTML += '<span id="uroAlertCrossBtnCaption" style="font-weight: bold;"></span>';
alertsHTML += '</span>';
alertsHTML += '</div>';
uroAlerts.innerHTML = alertsHTML;
document.body.appendChild(uroAlerts);
uroControls = document.createElement('section');
uroControls.style.fontSize = '12px';
uroControls.id = 'uroControls';
var updateURL;
if(navigator.userAgent.indexOf('Chrome') == -1)
{
updateURL = 'https://gf.qytechs.cn/scripts/1952-uroverview-plus-uro';
}
else
{
updateURL = 'https://chrome.google.com/webstore/detail/uroverview/amdamgkgchnbaopmphhjapmjcdghdphi';
}
var tabbyHTML = '<b><a href="'+updateURL+'" target="_blank">UROverview Plus</a></b> <label id="_uroVersion">'+uroVersion+'</label>';
tabbyHTML += '<label id="_uroDebugMode">(dbg)</label>';
tabbyHTML += ' <input type="checkbox" id="_cbMasterEnable" checked>Enabled</input>';
tabbyHTML += '<p><table border=0 width="100%"><tr>';
tabbyHTML += '<td valign="center" align="center" id="_tabSelectUserRequests"><a href="#" id="_linkSelectUserRequests" style="text-decoration:none;font-size:12px">URs</a></td>';
tabbyHTML += '<td valign="center" align="center" id="_tabSelectMapProblems"><a href="#" id="_linkSelectMapProblems" style="text-decoration:none;font-size:12px">MPs</a></td>';
tabbyHTML += '<td valign="center" align="center" id="_tabSelectPlaces"><a href="#" id="_linkSelectPlaces" style="text-decoration:none;font-size:12px">Places</a></td>';
tabbyHTML += '<td valign="center" align="center" id="_tabSelectCameras"><a href="#" id="_linkSelectCameras" style="text-decoration:none;font-size:12px">Cams</a></td>';
tabbyHTML += '<td valign="center" align="center" id="_tabSelectCWL"><a href="#" id="_linkSelectOWL" style="text-decoration:none;font-size:12px">OWL</a></td>';
tabbyHTML += '<td valign="center" align="center" id="_tabSelectMisc"><a href="#" id="_linkSelectMisc" style="text-decoration:none;font-size:12px">Misc</a></td>';
tabbyHTML += '</tr></table>';
uroControls.innerHTML = tabbyHTML;
uroCtrlURs = document.createElement('p');
uroCtrlMPs = document.createElement('p');
uroCtrlCameras = document.createElement('p');
uroOWL = document.createElement('p');
uroCtrlMisc = document.createElement('p');
uroAMList = document.createElement('div');
uroCtrlHides = document.createElement('div');
uroCtrlPlaces = document.createElement('p');
// UR controls tab
uroCtrlURs.id = "uroCtrlURs";
uroCtrlURs.innerHTML = '<br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbURFilterOutsideArea">Hide URs outside my editable area</input><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbNoFilterForURInURL">Don\'t filter UR in URL</input><br><br>';
uroCtrlURs.innerHTML += '<b>Filter by type:</b><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterWazeAuto">Waze Automatic</input><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterIncorrectTurn">Incorrect turn</input><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterIncorrectAddress">Incorrect address</input><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterIncorrectRoute">Incorrect route</input><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterMissingRoundabout">Missing roundabout</input><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterGeneralError">General error</input><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterTurnNotAllowed">Turn not allowed</input><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterIncorrectJunction">Incorrect junction</input><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterMissingBridgeOverpass">Missing bridge overpass</input><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterWrongDrivingDirection">Wrong driving direction</input><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterMissingExit">Missing exit</input><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterMissingRoad">Missing road</input><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterBlockedRoad">Blocked road</input><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterMissingLandmark">Missing Landmark</input><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterSpeedLimits">Missing or Invalid Speed limit</input><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterUndefined">Undefined</input><br>';
uroCtrlURs.innerHTML += ' <i>Specially tagged types</i><br>';
uroCtrlURs.innerHTML += ' <input type="checkbox" id="_cbFilterRoadworks">[ROADWORKS]</input><br>';
uroCtrlURs.innerHTML += ' <input type="checkbox" id="_cbFilterConstruction">[CONSTRUCTION]</input><br>';
uroCtrlURs.innerHTML += ' <input type="checkbox" id="_cbFilterClosure">[CLOSURE]</input><br>';
uroCtrlURs.innerHTML += ' <input type="checkbox" id="_cbFilterEvent">[EVENT]</input><br>';
uroCtrlURs.innerHTML += ' <input type="checkbox" id="_cbFilterNote">[NOTE]</input><br>';
uroCtrlURs.innerHTML += ' <input type="checkbox" id="_cbFilterBOG">[BOG]</input><br>';
uroCtrlURs.innerHTML += ' <input type="checkbox" id="_cbFilterDifficult">[DIFFICULT]</input><br>';
uroCtrlURs.innerHTML += ' <input type="checkbox" id="_cbFilterWSLM">[WSLM]</input><br><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbInvertURFilter">Invert operation of type filters?</input><br>';
uroCtrlURs.innerHTML += '<hr>';
uroCtrlURs.innerHTML += '<br><b>Hide by state:</b><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterOpenUR">Open</input><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterClosedUR">Closed</input><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterSolved">Solved</input><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterUnidentified">Not identified</input><br><br>';
uroCtrlURs.innerHTML += '<br><b>Filter by age of submission:</b><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableMinAgeFilter">Hide URs less than </input>';
uroCtrlURs.innerHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterMinDays"> days old<br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableMaxAgeFilter">Hide URs more than </input>';
uroCtrlURs.innerHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterMaxDays"> days old<br>';
uroCtrlURs.innerHTML += '<br><b>Filter by description/comments/following:</b><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideMyFollowed" pairedWith="_cbHideMyUnfollowed">Ones I am or </input>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideMyUnfollowed" pairedWith="_cbHideMyFollowed">am not following</input><br><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbURDescriptionMustBePresent" pairedWith="_cbURDescriptionMustBeAbsent">Hide</input> or ';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbURDescriptionMustBeAbsent" pairedWith="_cbURDescriptionMustBePresent">show</input> URs with no description<br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableKeywordMustBePresent">Hide URs not including </input>';
uroCtrlURs.innerHTML += '<input type="text" style="font-size:14px; line-height:16px; height:22px; margin-bottom:4px;" id="_textKeywordPresent"><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableKeywordMustBeAbsent">Hide URs including </input>';
uroCtrlURs.innerHTML += '<input type="text" style="font-size:14px; line-height:16px; height:22px; margin-bottom:4px;" id="_textKeywordAbsent"><br>';
uroCtrlURs.innerHTML += ' <input type="checkbox" id="_cbCaseInsensitive"><i>Case-insensitive matches?</i></input><br><br>';
uroCtrlURs.innerHTML += 'With comments from me?<br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideMyComments" pairedWith="_cbHideAnyComments">Yes </input>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideAnyComments" pairedWith="_cbHideMyComments">No</input><br>';
uroCtrlURs.innerHTML += 'If last comment made by me?<br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideIfLastCommenter" pairedWith="_cbHideIfNotLastCommenter">Yes </input>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideIfNotLastCommenter" pairedWith="_cbHideIfLastCommenter">No </input><br>';
uroCtrlURs.innerHTML += 'If last comment made by UR reporter?<br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideIfReporterLastCommenter" pairedWith="_cbHideIfReporterNotLastCommenter">Yes </input>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideIfReporterNotLastCommenter" pairedWith="_cbHideIfReporterLastCommenter">No</input><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableMinCommentsFilter">With less than </input>';
uroCtrlURs.innerHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterMinComments"> comments<br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableMaxCommentsFilter">With more than </input>';
uroCtrlURs.innerHTML += '<input type="number" min="0" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterMaxComments"> comments<br><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableCommentAgeFilter2">Last comment less than </input>';
uroCtrlURs.innerHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterCommentDays2"> days ago<br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableCommentAgeFilter">Last comment more than </input>';
uroCtrlURs.innerHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterCommentDays"> days ago<br>';
uroCtrlURs.innerHTML += ' <input type="checkbox" id="_cbIgnoreOtherEditorComments"><i>Ignore other editor comments?</i></input><br><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbURUserIDFilter">Without comments from user</input>';
uroCtrlURs.innerHTML += '<select id="_selectURUserID" style="width:80%; height:22px;"></select><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbURResolverIDFilter">Not resolved by user</input>';
uroCtrlURs.innerHTML += '<select id="_selectURResolverID" style="width:80%; height:22px;"></select>';
uroCtrlURs.innerHTML += '<br><br><input type="checkbox" id="_cbInvertURStateFilter">Invert operation of state/age filters?</input><br>';
uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbNoFilterForTaggedURs">Don\'t apply state/age filters to tagged URs</input><br>';
// Map problems controls tab
uroCtrlMPs.id = "uroCtrlMPs";
uroCtrlMPs.innerHTML = '<br>';
uroCtrlMPs.innerHTML += '<b>Filter MPs by type:</b><br>';
uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterMissingJunction">Missing junction</input><br>';
uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterMissingRoad">Missing road</input><br>';
uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterCrossroadsJunctionMissing">Missing crossroads</input><br>';
uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterDrivingDirectionMismatch">Driving direction mismatch</input><br>';
uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterRoadTypeMismatch">Road type mismatch</input><br>';
uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterRestrictedTurn">Restricted turn might be allowed</input><br>';
uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterRoadClosureProblem">Road closure</input><br>';
uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterUnknownProblem">Unknown/other problem type</input><br><br>';
uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterTurnProblem">Turn Problems</input><br><br>';
uroCtrlMPs.innerHTML += ' <i>Specially tagged types</i><br>';
uroCtrlMPs.innerHTML += ' <input type="checkbox" id="_cbFilterElgin">[Elgin]</input><br>';
uroCtrlMPs.innerHTML += ' <input type="checkbox" id="_cbFilterTrafficCast">[TrafficCast]</input><br>';
uroCtrlMPs.innerHTML += ' <input type="checkbox" id="_cbFilterTrafficMaster">[TM]</input><br>';
uroCtrlMPs.innerHTML += ' <input type="checkbox" id="_cbFilterCaltrans">[Caltrans]</input><br>';
uroCtrlMPs.innerHTML += ' <input type="checkbox" id="_cbFilterTFL">[TfL Open Data]</input><br>';
uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterReopenedProblem">Reopened Problems</input><br><br>';
uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbInvertMPFilter">Invert operation of type filters?</input><br>';
uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterOutsideArea">Hide MPs outside my editable area</input><br>';
uroCtrlMPs.innerHTML += '<br><b>Hide closed/solved/unidentified Problems:</b><br>';
uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterClosed">Closed</input><br>';
uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterSolved">Solved</input><br>';
uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterUnidentified">Not identified</input><br><br>';
uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPClosedUserIDFilter" pairedWith="_cbMPNotClosedUserIDFilter">Closed</input> or ';
uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPNotClosedUserIDFilter" pairedWith="_cbMPClosedUserIDFilter">Not Closed</input> by user';
uroCtrlMPs.innerHTML += '<select id="_selectMPUserID" style="width:80%; height:22px;"></select><br>';
uroCtrlMPs.innerHTML += '<br><b>Hide problems (not turn) by severity:</b><br>';
uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterLowSeverity">Low</input> ';
uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterMediumSeverity">Medium</input> ';
uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterHighSeverity">High</input><br>';
// Places filtering tab
uroCtrlPlaces.id = "uroCtrlPlaces";
uroCtrlPlaces.innerHTML = 'Places filter list being populated, please wait...';
// Camera controls tab
uroCtrlCameras.id = "uroCtrlCameras";
uroCtrlCameras.innerHTML = '<br><b>Show Cameras created by:</b><br>';
uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowWorldCams" checked>world_* users</input><br>';
uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowUSACams" checked>usa_* users</input><br>';
uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowNonWorldCams" checked>other users</input><br>';
uroCtrlCameras.innerHTML += '<br><b>Show Cameras touched by a specific editor:</b><br>';
uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowOnlyCamsCreatedBy">Created by</input> / ';
uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowOnlyCamsEditedBy">edited by</input><br>';
uroCtrlCameras.innerHTML += '<input type="text" style="font-size:14px; line-height:16px; height:22px; margin-bottom:4px;" id="_textCameraEditor"><br>';
uroCtrlCameras.innerHTML += '<select id="_selectCameraUserID" style="width:80%; height:22px;"></select><br>';
uroCtrlCameras.innerHTML += '<br><input type="checkbox" id="_cbShowOnlyMyCams">Show ONLY cameras created/edited by me</input><br>';
uroCtrlCameras.innerHTML += '<br><b>Show Cameras by approval status:</b><br>';
uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowApprovedCams" checked>approved</input><br>';
uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowNonApprovedCams" checked>non-approved</input><br>';
uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbShowOlderCreatedNonApproved"> if created more than </input>';
uroCtrlCameras.innerHTML += '<input type="number" min="1" size="3" style="width:50px;;line-height:14px;height:22px;margin-bottom:4px;" id="_inputCameraMinCreatedDays"> days ago<br>';
uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbShowOlderUpdatedNonApproved"> if updated more than </input>';
uroCtrlCameras.innerHTML += '<input type="number" min="1" size="3" style="width:50px;;line-height:14px;height:22px;margin-bottom:4px;" id="_inputCameraMinUpdatedDays"> days ago<br>';
uroCtrlCameras.innerHTML += '<br><b>Show Cameras by type:</b><br>';
uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowSpeedCams" checked>Speed</input><br>';
uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbShowIfSpeedSet" checked> with speed data</input><br>';
uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbShowIfNoSpeedSet" checked> with no speed data</input><br>';
uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowRedLightCams" checked>Red Light</input><br>';
uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowDummyCams" checked>Dummy</input><br>';
uroCtrlCameras.innerHTML += '<br><b>Hide Cameras by creator:</b><br>';
uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideCreatedByMe">me</input>';
uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideCreatedByRank0">L1</input>';
uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideCreatedByRank1">L2</input>';
uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideCreatedByRank2">L3</input>';
uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideCreatedByRank3">L4</input>';
uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideCreatedByRank4">L5</input>';
uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideCreatedByRank5">L6</input>';
uroCtrlCameras.innerHTML += '<br><b>Hide Cameras by updater:</b><br>';
uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideUpdatedByMe">me</input>';
uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideUpdatedByRank0">L1</input>';
uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideUpdatedByRank1">L2</input>';
uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideUpdatedByRank2">L3</input>';
uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideUpdatedByRank3">L4</input>';
uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideUpdatedByRank4">L5</input>';
uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideUpdatedByRank5">L6</input>';
uroCtrlCameras.innerHTML += '<br><br><b><input type="checkbox" id="_cbHideCWLCams">Hide cameras on watchlist</input></b><br>';
// Object watchlist tab
uroOWL.id = "uroOWL";
uroCWLGroups = [];
uroOWLUpdateHTML();
// Misc controls tab
uroCtrlMisc.id = "uroCtrlMisc";
uroCtrlMisc.innerHTML = '<br><b>Use default conversation markers:</b><br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbNativeConvoMarkers" checked />in public WME<br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbNativeBetaConvoMarkers" checked />in beta WME<br>';
uroCtrlMisc.innerHTML += '<br><br><b><input type="checkbox" id="_cbCommentCount" />Show comment count on UR markers</b><br>';
uroCtrlMisc.innerHTML += '<br><br><b><input type="checkbox" id="_cbURBackfill" />Backfill UR data</b><br>';
uroCtrlMisc.innerHTML += '<br><br><b>Marker Unstacking:</b><br>';
uroCtrlMisc.innerHTML += 'Distance threshold: <input type="number" min="1" max="30" value="15" size="2" style="width:50px;;line-height:14px;height:22px;margin-bottom:4px;" id="_inputUnstackSensitivity" /><br>';
uroCtrlMisc.innerHTML += 'Disable below zoom: <input type="number" min="0" max="10" value="3" size="2" style="width:50px;;line-height:14px;height:22px;margin-bottom:4px;" id="_inputUnstackZoomLevel" /><br>';
uroCtrlMisc.innerHTML += '<br><br><b>Use custom marker for URs tagged as:</b><br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomRoadworksMarkers" />[ROADWORKS]<br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomConstructionMarkers" />[CONSTRUCTION]<br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomClosuresMarkers" />[CLOSURE]<br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomEventsMarkers" />[EVENT]<br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomNotesMarkers" />[NOTE]<br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomBOGMarkers" />[BOG]<br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomDifficultMarkers" />[DIFFICULT]<br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomWSLMMarkers" />[WSLM]<br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomNativeSLMarkers" />Native speed limit reports<br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomKeywordMarkers" />';
uroCtrlMisc.innerHTML += '<input type="text" style="font-size:14px; line-height:16px; height:22px; margin-bottom:4px;" id="_textCustomKeyword" /><br>';
uroCtrlMisc.innerHTML += '<br><br><b>Use custom marker for MPs tagged as:</b><br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomElginMarkers" />[Elgin]<br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomTrafficMasterMarkers" />[TM]<br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomTrafficCastMarkers" />[TrafficCast]<br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomCaltransMarkers" />[Caltrans]<br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomTFLMarkers" />[TfL Open Data]<br>';
uroCtrlMisc.innerHTML += '<br><br><b>Popup mouse behaviour:</b><br>';
uroCtrlMisc.innerHTML += 'Mouse idle <input type="number" min="1" max="10" value="2" size="2" style="width:50px;;line-height:14px;height:22px;margin-bottom:4px;" id="_inputPopupDwellTimeout" /> *100ms<br>';
uroCtrlMisc.innerHTML += 'Mouse over <input type="number" min="1" max="10" value="2" size="2" style="width:50px;;line-height:14px;height:22px;margin-bottom:4px;" id="_inputPopupEntryTimeout" /> *100ms<br>';
uroCtrlMisc.innerHTML += 'Distance <input type="number" min="0" max="10" value="2" size="2" style="width:50px;;line-height:14px;height:22px;margin-bottom:4px;" id="_inputMaxJitter" /> pixels<br>';
uroCtrlMisc.innerHTML += '<br><br><b>Disable popup for:</b><br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitURPopup" />URs<br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitMPPopup" />MPs<br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitCamPopup" />Cameras<br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitSegPopup" />Segments<br>';
uroCtrlMisc.innerHTML += ' <input type="checkbox" id="_cbInhibitSegGenericPopup" />Speed limit info<br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitTurnsPopup" />Restricted Turns<br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitLandmarkPopup" />Places<br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitPUPopup" />Place Updates<br>';
uroCtrlMisc.innerHTML += '<br><br><b>Date/Time formatting for popups:</b><br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbDateFmtDDMMYY" pairedWith="_cbDateFmtMMDDYY,_cbDateFmtYYMMDD" checked />day/month/year<br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbDateFmtMMDDYY" pairedWith="_cbDateFmtDDMMYY,_cbDateFmtYYMMDD" />month/day/year<br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbDateFmtYYMMDD" pairedWith="_cbDateFmtMMDDYY,_cbDateFmtDDMMYY" />year/month/day<br><br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbTimeFmt24H" pairedWith="_cbTimeFmt12H" checked />24 hour<br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbTimeFmt12H" pairedWith="_cbTimeFmt24H" />12 hour<br><br>';
uroCtrlMisc.innerHTML += '<i>Unticked uses browser default setting</i>';
uroCtrlMisc.innerHTML += '<br><br><b><input type="checkbox" id="_cbWhiteBackground" />Use custom background colour</b><br>';
uroCtrlMisc.innerHTML += 'R:<input type="number" min="0" max="255" value="255" size="3" style="width:50px;;line-height:14px;height:22px;margin-bottom:4px;" id="_inputCustomBackgroundRed" />';
uroCtrlMisc.innerHTML += 'G:<input type="number" min="0" max="255" value="255" size="3" style="width:50px;;line-height:14px;height:22px;margin-bottom:4px;" id="_inputCustomBackgroundGreen" />';
uroCtrlMisc.innerHTML += 'B:<input type="number" min="0" max="255" value="255" size="3" style="width:50px;;line-height:14px;height:22px;margin-bottom:4px;" id="_inputCustomBackgroundBlue" /><br>';
uroCtrlMisc.innerHTML += '<br><br><b>Replace "Next ..." button with "Done" for:</b><br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitNURButton" />URs<br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitNMPButton" />MPs<br>';
uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitNPURButton" />PURs<br>';
uroCtrlMisc.innerHTML += '<br><br><b><input type="checkbox" id="_cbHideAMLayer" />Hide Area Manager polygons</b><br>';
uroCtrlMisc.innerHTML += '<b><input type="checkbox" id="_cbDisablePlacesFiltering" />Disable Places filtering</b><br>';
////uroCtrlMisc.innerHTML += '<b><input type="checkbox" id="_cbDisablePendingQuestions">Disable UR Pending Questions confirmation</input></b><br>';
uroCtrlMisc.innerHTML += '<b><input type="checkbox" id="_cbDisableTabStyling" />Use default tab styling</b><br>';
uroCtrlMisc.innerHTML += '<b><input type="checkbox" id="_cbHideEditorInfo" />Hide sidebar editor info</b><br>';
uroCtrlMisc.innerHTML += '<b><input type="checkbox" id="_cbEnableDTE" />Drive Tab Enhancement (DTE)</b><br>';
uroCtrlMisc.innerHTML += '<br><br><b>Settings backup/restore/reset:</b><br>';
uroCtrlMisc.innerHTML += '<input type="button" id="_btnSettingsToText" value="Backup" /> ';
uroCtrlMisc.innerHTML += '<input type="button" id="_btnTextToSettings" value="Restore" /> | ';
uroCtrlMisc.innerHTML += '<input type="button" id="_btnResetSettings" value="Reset" /><br><br>';
uroCtrlMisc.innerHTML += '<textarea id="_txtSettings" value="" /><br>';
uroCtrlMisc.innerHTML += '<input type="button" id="_btnClearSettingsText" value="Clear" /><br>';
/*
uroCtrlMisc.innerHTML += '<br><br><b>Debug:</b><br>';
uroCtrlMisc.innerHTML += '<input type="button" id="_btnDebugToScreen" value="Show debug data" />';
*/
// footer for tabs container
uroCtrlHides.id = 'uroCtrlHides';
uroCtrlHides.innerHTML = '<input type="button" id="_btnUndoLastHide" value="Undo last hide" /> ';
uroCtrlHides.innerHTML += '<input type="button" id="_btnClearSessionHides" value="Undo all hides" /><p>';
// footer for AM list
uroAMList.id = 'uroAMList';
window.addEventListener("beforeunload", uroSaveSettings, false);
//uroRealWazeBits();
}
function dteAddHeader()
{
if(uroMTEMode) return;
if(!uroInitialised) return;
var rlcObj = document.getElementsByClassName("result-list-container");
if(typeof rlcObj == "undefined") return;
if(typeof rlcObj[0].children[0] == "undefined") return;
if(typeof rlcObj[0].children[0].innerHTML == "undefined") return;
var thtml = rlcObj[0].children[0].innerHTML;
if(thtml.indexOf('Full drive history') == -1)
{
thtml += '<br><br><i><small>Full drive history goes back to '+dteOldestFullDrive.toDateString()+'</small></i>';
rlcObj[0].children[0].innerHTML = thtml;
}
}
function dteGetData()
{
var loc = 'https://'+window.location.hostname+Waze.Config.api_base+'/Archive/MyList?minDistance=1000';
loc += '&offset='+dteOffset+'&count=5';
var dteReq = new XMLHttpRequest();
dteReq.onreadystatechange = function()
{
var foundMissingDrive = false;
if(dteReq.readyState == 4)
{
uroAddLog('drive data request, response '+dteReq.status+' received');
if(dteReq.status == 200)
{
if(dteReq.responseText !== "")
{
var drives = JSON.parse(dteReq.responseText);
var loadedDrives = drives.archives.objects.length;
uroAddLog('received '+loadedDrives+' drives');
if(loadedDrives != 5) foundMissingDrive = true;
for(var loop=0; loop < loadedDrives; loop++)
{
if(drives.archives.objects[loop].hasFullSession === false)
{
foundMissingDrive = true;
}
else
{
dteOffset++;
dteOldestFullDrive = new Date(drives.archives.objects[loop].startTime);
}
}
}
else
{
foundMissingDrive = true;
}
}
if(foundMissingDrive === false)
{
dteGetData();
}
else
{
uroAddLog(dteOffset+' full drives in history');
uroAddLog('oldest drives are on '+dteOldestFullDrive.toDateString());
if(dteOffset < 5)
{
dteOffset = 5;
uroAddLog('insufficient full drives, using standard drives tab');
}
else if(dteOffset > 50)
{
var nPages = Math.ceil(dteOffset / 50);
uroAddLog('too many full drives for a single tab page, splitting over '+nPages+' pages...');
dteOffset = Math.ceil(dteOffset/nPages);
}
if((dteOldestFullDrive - dteEpoch) > 0)
{
var totalDrives = 0;
if(W.model.archives.additionalInfo !== null)
{
totalDrives = W.model.archives.additionalInfo.totalSessions;
}
if(totalDrives !== null)
{
uroAddLog('updating drives tab...');
W.map.controls[dteControlsIdx].sidePanelView.ResultsPerPage = dteOffset;
uroAddLog(totalDrives+' drives in history');
W.map.controls[dteControlsIdx].sidePanelView.setSessions(totalDrives);
W.map.controls[dteControlsIdx].loadSessions(0);
}
setInterval(dteAddHeader,250);
setInterval(dteCheckDriveListChanges,250);
}
}
}
};
dteReq.open('GET',loc,true);
dteReq.send();
}
function dteSetNewTabLength()
{
uroAddLog('altering ResultsPerPage parameter...');
var t = document.getElementById('sidepanel-drives');
t.style.overflow = 'auto';
t.style.height = (window.innerHeight * 0.6) + 'px';
dteOffset = 0;
dteGetData();
}
function dteListClick()
{
dteClearListHighlight();
this.style.backgroundColor = "lightgreen";
dteArmClearHighlightsOnPanelClose = true;
}
function dteClearListHighlight()
{
var drivesShown = document.getElementById('sidepanel-drives').getElementsByClassName('result session').length;
if(drivesShown > 0)
{
for(var loop = 0;loop < drivesShown; loop++)
{
var listEntry = document.getElementById('sidepanel-drives').getElementsByClassName('result session')[loop];
listEntry.style.backgroundColor = "";
}
}
}
function dteCheckDriveListChanges()
{
if(uroMTEMode) return;
if(!uroInitialised) return;
var drivesShown = document.getElementById('sidepanel-drives').getElementsByClassName('result session').length;
if(drivesShown > 0)
{
var topID = document.getElementById('sidepanel-drives').getElementsByClassName('result session')[0].getAttribute('data-id');
if(topID != dteTopID)
{
dteTopID = topID;
for(var loop = 0;loop < drivesShown; loop++)
{
var listEntry = document.getElementById('sidepanel-drives').getElementsByClassName('result session')[loop];
var driveID = listEntry.getAttribute('data-id');
var driveObj = W.model.archives.objects[driveID];
var driveSecs = Math.floor((driveObj.endTime - driveObj.startTime) / 1000);
var driveHours = Math.floor(driveSecs / 3600);
driveSecs -= (driveHours * 3600);
var driveMins = Math.floor(driveSecs / 60);
driveSecs -= (driveMins * 60);
var trueTime = (driveHours+':'+("0"+driveMins).slice(-2)+'.'+("0"+driveSecs).slice(-2));
listEntry.getElementsByTagName('span')[1].innerHTML = trueTime;
listEntry.addEventListener("click", dteListClick, false);
}
}
}
}
uroInitialise();