UROverview Plus (URO+)

Adds filtering and pop-up infobox for UR, MP and camera markers

当前为 2015-10-21 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name UROverview Plus (URO+)
  3. // @namespace http://greasemonkey.chizzum.com
  4. // @description Adds filtering and pop-up infobox for UR, MP and camera markers
  5. // @include https://*.waze.com/*editor*
  6. // @include https://editor-beta.waze.com/*
  7. // @grant none
  8. // @version 3.55
  9. // ==/UserScript==
  10.  
  11. /*
  12. TO-DO ITEMS
  13. =======================================================================================================================
  14. Bug fixes - MUST BE CLEARED BEFORE RELEASE
  15. =======================================================================================================================
  16.  
  17.  
  18.  
  19. =======================================================================================================================
  20. Things to be checked
  21. =======================================================================================================================
  22.  
  23.  
  24.  
  25. =======================================================================================================================
  26. Proposed functionality
  27. =======================================================================================================================
  28.  
  29. Flush settings to localStorage whenever a change is made, or at least before opening a new tab via a popup
  30.  
  31. User-defined setting presets
  32.  
  33. Extend unstacking to cameras
  34.  
  35. Place filtering
  36. - by last user to edit
  37.  
  38. Localisation
  39.  
  40. First-run information
  41. - show quickstart guide to URO features if no existing settings are present (i.e. new installation)
  42.  
  43. =======================================================================================================================
  44. New functionality in progress
  45. =======================================================================================================================
  46.  
  47. Addition of segment and place watchlist functionality
  48. */
  49.  
  50. /* JSHint Directives */
  51. /* globals $: */
  52. /* globals W: true */
  53. /* globals I18n: */
  54. /* globals loginManager: true */
  55. /* globals selectionManager: true */
  56. /* globals OL: true */
  57. /* globals OpenLayers: true */
  58. /* globals Waze: true */
  59. /* globals unsafeWindow: true */
  60. /* globals Components: true */
  61. /* globals require: */
  62. /* jshint bitwise: false */
  63.  
  64. var uroVersion = "3.55";
  65. var uroReleaseDate = "20151021";
  66.  
  67. // list of changes affecting all users
  68. var uroChanges =
  69. [
  70. 'TBR popups now work again',
  71. 'TBR editing UI can be opened from the TBR popup',
  72. 'Tweaks to popup positioning',
  73. 'Settings restore works properly with empty camera watchlists',
  74. 'Various performance optimisations'
  75. ];
  76. // list of changes affecting only WME Beta users
  77. var uroBetaChanges =
  78. [
  79. 'SRS functionality disabled as this is now provided natively by WME'
  80. ];
  81.  
  82. // true enables debug output during script startup
  83. var uroShowDebugOutput = true;
  84. // true keeps debug output enabled after script startup
  85. var uroPersistentDebugOutput = false;
  86.  
  87. var uroCtrlsHidden = false;
  88. var uroCurrentTab = 1;
  89. var uroFID = -1;
  90. var uroShownFID = -1;
  91. var uroShownPopupType = null;
  92. var uroInhibitSave = true;
  93. var uroPopupTimer = -2;
  94. var uroPopupDwellTimer = -1;
  95. var uroPopupShown = false;
  96. var uroSetupListeners = true;
  97. var uroRootContainer = null;
  98. var uroPlacesRoot = null;
  99. var uroMaskLayer = null;
  100. var uroCustomMarkerFID = null;
  101. var uroCustomMarkerType = null;
  102. var uroConfirmIntercepted = false;
  103. var uroCustomMarkerList = [];
  104. var uroPendingURSessionIDs = [];
  105. var uroRequestedURSessionIDs = [];
  106. var uroPlacesGroupsCollapsed = [];
  107.  
  108. var uroMouseInPopup = false;
  109. var uroURControlsIdx = null;
  110. var uroProblemControlsIdx = null;
  111. var uroTurnsLayerIdx = null;
  112.  
  113. var uroNullCamLayer = false;
  114. var uroNullOpenLayers = false;
  115. var uroNullRootContainer = false;
  116. var uroNullURLayer = false;
  117. var uroNullProblemLayer = false;
  118. var uroNullMapViewport = false;
  119.  
  120. var uroURDialogIsOpen = false;
  121. var uroSelectedURID = null;
  122. var uroPendingCommentDataRefresh = false;
  123. var uroWaitingCommentDataRefresh = false;
  124. var uroExpectedCommentCount = null;
  125. var uroCachedLastCommentID = null;
  126.  
  127. var uroPlaceSelected = false;
  128. var uroMouseIsDown = false;
  129. var uroBackfilling = false;
  130. var uroHidePopupOnPanelOpen = false;
  131.  
  132. var uroUserID = -1;
  133.  
  134. var uroDOMHasTurnProblems = false;
  135. var uroBetaEditor = false;
  136. var uroPracticeMode = false;
  137. var uroWazeBitsPresent = 0;
  138.  
  139. var uroOWL = null;
  140. var uroDiv = null;
  141. var uroControls = null;
  142. var uroCtrlURs = null;
  143. var uroCtrlMPs = null;
  144. var uroCtrlPlaces = null;
  145. var uroCtrlCameras = null;
  146. var uroCtrlMisc = null;
  147. var uroCtrlHides = null;
  148. var uroAMList = [];
  149. var srsCtrl = null;
  150.  
  151. var uroCWLGroups = [];
  152. var uroCamWatchObjects = [];
  153. var uroSegWatchObjects = [];
  154. var uroPlaceWatchObjects = [];
  155.  
  156. var uroFriendlyAreaNames = [];
  157. var uroAreaNameHoverTime = -1;
  158. var uroAreaNameHoverObj = null;
  159. var uroAreaNameOverlayShown = false;
  160. var uroANEditHovered = false;
  161. var uroANEditBox = null;
  162.  
  163. var uroPrevMouseX = -1;
  164. var uroPrevMouseY = -1;
  165.  
  166. var dteControlsIdx = -1;
  167. var dteOldestFullDrive = new Date(0);
  168. var dteEpoch = new Date(0);
  169. var dteTopID = '';
  170. var dteClearHighlightsOnPanelClose = false;
  171. var dteArmClearHighlightsOnPanelClose = false;
  172.  
  173. var uroUserTabId = '';
  174.  
  175. var uroTBRObj = null;
  176.  
  177. var uroUnstackedMasterID = null;
  178. var uroStackList = [];
  179. var uroStackType = null;
  180.  
  181. var uroIcons =
  182. [
  183. // stuff used within the URO tabbed UI
  184. // 0 = group collapse/group expand
  185. [
  186. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94CAhYRIqo78SIAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAADtJREFUKM9j/P//PwNJgCQN////ZyFeGyMjIwMDAxMDiWAQamDB9Bb+kKTMBmICdxgFK64AxZKiSE3eAAOXFRnJRfN6AAAAAElFTkSuQmCC",
  187. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94CAhYRDHbt/O0AAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAAE5JREFUKM+9UkEKACAMcmP//7IdgghqMQvytoOKTiMJCRKBZNRpZgbAIcIzsa5XJcgOB8Qaaz3nSt4chlLX3nb9OXRlL7cO2V83I1Dn3QDKfhshMqWScAAAAABJRU5ErkJggg=="
  188. ],
  189. // 1 = addtogroup active/addtogroup idle
  190. [
  191. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94BGhYVKhKBubQAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAAEZJREFUOMtjYBjygBHB/P8fjzJGIszCZQA+gxkYWIjTABPDdAkL8U7G7hIcYcDISEGYwDQSFyZM5AQckYA4F7CQZ8goQAYAMCsd/TxbqrwAAAAASUVORK5CYII=",
  192. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94DAw0tDee2t8AAAABPSURBVDjL7ZAxCgAgDAMT6cP6dH+mUwfBaugmeFMpbTgCPA9j6H2M7MidvCZlAadgADDlIXY7E1OVM5NtB+5kuZN4VDtpleIkVAOrhHxWJoJkNv2QAd51AAAAAElFTkSuQmCC"
  193. ],
  194. // 2 = goto active/goto idle
  195. [
  196. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94BGhYfLAEN9AsAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAAGdJREFUOMutk+EKACEIg7fD93/l3Y+uP5kmeYMgkH0NTUpCRw+acgBynHaCKsgBlpaIhDJQtQchaAtIBuNAlAQSV7OUwPYYGX2kL6Zi37hYYk6NU1ZPui/Y4XWeVsWSDpdkt8bftvEFOy0jJkeygWMAAAAASUVORK5CYII=",
  197. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94DAw0tFm3TfiwAAABySURBVDjLrZNRDsAgCEPp4r306HKy7sMsMRMckZH4ZfqoYEFSMnVJshYAME7aQRS0AOaR9C5UFe5AoRnsQCbAW4wFAklRlaNd1ipIrxHeRwKGZeuuNcEjK554J5x7lohNS+g+4d39Kyqug2jGyqnwtzTengM2Gxwa0GsAAAAASUVORK5CYII="
  198. ],
  199.  
  200. // replacements for native UR/problem markers
  201. // 3 = normal/selected open roadworks UR
  202. [
  203. "data:image/png;base64,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",
  204. "data:image/png;base64,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"
  205. ],
  206. // 4 = normal/selected closed roadworks UR
  207. [
  208. "data:image/png;base64,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",
  209. "data:image/png;base64,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"
  210. ],
  211.  
  212. // 5 = normal/selected open closure UR
  213. [
  214. "data:image/png;base64,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",
  215. "data:image/png;base64,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"
  216. ],
  217. // 6 = normal/selected closed closure UR
  218. [
  219. "data:image/png;base64,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",
  220. "data:image/png;base64,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"
  221. ],
  222.  
  223. // 7 = normal/selected open event UR
  224. [
  225. "data:image/png;base64,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",
  226. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAoCAYAAABw65OnAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94ICBQjNnsYXYUAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAADLVJREFUWMOdWGtsXVV2/vbjPO/D13FsxyR2Lmk9JoVQE08zNaEaCw1UCWJaIYXOlCIof6ZDB4r4M4JRpy+qqkLNrymU/AGiQaJCU/gBRCiUXiSCiwU0RZg8SMgtdrh2rq8f9/rec/fZj9Uf1zZ5UZief2fr7LO+vb611l7fYvj1Hw6ATUxMsEajwdYXc7kclUolAkAA3K/zQ/YNv2ETExO8XC7LYrEojTFekiQiCAJer9dZPp8npZSLoshKKXW5XDbFYtGUSiW3Bor+LwPia4zzsbEx6ZwL8/l8JpfL5ZMkKTjnugFsklJ2+77fzTnPW2tz1tpYKRUWCgXfWiu01uy6666jSqXy//IEm5iYEEopD0AkhMg65/J79uwZvOeee24bGhr6djab/Y0wDDdzzn3nXNputxdWV1fPfv755++/8MILR6empmY453Vr7SqAJAgCXSqV7NW8cjUQbGxsTIZhGLbb7azneYU77rhj5L777vvR1q1bv8c5l191oiRtIvIzcM6Z8+fPv/n8888/89prr53SWi+HYbjabrfbH3zwgbkcCLsaACllFARBV5qmvQcPHvyTPXv2/JhxFnLGv3GwOXIgR+2pqamnH3300V/6vl9VSq0YY5LLgbDLKdBaR4yx7jiOB5555pmfF4vF/d/UcFKvYuX8NNorcyCjIPwMslu+hSWdff3BB3/8t61Wq0JES57nJRdTc3FgiiRJwkKh0MUY2/Lss8/+zfbt2/cz9vUJRERY+eIEls5NgYwG4MCIw+kWWgtlsNbs8P4/+rOtr7zyypRzTn/66aem2WxeAYLt27fPi+M4p5TqO3jw4J/eeOON9zDGoLWGSVpwxkF43lUBNBdn0Dh/Ap4fg0sJxgQ64AnkLEgr8PaF4d+97W716quvnuzr60tvuOEGfebMGbcBYmJiQi4tLcVCiE2333776L333vt31lpZeW8KZ195GfMffIjzk+9i5t/fRG7HDvi5XId350BwWDjxNoQfQvghILzOAcnBOdMBai10cwlDw7tGa/X2u+fOnavV6/V0ZGTElMtlx9biwr/++uu7e3t7tz333HP/uKWv/9ZP//VFcE8C1sFqDdNOkTQbQL2Oxd/7Hs75ObTSFBIOt3StYjDvwfdjMBCMasGZNrRqwqoENk1gdAtB9zbwLd956/777/9ptVqdnZ6eXgKQcgB87969fhiGmd27d1+7bWjo1v858jrCbBZhNosgl4Mfx5BhAMrlcGbf3ajmehAHPvJhCAiJN2oZPHuOgUh3Tk8Ozpo1vhzAHEAO6UoFg4OD3929e/e1YRhm9u7d6wPgYq0oZaIo6nn44Yd/kFVqTM3Nwc9mEWQy4EKAiGCtxeldNyMKAwSehOS840MCLDnULcf7Cym+nWuDrIGzGtakIJvCag0iAyJC37f28lwut/T2228fT9O0NTw8rHipVBLWWl8plRkaGrqpce4cuJSQvg8/jsF8D5wLfPybo8gEAbJhiHwYIvIEAs+D70kEQiDkQJUifLDMoHQCaxTI6k5gwgIAZJBFS61iaGjoJqVUxlrrl0olwcfHx3kQBH4URWGhUCi2FxbgnIPVBmmrBacNLDmQF8CXEhnfQyYMEHgBPCEguADjDByAAOHoYgbMKDjdhtMpnE1BVgMA4p4hxEEWhUKhGEVRGASBPz4+zmUul+O1Wk0SkR/HcUEr1clZxmBSCWcMLpAEA8ESwTgH5qhTEYlAIIA6dzeBIWUcOml0ssemcGkKcICcRW5gpAMmjgtpmvppmsqenh4u0zRlUkpORJxz7nEpkbYSkLVgjME5h3rYBWUthNZgIBAxtE2KRGtoY2HIwRBgOECOw6QtMC46Hlir9CzMIdd7bach4dwjIi6l5GmaMgkAURRRu92GtVZH/f3e0okTMKkHLjicNRDKoJ1uB8hBGw+05pG2TtHWFql1aILBOga5lglkv+xryFkM7v5DrFdfazv8RFFEACB936dWq+V837fNZnOxe3i4v3LsGHgcb3gititoFVMY6yCFAYHB2o5xZTSalqBcJy5CMnDOgXO+UVE3j0wg7tqyAarZbC76vm+NMS6OY5KNRsMJIYxzLq3VauWBrf39Mp+HnZ+HEwKMCFwpNJWCsraTmgCMc7AgrFqg4RhSdFL2d/iFDQAA0Pdbt6IwOLqxpnSCxcXFc865FIBpNBqOT05OuiRJtDEmOXXq1PHQj7Hzj38IMT8PUatBLC2Br65iZOodLGmLZW2wrA1WLKFqGGpOoL1GvE8OP/j9O7F1zw+hgq3Y/t0foTA4CrFWawAg8CKcPHnyv40xSZIkenJy0vGJiQnr+75ijLUOHz78jjFG5Qeuwbaf/AQ8TQHX4Xaw8hlWU4d5K1B1AjUnsEocDgAjgiNg3/ZuMO5BeB66tu6E74cbANbjwRijDh8+/A5jrOX7vpqYmLC8VCq5IAhSIURzdna2Mj09XQKAgbExDD36KJCmYNaCWYsD5fc7cUIdrtna6YgxjIQWd+waBucccb4PXtwNIb1LAADA9PR0aXZ2tiKEaAZBkJZKJScAoFwus3w+L6SU3unTp2v79u271fO8INvfj4Hvfx8Na5EM9OGWB/8co5szmJxZQMoEGAM0MYzlOP7i1j3g/Mv2ZGWphq7CpksAKKUajz/++D9Vq9VyvV6vTU1NtQDYjV3Dw8MQQojl5WVEUdTatWvXdxhjjIjg+T74pm50bxlAVxxh//A1yNg2aLmGu2/Yjj+4aeclxogIYZyBlPLiNXrxxRf/5ejRo/8phJgPgmBlZmZGAXAbIGZmZtDb2wtrLT788MPFa665JnvkyJHrxsfHEfX0QMYxfD8AYwyMcYSej55Nm5Ahhc2FwqWNKmNgjIFzDiLCRx99hI8//vjlJ5988lda6/Na68X33nsvAWDW1RTW2iwNoJXJZGpa6/NPPPHEs9u3b//V/v2dFjOby29EOABs7c5hbLAXffnsFd3WXGUWjHVqyWOPPYa77rrrwkMPPXREKfVFJpOpAWit2buix8TIyAgBcERkAZhjx459duedd84fOnToprm5Oblz5wiCILzEYDtJEEXxBg2MMSwtLeGpp57GAw884Ky1r3PO/yqO41NCiAtSykYQBKpcLrurKrByuUzFYtFJKW2SJFoIoU+dOlUxxrwrhOg7cuTI1ttuu50J8eW2djtBGEYbFCil8MyhQ3T8+PHpbDb789XV1SMAzqdpeiGO4zqA9uUi6AoZuA4kTVMTBEG6urqqtNaNL7744r8WFmrHTp8+PTo+Pp7z1ppenaYIwwhEhMXFRfzlz37W/I9S6aetVuvlZrN5NkmSShRFC1rrRhAE6moq7KpatFwuU6VScTt27DDtdjsVQigAbcZY++zZsx82Go3xQqGQ6evrQ6oU/CBAu92GMab5by+//NeLi4sntNazRDTvnFuK47g1OTmZrlFAV5P5XykNG42GjaJIGWManPOac24OwOzx48f/oVgs1tduRBARgiBwTz/91KFyuXzKWlvhnC9orRtRFKlqteouVvhfp8rZgQMH+CeffOL19/f7mzZt8hljgZTSt9ZKrbUMw9BbXFzkSZKs3HzzzWMLK3OskN+Et9566+gvfvHPb3LOF4QQDc65TpIEUkqxefNmMTAwILdt28a7urpYtVr9SjrYxMSEmJ+fDwYHBzPd3d05znkXEeWllF2c83wQBDnGWMYYE588eVIVi8VoZHhncWbm8/IjjzzyEoBVznnKGOMAgiiKImNMnKZpBCBoNBoyDEOMjo7SmvC5IkXXhyCx53kFY0y37/vdQohurXU3Y6ygte7inOcBbNNa9x07dqwxOvrb/U888ffvzM/NgQsRAIAQQhJRhoiyADJCiIhz7vu+L3zfd0op29fX5yqVypUgxsfHJWMsApAhohznPAMgttaGUspQSulrrX0i2kzkIq2NfOONNz6rVqsKRA6MOc65BmCISAghhJRSWGu553mUpqnlnKe+76dpmupKpeIuV+UcgHfLLbfEAHJKqZzneTFjLCQiz1orGWOCc84ZY+Kid6GUckIIK4QwRGSJyDLGnJTSADBKqZSIEq110xhTJ6Lm9PR0G4AFQBcPPOjAgQOmWq0mjUbDKaVUFEX+8vKyDMPQ45wLay231kJKyaWUvNVqrUc7hWFIjDGy1jpjDIVhSEopY621QRAYxphmjCmttQKQYr1Bv9qQZG1QImq1mujp6eG5XI43Gg2Ry+WYMYZZa9laarJ1ZcYYgxACQoiNqE+SxAkhKAxDd+bMGbdjxw5Xr9dtb2+vu7xgsa+ZZbG1tEW1Wr1kZLj+GKMhhMTlc4z1keKBAwfw0ksv0UUX5RXF6n8Bf5Lu7gqeuyEAAAAASUVORK5CYII="
  227. ],
  228. // 8 = normal/selected closed event UR
  229. [
  230. "data:image/png;base64,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",
  231. "data:image/png;base64,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"
  232. ],
  233.  
  234. // 9 = normal/selected open note UR
  235. [
  236. "data:image/png;base64,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",
  237. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAoCAYAAABw65OnAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94IGgkbBqSwfuUAAAqJSURBVFjDrVhtbFRXen7Ox/0c3/EMYfBagBnAkSEQNcYE7+BEHVksXch+KBsZ7YpUtKuETRVloyBVlbLSNqJCldqIVG1RRfMjirT8Iaqi/RGUDUmYVQjeQCBfJtjEMWPHZLAH2+O5Ht+599xzTn+s7QK1N8nG7587Ojpz3/e8z3Pe+z4vwTc3CoDk83ni+z6ZX/Q8TxcKBQ1AA1Df5IXka+4h+XyeFotFns1meRzHRhAEzLIsWq1WSTKZ1GEYKsdxJOdcFIvFOJvNxoVCQc0Fpf+UA/YVzmlHRwdXStnJZDLheV4yCIKUUioNYAXnPG2aZppSmpRSelJKNwxDO5VKmVJKJoQgmzZt0qVS6c/KBMnn8ywMQwOAwxhrUEold+zYsXb//v3fa2lp2d7Q0LDRtu2VlFJTKRXV6/WbMzMzn4+MjLx/4sSJ0+fPn/+CUlqVUs4ACCzLEoVCQS6WlcWCIB0dHdy2bbterzcYhpF66KGH2g4cOPCL1atX76KU8qVOFEQ1OGYCSqn4+vXrb7788svHX3vttQEhRMW27Zl6vV6/ePFifGcgZLEAOOeOZVmNURRljh49+uiOHTv+jlBiU0K/NtmUVtBK18+fP/9fhw4d+o1pmuUwDKfjWi242Nd3WyDkTgiEEA4hJO26bvPx48d/nc1m9+JbWrFYPPWLgwcPz9ZqJV2pTBlCBIXPPlsUGtbU1JTI5XKru7q6tl+7du2UXka7NjR0Krdly/bOlpbVTQ0NiVsvxfwPsmfPHsN1XS8Mw1UvvPDC39577737sVymNVLp9N2bh4fD377/fn+T60ZbmprE4OSkmi88yOfzbHx83NZaJ/fs2bOls7PzIJbTCAH+8Ad0fvDBwR+sX79Fa538cmbG7sxm2UL1KxQKrF6vO5ZlpR5//PHHGGMWltuOHwdmZqzHg+Axg9LUbBw77xWLDAChAGhXV5dp23Zi27Zt69etW9e9nDAAAN58ExgbA/v8c6zt6/vLzen0eouxxM5czgRAaT6fJ0II03XdxCOPPLJr2WGQEnj1VehqFRgfR6AUyyUSu7xMJhFLaebzeUILhQKTUpphGCZaWlralz0Lp08D4+MgfX3QAIoAUlK2x6aZkFKahUKB0VwuRy3LMh3HsVOpVHZZs+D7wLlzQLEITE+jDmAUwMYf/zibaGiwLcsyc7kcpZ7n0TAMeRRFpuu6qW916jvt8mXgk0+gr16FnguAt7Rgzfe/n4qEMMMw5J7nURpFEeGcU601JYQYf/apb4tJA7VZ4K23oIeGQGo1xAAGAXxn716kOjoMrTXlnNMoiv74MXAcRwOAUkosRxYIIZCzZahPzoNcGwWkxGcA2MqVWPPzn0NKKW71S03T1HEcK9M0Za1Wm/y2WZg34c5g8m+y8H/YjBqAYQCrurvReP/9qNVqk6Zpyjm/mvu+rxhjsVIqmpiYKFqO0WQZzrcnJmMItjZg+h86QO5pRPpsCXcfPoJQBJiYmLimlIoAxL7vK9rb26uq1bKI4zgYGBj40OT2N0BCL7lWqdQxWiwDQxNgrW1o/83vkWhrhWU4GBgY+CiO4yAIAtHb26tY5/ZtZHLK54xxZ3h4OOru7n5oZGSEnzlzBslkEpZlgfP/62OUUiBzEBBCUK/XUSqV8MYbb4AxBs45Zmdn8d57V3Dol/+NbbmfYvvP/hncbYTWGlLK8LnnnvvP6enpUcbYVGtra50AoLlczp2enl4lhFi/a9euvx8cHPyrrVu3oq+vDzt37sSDDz6IFStWYPPmzbBtG/V6HVeuXMHk5CTeeecdnDt3DvP7m5ubIYRAS0sLevbtQ8e2bbdl6qOPPvrdU0899a9a62uc8/FCoTDLAeje3l7R1tZWS6fTU1NTUycfffTRnfv27fMopTh58iQuXLiATZs2obW1FbZtQwiB4eFh9Pf3o7W1Fc8++yyUUjh58iR2794N13XR39+Pbe3tCxARQhCGoX/06NGTQoipmZmZWl9fnwCg56nNurq6XEJIhhCSPXjw4I/279//S0L+P/WVUqCULrwYAOJ4FkRJEGqCMHNhfX7PHE/0iRMn/v3YsX/7LZHhsIpV+b0PPp0FIBe6my+++AKZTAZSSly6dGmyubm54fXXX9/U2dkJAAvYnz59+jbs33rrDH76k59gY8bA3X/RBUIIgiDAjRs3Fnhy4cIFDA0NvXr48D/9z/hY+ToIm/zgk/4AQHxnj0k7Ojpsz/OStVrtO4ZhrHvmmWf+euPGjY98Hey33HPPkjwplUrj5XL5V57nXcxkMqUoiqoXL16szyu128RPW1ubBqC01hJA/O677w7dvHlz7KWXXmrfu3cvP3LkCLq7u8EYwxNPPIGHH34YmUwG92/fjiAIcOnSJXz88cfIZrM4cuQI3n77bdXQ0HBKa/2PlmUNGIYxnkgkfMuywmKxqJZs+fP5PANg+77vmaa5kjHWlEwm123evPmx559//ruLtvdzPLnVnnzyyb5qtfofQRAMffnll2NRFN30PM8HUL9TBJGl1Jfv+6brugnf91O2ba9gjDVxzte6rnvo1KlTG5YqYAcOHJiuVqvPMcaKo6OjN8IwnPA8rzI7O1vzPC9aTIWxJXSCLpVKasOGDXG9Xo8YYyGAOoB6EAQf9/f379i9e7d35/8qlUrl3Llzh69evTpQqVRGtdZjSqkp13Vne3t7ozkI9GIyf0lp6Pu+dBwnjOPYp5ROKKVuKKVGr1+//i++70/PVUAopaCUUi+++OJLH3744aCUskQpvSmE8B3HCcvlsrpV4X+VKic9PT30008/NZqamswVK1aYhBCLc25KKbkQgluWZVQqFVqr1aZ37tzZUQ2miGMlcObMmdPHjh17E8BNxphPKRVBEIBzzlauXMmam5v5mjVraGNjIymXy0vCQfL5PBsbG7PWrl2bSKfTHqW0UWud5Jw3UkqTlmV5hJCElNK9cuVKmM1mnXs2bc2OjIwUn3766VeklDOU0ogQQgFYjuM4cRy7URQ5ACzf97lt27jvvvv04ODgAjS3BjE/BHENw0jFcZw2TTPNGEsLIdKEkJQQopFSmtRar5FSrjp79qzf3t7edPjw4bPlchkArD9+xRnXWie01g0AEowxh1JqmqbJTNNUYRjKVatWqVKppO+8HSyXy5mEEI8Qko7jOG0YRgMARwhhmqZpEEJYFEWG1roFQDKOY4dzzqWUSmsdEkJmOOfjlNIprXXMGIsJIUIIEZqmWQuCoGoYxpRpmtO+79fmxwTkDpIaDzzwgAvAC8PQMwzDJYTYWmtDSskJIYxSSgkhTErJOeeMEMKEEEprLRljsdZaaq0lIURxzmMAcRiGkdY6EELU4jiuaq1rly9frgOQAPStAw/d09MTl8vlwPd9FYZh6DiOWalUuG3bBqWUSSmplBKcc8o5p2EYEq01IYRoy7I0IURLKVUcx9q2bR2GYSyllJZlxYQQQQgJhRAhgGiuZOtFK+bcoIRNTEywu+66i3qeR33fZ57nkTiOiZSSAMD88/aOji2wPggCxRjTtm2rwcFBtWHDBlWtVmUmk1Ffp2Leuk7mri3K5fJtI8OvsvmRYk9PD1555ZV5h4tO8v4XQ4S+ZuwgEBYAAAAASUVORK5CYII="
  238. ],
  239. // 10 = normal/selected closed note UR
  240. [
  241. "data:image/png;base64,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",
  242. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAoCAYAAABw65OnAAAAAXNSR0IArs4c6QAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94IGgkfK4UD55QAAAnbSURBVFjDrVhrbBxXFf7uvfPaXc9616+NEztZO46c5lFInDa4DWIVhUdbUIHKqKiCUtQWEKIIJIQEQm0jkCqeP+AHET8KEpWACCp+UApJwRKlafNommeT4job1+l6vfZ6vbO7s7Nz7z38yNokrk3T1ufPSDN35nznO9+ce85leOfGAbB0Js0CL2AePACA4RpUGi0RAAKg38kH2Q2uYelMmpeyJSOejhskyQz9UFTsCtdlzXicEwWkRUQoGAgb2YZ00o4sjZZ0ExT9PwfibZzzoaEho6zLjhW3YqZrxkM/TGitk2WU22AgySyWBEecFLla6agOtCMSwiJFgkJi0c1RauQa74oJlslkRBAE5gQmIhBoIU3xjls7ehP3JT5cXF/cdb7l/Ebt6A5wWNBo8DqfsSrW67GJ2HE8hUP1o/U3GGdlpliFgfltdluYHc2q5VhZDgTrHuo2hCMcWZctnuklondFB3vv7/3SqXWn9imujBVDagCwAGjI2JXY4ehvogdqf6ldRIhS0klWUvVU/cSJE3IpELEcAGawCDd5QkOn2E/ZA7P3zj6Ra81tJk4cN5JcBh7Gw4Hanton3W2uloflpagZ1a3UqtYkkzo3Pb0iCJbOpAU4IhBI8ghfm/p16vHx7eOfB4dxQxJ+i6Jg+L3+sLXP6o3+NfJym0xIw/flxkRCZYtFWg6ECP3QsRN2KxjWdD7Z+fjJ9Mk7sQoWJsJN/Xs2rhNP1o6qSiUcKxRktdFY1McigQN3DJhG1HBlILv6f9b/wLHtx+7DahkBU8mpTb+//EDw5+PHL6Si0cbWVCocKxb1QuFBOpMWlemKQ0TxtXes3Xp89/GHsZrGAHrxCHafPPnwx/v6thJR/M1KxdmdTovF6pcdzQpZlxFu84R+SD/YEA0bq20HDgCViv2Q7z9ocp6oSRl5KZsVABgHwHtu77GEI2LJncm+0xtO713NNAAAHT4E5PMQr7+O3rNnP3RTMtlnCxG7bXjYAsB5OpNmOtSWETVisXti+1Y7DVAAnn4aVC4D09PwtRbDsdg+t7MzJpWyMpkM49nRrNBKWzKQsbn1cztWmwUcAjA9DXb2LAhAFkBCqR3SsmITasIaHR0VvGe4hwtbWCIinEKikF5VFjyAXvgekM0C8/OoA5gEsPHuu9Nvtkw5whZWz3AP57ZrcxlIQzWUVY6WE+8p6qV2DsCZM6DXXgM1ARjr12PHxx5NqFBZMpCG7dqch42QcYNzELhk0nzXUS8FVQXoue+DxsfBqlVIAGMA9t05ATmkTBA4N5r+AcCIGAQAhjbCVWGBAagB+sxRsEuTgFL4DwDR0QF8ETDUVT8LfrlpmaSl1sISKlFNFN8zCwsWBYpfSMP7RDeqAC4D6Nq7F7gFSFQTRWEJpaXWpmWSEXiBhoAkTY322fbsTGQmBXMVhCkAf1sL5r89BLalFcnnc9ix/w9ACHTMdlya1/MNBiYDL9B88sikDst+SJJ896L7Coz3mIqFeyVgMlsAxmchBgYx/NtLwCAAE2i52HKKJPnKV+HkkUktdu/ayfJzswYTPCIvy0Ztb+0uNaEM/BNAHIANXAdMX5MCBqAOIAfg783t0LiqB7wEHHukgp3D9+KWzz4BRK8CtJQVmI+Zv5DzclIIMdc+0F5nAPja4bXRYD7okqHsc/Y538qP5T+KbQDOArgNwAcBtAG4CYDTdPwqgCKAfwF4AVhc3w0gBLAewGcA7LyeqO2ntv9t5mszP+LELwlDTE+MTtQEAHiTHou0RYSdsM1oJDrr3+PvVY8oG/c1o7xwlUZsaDLjAzgJ4DSANIAfANjbZOLLAD4FoBPAUJMtunqNBTHP/o79k0ahkZVlOZs7mqsBUItNTfvmdnCDi9AL0berrza1Y2o3DDDcDGAPgM1NALrJxmCToZuv0cHNANzm83Vv+Xto2++2/XL22ZkXuVJ5wTDvTdUCAHoRRPmNMmKdMUABlZcrxQ3dG1oKzxY2Y3dzwULuDy3J/XMAPt2M/H1Npz6AqWt0cgzYOr716Sv7r/yxng+uMMaL+TOzPgC59C/nQ0NDTsEtxINqsAYmNrR/o/1z5zeev+eGcr9lZZ2InJg2C+Z3bdc+EeuM5ahB5dyJXH1hUruu2x4cHKQkknqO5hQDk9V/V8e7Zrry5SfLO+hOMlbM/a5m9C8v0ck/oFMtqWeSlHzUtM2LwhTTVszyTNsMStmSXqnesUwmIwA4F7wLLrNYBwRSIi421G+qPzjz45kPLFsv9EKj+D9r/Wrr2fZy+8+Zz8Zrb9by1KAZy7U8Dl5fOgSxlaYvz/OsfDQfa3iNBHd4GwRSZFDvfHT+m/Vn6v0rFrD7MR8tRx9LiVTWn/SndKBnLdcqqZqq2q7dWG4KW3YWzWazlMvldFt/m5R12eCCBwyszsDqpm+exgXcGn4kdJe+Fy/FS9YL1n79mr7IS3ySE89DY86O2rXJI5ONZgpouTF/xS2p3WtXZsQMSJLHOZ9lmk1xzSe7rnT90PXceVCzfdMA00z3/KrnSfmKHGOK5TjnMzrUnhkxg2qhqq+d8N8OBBsZGeEArFQq5RiGESFQRNjC1lJzFSgpTFHzL/tT6w6se4qBadSvfmVwdPBw4U+FU626tcpMJrngQktta6Wjse5YpOf2nmjPcI/dubXTXOjylx0DM5mMyOfzdm9vbyyZTLqc89Y5moszg7WCIy5s4YIhppWOVl+tBuvS6yLFzcV090R3tvr16kEoVDjnjS1sCy+iaIuIiGipo7IhIwDswAsMwzGw5v1rqDhW1EsnMADg2WzWSKfTUdM0E1LKpGVZyTbRliyEhSQYEipUrcQprkj1aKW7as/XPHeHm8J+PN8oNADAHsAAhBBGK7XGilRsIVCMCRYBhyUsIYQltAqU2tS1SedyuavN1LVMDA8Pc8aYQUQm59whogiASJrS1mV+2eQ2F6qhTCKKgMFQviL9Ff0sFDQIop/128QoppRqEJE5IAYkEywMw1BYpkW+74cmN03LsoRX95btizgAc8+ePVEAbhAErmmaUcaYQ0SmUsrIsqxgnHEwCK20wQ0uwCB0qHUf9SkhhCQiRUSKMaYNw5AAZBAEDSLywzCsSinLRFQ9d+5cvSlrupYJGhkZkYVCwfc8TwdBEEQiEatUKhmO45icc7FeredQgGEYXBiCB0HAiIgxxsi0TWKMkVJKSynJcRwKgkAqpZRt25IxFjLGgjAMg+ZxyqIm2HKHZENDQ2J2dla0t7dz13W553nCdV0mpWRKKQYAC9frio4QizXA930thCDHcfTY2Jju7+/X5XJZdXZ26tHR0betmFjSO7GRkREUCgXmed4NH5W4rkujo6M0MjKCgwcP0jXN31uK1X8B9tS5wV4E/YMAAAAASUVORK5CYII="
  243. ],
  244.  
  245. // 11 = normal/selected open Elgin MP
  246. [
  247. "data:image/png;base64,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",
  248. "data:image/png;base64,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"
  249. ],
  250. // 12 - normal/selected closed Elgin MP
  251. [
  252. "data:image/png;base64,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",
  253. "data:image/png;base64,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"
  254. ],
  255.  
  256. // 13 - normal/selected open TrafficCast MP
  257. [
  258. "data:image/png;base64,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",
  259. "data:image/png;base64,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"
  260. ],
  261. // 14 - normal/selected closed TrafficCast MP
  262. [
  263. "data:image/png;base64,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",
  264. "data:image/png;base64,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"
  265. ],
  266.  
  267. // 15 - normal/selected open TrafficMaster MP
  268. [
  269. "data:image/png;base64,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",
  270. "data:image/png;base64,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"
  271. ],
  272. // 16 - normal/selected closed TrafficMaster MP
  273. [
  274. "data:image/png;base64,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",
  275. "data:image/png;base64,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"
  276. ]
  277. ];
  278.  
  279. var uroMarkers =
  280. [
  281. // 0 = comment count circle
  282. ["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=="],
  283. // 1 = green comment marker
  284. ["data:image/png;base64,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"],
  285. // 2 = yellow (own) comment marker
  286. ["data:image/png;base64,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"]
  287. ];
  288.  
  289.  
  290. function uroAddLog(logtext)
  291. {
  292. if(uroShowDebugOutput) console.log('URO+: '+logtext);
  293. }
  294.  
  295. function uroGetCBChecked(cbID)
  296. {
  297. return(document.getElementById(cbID).checked);
  298. }
  299.  
  300. function uroSetCBChecked(cbID, state)
  301. {
  302. document.getElementById(cbID).checked = state;
  303. }
  304.  
  305. function uroGetElmValue(elmID)
  306. {
  307. return(document.getElementById(elmID).value);
  308. }
  309.  
  310. function uroSetStyleDisplay(elm,style)
  311. {
  312. document.getElementById(elm).style.display = style;
  313. }
  314.  
  315. function uroSetOnClick(elm,fn)
  316. {
  317. document.getElementById(elm).onclick = fn;
  318. }
  319.  
  320. function uroAddEventListener(elm,eventType,eventFn,eventBool)
  321. {
  322. document.getElementById(elm).addEventListener(eventType, eventFn, eventBool);
  323. }
  324.  
  325.  
  326. function uroFirstTimerWelcomePack()
  327. {
  328. uroAddLog('welcome new users to Club URO...');
  329.  
  330. // to be completed...
  331. }
  332.  
  333. function uroShowUpdateNotes()
  334. {
  335. uroAddLog('let existing users know what\'s new in this release');
  336.  
  337. var alertMsg = 'URO+ Update Notes...\n\n';
  338. alertMsg += 'Thanks for upgrading to URO+ '+uroVersion+' ('+uroReleaseDate+'). What\'s changed?\n\n';
  339.  
  340. var loop;
  341. if(uroChanges.length > 0)
  342. {
  343. for(loop=0; loop < uroChanges.length; loop++)
  344. {
  345. alertMsg += '* '+uroChanges[loop]+'\n';
  346. }
  347. }
  348. if((uroBetaEditor) && (uroBetaChanges.length > 0))
  349. {
  350. alertMsg += '\nFor WME Beta:\n';
  351. for(loop=0; loop < uroBetaChanges.length; loop++)
  352. {
  353. alertMsg += '* '+uroBetaChanges[loop]+'\n';
  354. }
  355. }
  356.  
  357. alert(alertMsg);
  358. }
  359.  
  360. function uroAdvertiseCustomIcons()
  361. {
  362. uroAddLog('advertise the benefits of custom UR icons...');
  363.  
  364. var confirmMsg = 'URO+ Installation/Upgrade Processing...\n\n';
  365. confirmMsg += '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.\n\n';
  366. confirmMsg += 'Markers are defined for [ROADWORKS], [CONSTRUCTION], [CLOSURE], [EVENT] and [NOTE] tags in URs, and [Elgin], [TM] and [TrafficCast] in MPs.\n\n';
  367. confirmMsg += 'Would you like me to automatically enable these custom markers?\n\n';
  368. confirmMsg += 'If you change your mind later on, they can be enabled/disabled via the Misc tab within the URO+ settings';
  369.  
  370. if(confirm(confirmMsg) === true)
  371. {
  372. uroSetCBChecked('_cbCustomRoadworksMarkers', true);
  373. uroSetCBChecked('_cbCustomConstructionMarkers', true);
  374. uroSetCBChecked('_cbCustomClosuresMarkers', true);
  375. uroSetCBChecked('_cbCustomEventsMarkers', true);
  376. uroSetCBChecked('_cbCustomNotesMarkers', true);
  377. uroSetCBChecked('_cbCustomElginMarkers', true);
  378. uroSetCBChecked('_cbCustomTrafficMasterMarkers', true);
  379. uroSetCBChecked('_cbCustomTrafficCastMarkers', true);
  380. }
  381. }
  382.  
  383.  
  384. function uroGatherSettings(container)
  385. {
  386. var options = '';
  387. var urOptions = document.getElementById(container).getElementsByTagName('input');
  388. for (var optIdx=0;optIdx<urOptions.length;optIdx++)
  389. {
  390. var id = urOptions[optIdx].id;
  391. if((id.indexOf('_cb') === 0)||(id.indexOf('_text') === 0)||(id.indexOf('_input') === 0))
  392. {
  393. options += ':' + id;
  394. if(urOptions[optIdx].type == 'checkbox') options += ',' + urOptions[optIdx].checked.toString();
  395. else if((urOptions[optIdx].type == 'text')||(urOptions[optIdx].type == 'number')) options += ',' + urOptions[optIdx].value.toString();
  396. }
  397. }
  398. return options;
  399. }
  400.  
  401.  
  402. function uroGatherCamWatchList()
  403. {
  404. var liststr = '';
  405. for(var loop=0;loop<uroCamWatchObjects.length;loop++)
  406. {
  407. var camObj = uroCamWatchObjects[loop];
  408. if((camObj.fid !== undefined) && (camObj.persistent === true))
  409. {
  410. if(loop > 0) liststr += ':';
  411.  
  412. liststr += camObj.fid+',';
  413. liststr += camObj.watch.lon+',';
  414. liststr += camObj.watch.lat+',';
  415. liststr += camObj.watch.type+',';
  416. liststr += camObj.watch.azymuth+',';
  417. liststr += camObj.watch.speed+',';
  418. liststr += camObj.watch.validated+',';
  419. liststr += camObj.groupID+',';
  420. liststr += camObj.server;
  421. }
  422. }
  423. return liststr;
  424. }
  425. function uroGatherSegWatchList()
  426. {
  427. var liststr = '';
  428. for(var loop=0;loop<uroSegWatchObjects.length;loop++)
  429. {
  430. var segObj = uroSegWatchObjects[loop];
  431. if((segObj.fid !== undefined) && (segObj.persistent === true))
  432. {
  433. if(loop > 0) liststr += ':';
  434.  
  435. liststr += segObj.fid+',';
  436. liststr += segObj.watch.left+',';
  437. liststr += segObj.watch.right+',';
  438. liststr += segObj.watch.bottom+',';
  439. liststr += segObj.watch.top+',';
  440. liststr += segObj.watch.fromNode+',';
  441. liststr += segObj.watch.toNode+',';
  442. liststr += segObj.watch.fwdDir+',';
  443. liststr += segObj.watch.revDir+',';
  444. liststr += segObj.watch.length+',';
  445. liststr += segObj.watch.level+',';
  446. liststr += segObj.watch.rank+',';
  447. liststr += segObj.watch.roadType+',';
  448. liststr += segObj.watch.updatedOn+',';
  449. liststr += segObj.groupID+',';
  450. liststr += segObj.server;
  451. }
  452. }
  453. return liststr;
  454. }
  455. function uroGatherPlaceWatchList()
  456. {
  457. var liststr = '';
  458. for(var loop=0;loop<uroPlaceWatchObjects.length;loop++)
  459. {
  460. var placeObj = uroPlaceWatchObjects[loop];
  461. if((placeObj.fid !== undefined) && (placeObj.persistent === true))
  462. {
  463. if(loop > 0) liststr += ':';
  464.  
  465. liststr += placeObj.fid+',';
  466. liststr += placeObj.watch.left+',';
  467. liststr += placeObj.watch.right+',';
  468. liststr += placeObj.watch.bottom+',';
  469. liststr += placeObj.watch.top+',';
  470. liststr += placeObj.watch.name+',';
  471. liststr += placeObj.watch.imageCount+',';
  472. liststr += placeObj.watch.residential+',';
  473. liststr += placeObj.watch.updatedOn+',';
  474. liststr += placeObj.groupID+',';
  475. liststr += placeObj.server;
  476. }
  477. }
  478. return liststr;
  479. }
  480. function uroGatherCWLGroups()
  481. {
  482. var liststr = '';
  483. for(var loop=0;loop<uroCWLGroups.length;loop++)
  484. {
  485. var groupObj = uroCWLGroups[loop];
  486. if(groupObj.groupID != -1)
  487. {
  488. if(loop > 0) liststr += ':';
  489.  
  490. liststr += groupObj.groupID+',';
  491. liststr += groupObj.groupName+',';
  492. liststr += groupObj.groupCollapsed;
  493. }
  494. }
  495. return liststr;
  496. }
  497. function uroGatherPlacesGroups()
  498. {
  499. var liststr = '';
  500. for(var loop=0;loop<uroPlacesGroupsCollapsed.length;loop++)
  501. {
  502. if(loop > 0) liststr += ':';
  503. liststr += uroPlacesGroupsCollapsed[loop];
  504. }
  505. return liststr;
  506. }
  507. function uroGatherFriendlyAreaNames()
  508. {
  509. var liststr = '';
  510. for(var loop=0;loop<uroFriendlyAreaNames.length;loop++)
  511. {
  512. var fnObj = uroFriendlyAreaNames[loop];
  513. if(loop > 0) liststr += ':';
  514.  
  515. liststr += fnObj.fName+',';
  516. liststr += fnObj.area+',';
  517. liststr += fnObj.server;
  518. }
  519. return liststr;
  520. }
  521.  
  522. function uroSaveSettings()
  523. {
  524. if(uroInhibitSave)
  525. {
  526. uroAddLog('save inhibited');
  527. return;
  528. }
  529.  
  530. if (localStorage)
  531. {
  532. localStorage.UROverviewUROptions = uroGatherSettings('uroCtrlURs');
  533. localStorage.UROverviewMPOptions = uroGatherSettings('uroCtrlMPs');
  534. localStorage.UROverviewCameraOptions = uroGatherSettings('uroCtrlCameras');
  535. localStorage.UROverviewMiscOptions = uroGatherSettings('uroCtrlMisc');
  536. localStorage.UROverviewPlacesOptions = uroGatherSettings('uroCtrlPlaces');
  537. localStorage.UROverviewCamWatchList = uroGatherCamWatchList();
  538. localStorage.UROverviewSegWatchList = uroGatherSegWatchList();
  539. localStorage.UROverviewPlaceWatchList = uroGatherPlaceWatchList();
  540. localStorage.UROverviewCWLGroups = uroGatherCWLGroups();
  541. localStorage.UROverviewFriendlyAreaNames = uroGatherFriendlyAreaNames();
  542. localStorage.UROverviewPlacesGroups = uroGatherPlacesGroups();
  543.  
  544. localStorage.UROverviewMasterEnable = uroGetCBChecked('_cbMasterEnable');
  545. localStorage.UROverviewCurrentVersion = uroVersion;
  546.  
  547. uroAddLog('save complete');
  548. }
  549. else
  550. {
  551. uroAddLog('no localStorage, save blocked');
  552. }
  553. }
  554.  
  555. function uroApplySettings(settings)
  556. {
  557. var options = settings.split(':');
  558. for(var optIdx=0;optIdx<options.length;optIdx++)
  559. {
  560. var fields = options[optIdx].split(',');
  561. if(fields[0].indexOf('_cb') === 0)
  562. {
  563. if(document.getElementById(fields[0]) !== null)
  564. {
  565. uroSetCBChecked(fields[0], (fields[1] == 'true'));
  566. }
  567. }
  568. else if((fields[0].indexOf('_input') === 0)||(fields[0].indexOf('_text') === 0))
  569. {
  570. if(document.getElementById(fields[0]) !== null) document.getElementById(fields[0]).value = fields[1];
  571. }
  572. }
  573. }
  574.  
  575.  
  576. function uroApplyCamWatchList()
  577. {
  578. var objects = localStorage.UROverviewCamWatchList.split(':');
  579. uroCamWatchObjects = [];
  580. if(objects.length > 0)
  581. {
  582. for(var objIdx=0;objIdx<objects.length;objIdx++)
  583. {
  584. var fields = objects[objIdx].split(',');
  585. if(fields.length >= 7)
  586. {
  587. // following two bits of code add in blank fields if the user has updated their copy of URO+ from an
  588. // older version which didn't include support for either of these field types
  589.  
  590. // add default groupID field
  591. if(fields.length == 7)
  592. {
  593. fields.push(0);
  594. }
  595. // set default groupID value to 0 (no group)
  596. if(fields[7] == -1)
  597. {
  598. fields[7] = 0;
  599. }
  600.  
  601. // add default server field
  602. if(fields.length == 8)
  603. {
  604. fields.push('??');
  605. }
  606. // set default server value to unknown
  607. if(fields[8] === 0)
  608. {
  609. fields[8] = '??';
  610. }
  611.  
  612. uroCamWatchObjects.push(new uroCamWatchObj(true,fields[0],fields[1],fields[2],fields[3],fields[4],fields[5],fields[6],fields[7],fields[8]));
  613. }
  614. }
  615. }
  616. }
  617. function uroApplySegWatchList()
  618. {
  619. var objects = localStorage.UROverviewSegWatchList.split(':');
  620. uroSegWatchObjects = [];
  621.  
  622. for(var objIdx=0;objIdx<objects.length;objIdx++)
  623. {
  624. var fields = objects[objIdx].split(',');
  625. 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]));
  626. }
  627. }
  628. function uroApplyPlaceWatchList()
  629. {
  630. var objects = localStorage.UROverviewPlaceWatchList.split(':');
  631. uroPlaceWatchObjects = [];
  632.  
  633. for(var objIdx=0;objIdx<objects.length;objIdx++)
  634. {
  635. var fields = objects[objIdx].split(',');
  636. 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]));
  637. }
  638. }
  639.  
  640. function uroApplyCWLGroups()
  641. {
  642. var objects = localStorage.UROverviewCWLGroups.split(':');
  643. uroCWLGroups = [];
  644.  
  645. for(var objIdx=0;objIdx<objects.length;objIdx++)
  646. {
  647. var fields = objects[objIdx].split(',');
  648. if(fields.length < 2)
  649. {
  650. fields.push(false);
  651. }
  652. uroCWLGroups.push(new uroOWLGroupObj(fields[0],fields[1],(fields[2] == 'true')));
  653. }
  654. }
  655.  
  656. function uroApplyPlacesGroups()
  657. {
  658. var t = localStorage.UROverviewPlacesGroups.split(':');
  659. for(var i=0;i<t.length;i++)
  660. {
  661. uroPlacesGroupsCollapsed[i] = (t[i] == "true");
  662. }
  663. }
  664.  
  665.  
  666. function uroApplyFriendlyAreaNames()
  667. {
  668. var objects = localStorage.UROverviewFriendlyAreaNames.split(':');
  669. uroFriendlyAreaNames = [];
  670.  
  671. for(var objIdx=0;objIdx<objects.length;objIdx++)
  672. {
  673. var fields = objects[objIdx].split(',');
  674. uroFriendlyAreaNames.push(new uroAFNObj(fields[0],parseFloat(fields[1]),fields[2]));
  675. }
  676.  
  677. uroReplaceAreaNames(true);
  678. }
  679.  
  680. function uroLoadSettings()
  681. {
  682. var isNewInstall = true;
  683. var isUpgradeInstall = true;
  684. var notifyAboutCustomIcons = true;
  685.  
  686. uroAddLog('loadSettings()');
  687. if (localStorage.UROverviewUROptions !== undefined)
  688. {
  689. uroAddLog('recover UR tab settings');
  690. uroApplySettings(localStorage.UROverviewUROptions);
  691. isNewInstall = false;
  692. }
  693.  
  694. if (localStorage.UROverviewCameraOptions !== undefined)
  695. {
  696. uroAddLog('recover camera tab settings');
  697. uroApplySettings(localStorage.UROverviewCameraOptions);
  698. isNewInstall = false;
  699. }
  700.  
  701. if (localStorage.UROverviewMPOptions !== undefined)
  702. {
  703. uroAddLog('recover MP tab settings');
  704. uroApplySettings(localStorage.UROverviewMPOptions);
  705. isNewInstall = false;
  706. }
  707.  
  708. if (localStorage.UROverviewPlacesOptions !== undefined)
  709. {
  710. uroAddLog('recover Places tab settings');
  711. uroApplySettings(localStorage.UROverviewPlacesOptions);
  712. isNewInstall = false;
  713. }
  714.  
  715. if (localStorage.UROverviewMiscOptions !== undefined)
  716. {
  717. uroAddLog('recover misc tab settings');
  718. uroApplySettings(localStorage.UROverviewMiscOptions);
  719. isNewInstall = false;
  720.  
  721. if(localStorage.UROverviewCurrentVersion !== undefined)
  722. {
  723. notifyAboutCustomIcons = false;
  724. }
  725. else
  726. {
  727. if(uroGetCBChecked('_cbCustomRoadworksMarkers') === true) notifyAboutCustomIcons = false;
  728. if(uroGetCBChecked('_cbCustomConstructionMarkers')=== true) notifyAboutCustomIcons = false;
  729. if(uroGetCBChecked('_cbCustomClosuresMarkers') === true) notifyAboutCustomIcons = false;
  730. if(uroGetCBChecked('_cbCustomEventsMarkers') === true) notifyAboutCustomIcons = false;
  731. if(uroGetCBChecked('_cbCustomNotesMarkers') === true) notifyAboutCustomIcons = false;
  732. }
  733. }
  734.  
  735. if(localStorage.UROverviewCWLGroups !== undefined)
  736. {
  737. uroAddLog('recover CWL groups');
  738. uroApplyCWLGroups();
  739. isNewInstall = false;
  740. }
  741. else
  742. {
  743. uroAddLog('set default CWL group');
  744. uroCWLGroups.push(new uroOWLGroupObj(0,'No group',false));
  745. }
  746.  
  747. if(localStorage.UROverviewCamWatchList !== undefined)
  748. {
  749. uroAddLog('recover camera watchlist');
  750. uroApplyCamWatchList();
  751. uroGetCurrentCamWatchListObjects();
  752. isNewInstall = false;
  753. }
  754.  
  755. if(localStorage.UROverviewSegWatchList !== undefined)
  756. {
  757. uroAddLog('recover segment watchlist');
  758. uroApplySegWatchList();
  759. uroGetCurrentSegWatchListObjects();
  760. isNewInstall = false;
  761. }
  762.  
  763. if(localStorage.UROverviewPlaceWatchList !== undefined)
  764. {
  765. uroAddLog('recover places watchlist');
  766. uroApplyPlaceWatchList();
  767. //uroGetCurrentPlaceWatchListObjects();
  768. isNewInstall = false;
  769. }
  770.  
  771. if(localStorage.UROverviewPlacesGroups !== undefined)
  772. {
  773. uroAddLog('recover places groups');
  774. uroApplyPlacesGroups();
  775. isNewInstall = false;
  776. }
  777.  
  778. if(localStorage.UROverviewCurrentVersion !== undefined)
  779. {
  780. uroAddLog('comparing install versions');
  781. if(localStorage.UROverviewCurrentVersion == uroVersion)
  782. {
  783. isUpgradeInstall = false;
  784. }
  785. }
  786.  
  787. if(localStorage.UROverviewFriendlyAreaNames !== undefined)
  788. {
  789. uroAddLog('recover friendly area names');
  790. uroApplyFriendlyAreaNames();
  791. isNewInstall = false;
  792. }
  793.  
  794. if(localStorage.UROverviewMasterEnable !== undefined)
  795. {
  796. uroAddLog('recover master enable state');
  797. document.getElementById('_cbMasterEnable').checked = (localStorage.UROverviewMasterEnable == "true");
  798. }
  799.  
  800. if(isNewInstall)
  801. {
  802. uroFirstTimerWelcomePack();
  803. }
  804. else if(isUpgradeInstall)
  805. {
  806. uroShowUpdateNotes();
  807. }
  808.  
  809. if(notifyAboutCustomIcons)
  810. {
  811. uroAdvertiseCustomIcons();
  812. }
  813.  
  814. uroInhibitSave = false;
  815. }
  816.  
  817. function uroDefaultSettings()
  818. {
  819. if(confirm('Resetting URO+ settings cannot be undone\nAre you sure you want to do this?') === true)
  820. {
  821. var defaultSettings = '';
  822. 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]';
  823. defaultSettings += '[UROverviewPlaceWatchList][len=0][END]';
  824. defaultSettings += '[UROverviewCamWatchList][len=0][END]';
  825. defaultSettings += '[UROverviewSegWatchList][len=0][END]';
  826. defaultSettings += '[UROverviewPlacesOptions][len=5106]:_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:_cbHidePhotoPlaces,false:_cbHideNoPhotoPlaces,false:_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]';
  827. defaultSettings += '[UROverviewCurrentVersion][len=0][END]';
  828. defaultSettings += '[UROverviewFriendlyAreaNames][len=0][END]';
  829. defaultSettings += '[UROverviewMasterEnable][len=4]true[END]';
  830. defaultSettings += '[UROverviewMiscOptions][len=1004]:_cbNativeConvoMarkers,true:_cbNativeBetaConvoMarkers,true:_cbCommentCount,false:_cbURBackfill,false:_inputUnstackSensitivity,15:_inputUnstackZoomLevel,3:_cbCustomRoadworksMarkers,false:_cbCustomConstructionMarkers,false:_cbCustomClosuresMarkers,false:_cbCustomEventsMarkers,false:_cbCustomNotesMarkers,false:_cbCustomElginMarkers,false:_cbCustomTrafficMasterMarkers,false:_cbCustomTrafficCastMarkers,false:_inputPopupDwellTimeout,2:_inputPopupEntryTimeout,2:_inputMaxJitter,2:_cbInhibitURPopup,false:_cbInhibitMPPopup,false:_cbInhibitCamPopup,false:_cbInhibitSegPopup,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:_cbHideAMLayer,false:_cbDisablePlacesFiltering,false:_cbDisablePendingQuestions,false:_cbEnableDTE,false:_cbEnableSRS,false[END]';
  831. defaultSettings += '[UROverviewUROptions][len=1544]:_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:_cbInvertURFilter,false:_cbFilterOpenUR,false:_cbFilterClosedUR,false:_cbFilterSolved,false:_cbFilterUnidentified,false:_cbEnableMinAgeFilter,false:_inputFilterMinDays,:_cbEnableMaxAgeFilter,false:_inputFilterMaxDays,:_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,:_cbHideMyFollowed,false:_cbHideMyUnfollowed,false:_cbEnableCommentAgeFilter2,false:_inputFilterCommentDays2,:_cbEnableCommentAgeFilter,false:_inputFilterCommentDays,:_cbURUserIDFilter,false:_cbURResolverIDFilter,false:_cbNoFilterForTaggedURs,false[END]';
  832. defaultSettings += '[UROverviewCameraOptions][len=798]:_cbShowWorldCams,true:_cbShowUSACams,true:_cbShowNonWorldCams,true:_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]';
  833. defaultSettings += '[UROverviewPlacesGroups][len=59]false:false:false:false:false:false:false:false:false:false[END]';
  834. defaultSettings += '[UROverviewCWLGroups][len=16]0,No group,false[END]';
  835. document.getElementById('_txtSettings').value = defaultSettings;
  836. uroTextToSettings();
  837. document.getElementById('_txtSettings').value = '';
  838. }
  839. }
  840.  
  841. function uroSettingsToText()
  842. {
  843. var txtSettings = '';
  844.  
  845. uroSaveSettings();
  846.  
  847. for(var lsEntry in localStorage)
  848. {
  849. if(lsEntry.indexOf('UROverview') === 0)
  850. {
  851. txtSettings += '['+lsEntry+'][len=' + localStorage[lsEntry].length + ']' + localStorage[lsEntry] + '[END]';
  852. }
  853. }
  854.  
  855. document.getElementById('_txtSettings').value = txtSettings;
  856. document.getElementById('_txtSettings').focus();
  857. document.getElementById('_txtSettings').select();
  858. }
  859.  
  860. function uroTextToSettings()
  861. {
  862. var txtSettings = '';
  863. txtSettings = uroGetElmValue('_txtSettings');
  864. if(txtSettings.indexOf('[END]') == -1) return;
  865.  
  866. var subText = txtSettings.split('[END]');
  867. for(var i=0;i<subText.length;i++)
  868. {
  869. var bPos = subText[i].indexOf(']');
  870. if(bPos != -1)
  871. {
  872. var settingID = subText[i].substr(1,bPos-1);
  873. subText[i] = subText[i].substr(bPos+1);
  874. bPos = subText[i].indexOf(']');
  875. if(bPos != -1)
  876. {
  877. var settingLength = subText[i].substr(5,bPos-5);
  878. subText[i] = subText[i].substr(bPos+1);
  879. if(subText[i].length == settingLength)
  880. {
  881. localStorage[settingID] = subText[i];
  882. }
  883. }
  884. }
  885. }
  886. uroLoadSettings();
  887. }
  888.  
  889. function uroClearSettingsText()
  890. {
  891. document.getElementById('_txtSettings').value = '';
  892. }
  893.  
  894.  
  895. function uroDateToDays(dateToConvert)
  896. {
  897. var dateNow = new Date();
  898.  
  899. var elapsedSinceEpoch = dateNow.getTime();
  900. var elapsedSinceEvent = elapsedSinceEpoch - dateToConvert;
  901.  
  902. dateNow.setHours(0);
  903. dateNow.setMinutes(0);
  904. dateNow.setSeconds(0);
  905. dateNow.setMilliseconds(0);
  906.  
  907. var elapsedSinceMidnight = elapsedSinceEpoch - dateNow.getTime();
  908.  
  909. if(elapsedSinceEvent < elapsedSinceMidnight)
  910. {
  911. // event occurred today...
  912. return 0;
  913. }
  914. else
  915. {
  916. // event occurred at some point prior to midnight this morning, so return a minimum value of 1...
  917. return 1 + Math.floor((elapsedSinceEvent - elapsedSinceMidnight) / 86400000);
  918. }
  919. }
  920.  
  921. function uroGetURAge(urObj,ageType,getRaw)
  922. {
  923. if(ageType === 0)
  924. {
  925. if((urObj.attributes.driveDate === null)||(urObj.attributes.driveDate === 0)) return -1;
  926. if(getRaw) return urObj.attributes.driveDate;
  927. else return uroDateToDays(urObj.attributes.driveDate);
  928. }
  929. else if(ageType === 1)
  930. {
  931. if((urObj.attributes.resolvedOn === null)||(urObj.attributes.resolvedOn === 0)) return -1;
  932. if(getRaw) return urObj.attributes.resolvedOn;
  933. else return uroDateToDays(urObj.attributes.resolvedOn);
  934. }
  935. else
  936. {
  937. return -1;
  938. }
  939. }
  940.  
  941. function uroGetPURAge(purObj)
  942. {
  943. if(purObj.attributes.venueUpdateRequests[0].attributes.dateAdded !== null)
  944. {
  945. return uroDateToDays(purObj.attributes.venueUpdateRequests[0].attributes.dateAdded);
  946. }
  947. else
  948. {
  949. return -1;
  950. }
  951. }
  952.  
  953. function uroGetCameraAge(camObj, mode)
  954. {
  955. if(mode === 0)
  956. {
  957. if(camObj.attributes.updatedOn === null) return -1;
  958. return uroDateToDays(camObj.attributes.updatedOn);
  959. }
  960. if(mode === 1)
  961. {
  962. if(camObj.attributes.createdOn === null) return -1;
  963. return uroDateToDays(camObj.attributes.createdOn);
  964. }
  965. }
  966.  
  967. function uroGetCommentAge(commentObj)
  968. {
  969. if(commentObj.createdOn === null) return -1;
  970. return uroDateToDays(commentObj.createdOn);
  971. }
  972.  
  973. function uroParseDaysAgo(days)
  974. {
  975. if(days === 0) return 'today';
  976. else if(days === 1) return '1 day ago';
  977. else return days+' days ago';
  978. }
  979.  
  980. function uroGetCameraSpeedString(camSpeed)
  981. {
  982. if(camSpeed !== null)
  983. {
  984. var conversionFactor = 1; // default to metric
  985. var multipleFactor = 10; // default to limits being set in multiples of 10
  986.  
  987. var country;
  988. if(W.model.countries.top === undefined)
  989. {
  990. country = W.model.countries.additionalInfo[0].name;
  991. }
  992. else
  993. {
  994. country = W.model.countries.top.name;
  995. }
  996. if(country !== null)
  997. {
  998. // country-specific deviations from the above...
  999. if
  1000. (
  1001. (country == "United Kingdom") ||
  1002. (country == "Jersey") ||
  1003. (country == "Guernsey") ||
  1004. (country == "United States")
  1005. )
  1006. {
  1007. // countries using MPH
  1008. conversionFactor = 1.609;
  1009. }
  1010. if
  1011. (
  1012. (country == "United States") ||
  1013. (country == "Guernsey")
  1014. )
  1015. {
  1016. // countries with speed limits set in multiples of 5
  1017. multipleFactor = 5;
  1018. }
  1019. }
  1020.  
  1021. var speed = Math.round(camSpeed / conversionFactor);
  1022. var retval = speed;
  1023. if(conversionFactor == 1) retval += "KM/H";
  1024. else retval += "MPH";
  1025. if(speed % multipleFactor !== 0) retval += " (not valid?)";
  1026. return retval;
  1027. }
  1028. else return "not set";
  1029. }
  1030.  
  1031.  
  1032. // --------------------------------------------------------------------------------------------------------------------
  1033. // AREA FRIENDLYNAME STUFF
  1034. // --------------------------------------------------------------------------------------------------------------------
  1035. function uroAFNObj(fName, area, server)
  1036. {
  1037. this.fName = fName;
  1038. this.area = area;
  1039. this.server = server;
  1040. }
  1041.  
  1042. function uroUpdateAreaName(name, server, area)
  1043. {
  1044. var foundExisting = false;
  1045. for(var i=0; i<uroFriendlyAreaNames.length; i++)
  1046. {
  1047. if((uroFriendlyAreaNames[i].server == server) && (uroFriendlyAreaNames[i].area == area))
  1048. {
  1049. if(name === "")
  1050. {
  1051. uroFriendlyAreaNames.splice(i,1);
  1052. foundExisting = true;
  1053. }
  1054. else
  1055. {
  1056. uroFriendlyAreaNames[i].fName = name;
  1057. foundExisting = true;
  1058. }
  1059. }
  1060. }
  1061.  
  1062. if((foundExisting === false) && (name !== ""))
  1063. {
  1064. uroFriendlyAreaNames.push(new uroAFNObj(name,area,server));
  1065. }
  1066. uroReplaceAreaNames(true);
  1067. }
  1068.  
  1069. function uroAreaNameHover()
  1070. {
  1071. if((uroAreaNameHoverObj === null) || (uroAreaNameHoverObj != this))
  1072. {
  1073. uroAreaNameHoverTime = 0;
  1074. }
  1075. uroAreaNameHoverObj = this;
  1076. }
  1077.  
  1078. function uroAreaNameUnHover()
  1079. {
  1080. if(uroANEditHovered === true)
  1081. {
  1082. return false;
  1083. }
  1084. if(uroAreaNameOverlayShown)
  1085. {
  1086. uroAreaNameHoverObj.removeChild(uroANEditBox);
  1087. }
  1088. uroAreaNameHoverObj = null;
  1089. uroAreaNameHoverTime = -1;
  1090. uroAreaNameOverlayShown = false;
  1091. }
  1092.  
  1093. function uroANEditHover()
  1094. {
  1095. uroANEditHovered = true;
  1096. uroAddEventListener('uroANEditBox','mouseout',uroANEditUnHover,false);
  1097. uroAddEventListener('uroANEditBox','click',uroANEditClick,false);
  1098. }
  1099.  
  1100. function uroANEditUnHover()
  1101. {
  1102. var newName = document.getElementById('_textAreaName').value;
  1103. // sanitise name to avoid conflicts with config storage delimiters...
  1104. newName = newName.replace(',','');
  1105. newName = newName.replace(':','');
  1106. var server = W.location.code;
  1107. var area = uroGetAreaArea(uroAreaNameHoverObj.parentNode.children[1]);
  1108. uroAreaNameHoverObj.removeChild(uroANEditBox);
  1109. uroAreaNameOverlayShown = false;
  1110. uroANEditHovered = false;
  1111. uroUpdateAreaName(newName, server, area);
  1112. }
  1113.  
  1114. function uroANEditClick(e)
  1115. {
  1116. // this traps the click to prevent it falling through to the underlying area name element and
  1117. // potentially causing the map view to be relocated to that area...
  1118. e.stopPropagation();
  1119. }
  1120.  
  1121. function uroGetAreaArea(listObj)
  1122. {
  1123. var area = listObj.getElementsByTagName('span')[0].innerHTML;
  1124. area = parseFloat(area.split(' ')[0]);
  1125. return area;
  1126. }
  1127.  
  1128. function uroAreaNameOverlaySetup()
  1129. {
  1130. uroAreaNameOverlayShown = true;
  1131.  
  1132. uroANEditBox = document.createElement('div');
  1133. uroANEditBox.id = "uroANEditBox";
  1134. uroANEditBox.style.position = "absolute";
  1135. uroANEditBox.style.top = '7px';
  1136. uroANEditBox.style.left = '2px';
  1137. uroANEditBox.style.width = "99%";
  1138. uroAreaNameHoverObj.appendChild(uroANEditBox);
  1139. uroANEditBox.onmouseover = uroANEditHover();
  1140. var existingName = uroAreaNameHoverObj.innerHTML;
  1141. var italicTagPos = existingName.indexOf(' <i>');
  1142. if(italicTagPos == -1)
  1143. {
  1144. existingName = "";
  1145. }
  1146. else
  1147. {
  1148. existingName = existingName.substr(0,italicTagPos);
  1149. }
  1150. uroANEditBox.innerHTML = '<input type="text" style="font-size:14px; line-height:16px; height:22px; width:100%" id="_textAreaName" value="'+existingName+'">';
  1151. }
  1152.  
  1153. function uroReplaceAreaNames(replaceAfterNameChange)
  1154. {
  1155. if(document.getElementById('sidepanel-areas') === undefined)
  1156. {
  1157. return;
  1158. }
  1159.  
  1160. if(replaceAfterNameChange === false)
  1161. {
  1162. if(document.getElementById('sidepanel-areas').getElementsByClassName('result-list')[0].id == "friendlyNamed")
  1163. {
  1164. return;
  1165. }
  1166. }
  1167.  
  1168. var panelRootObj = document.getElementById('sidepanel-areas').getElementsByClassName('result-list')[0];
  1169. var areaCount = panelRootObj.children.length;
  1170. if(areaCount === 0)
  1171. {
  1172. return;
  1173. }
  1174.  
  1175. var localisedManagedArea = I18n.lookup("user.areas.managed_area");
  1176. for(var loop=0; loop < areaCount; loop++)
  1177. {
  1178. var childObjPElems = panelRootObj.children[loop].getElementsByTagName('p');
  1179. var title = childObjPElems[0].innerHTML;
  1180. if(title.indexOf(localisedManagedArea) > -1)
  1181. {
  1182. var area = uroGetAreaArea(childObjPElems[1]);
  1183. childObjPElems[0].innerHTML = localisedManagedArea;
  1184.  
  1185. for(var fnIdx=0; fnIdx < uroFriendlyAreaNames.length; fnIdx++)
  1186. {
  1187. var fnObj = uroFriendlyAreaNames[fnIdx];
  1188. if((fnObj.area == area) && (fnObj.server == W.location.code))
  1189. {
  1190. childObjPElems[0].innerHTML = fnObj.fName +' <i>('+localisedManagedArea+')</i>';
  1191. break;
  1192. }
  1193. }
  1194. var titleObj = panelRootObj.getElementsByClassName('title')[loop];
  1195. titleObj.addEventListener("mouseover", uroAreaNameHover, false);
  1196. titleObj.addEventListener("mouseout", uroAreaNameUnHover, false);
  1197. titleObj.style.cursor = "text";
  1198. }
  1199. }
  1200. document.getElementById('sidepanel-areas').getElementsByClassName('result-list')[0].id = "friendlyNamed";
  1201. }
  1202.  
  1203. // --------------------------------------------------------------------------------------------------------------------
  1204. // WATCHLIST STUFF
  1205. // --------------------------------------------------------------------------------------------------------------------
  1206.  
  1207. // Generic Functions
  1208. function uroTypeCast(varin)
  1209. {
  1210. if(varin == "null") return null;
  1211. if(typeof varin == "string") return parseInt(varin);
  1212. return varin;
  1213. }
  1214. function uroTruncate(val)
  1215. {
  1216. if(val === null) return val;
  1217. if(val < 0) return Math.ceil(val);
  1218. return Math.floor(val);
  1219. }
  1220. function uroOWLGroupObj(groupID, groupName, groupCollapsed)
  1221. {
  1222. groupID = uroTypeCast(groupID);
  1223. this.groupID = groupID;
  1224. this.groupName = groupName;
  1225. this.groupCount = 0;
  1226. this.groupCollapsed = groupCollapsed;
  1227. }
  1228.  
  1229. // Camera Functions
  1230. function uroCamWatchObjCheckProps(type, azymuth, speed, validated, lat, lon)
  1231. {
  1232. if(type !== null) type = uroTypeCast(type);
  1233. if(azymuth !== null) azymuth = uroTruncate(uroTypeCast(azymuth)%360);
  1234. if(speed !== null) speed = uroTruncate(uroTypeCast(speed));
  1235. if(typeof validated == "string") validated = (validated == "true");
  1236. if(lat !== null) lat = uroTruncate(uroTypeCast(lat));
  1237. if(lon !== null) lon = uroTruncate(uroTypeCast(lon));
  1238.  
  1239. this.type = type;
  1240. this.azymuth = azymuth;
  1241. this.speed = speed;
  1242. this.validated = validated;
  1243. this.lat = lat;
  1244. this.lon = lon;
  1245. }
  1246. function uroCamWatchObj(persistent, fid, lon, lat, type, azymuth, speed, validated, groupID, server)
  1247. {
  1248. fid = uroTypeCast(fid);
  1249. groupID = uroTypeCast(groupID);
  1250. if(typeof persistent == "string") persistent = (persistent == "true");
  1251.  
  1252. this.fid = fid;
  1253. this.persistent = persistent;
  1254. this.loaded = false;
  1255. this.server = server;
  1256. this.groupID = groupID;
  1257. this.watch = new uroCamWatchObjCheckProps(type, azymuth, speed, validated, lat, lon);
  1258. this.current = new uroCamWatchObjCheckProps(null, null, null, null, null, null);
  1259. }
  1260. function uroCamDataChanged(idx)
  1261. {
  1262. var camObj = uroCamWatchObjects[idx];
  1263. if(camObj.loaded === false) return false;
  1264. if(camObj.current.type != camObj.watch.type) return true;
  1265. if(camObj.current.azymuth != camObj.watch.azymuth) return true;
  1266. if(camObj.current.speed != camObj.watch.speed) return true;
  1267. if(camObj.current.validated != camObj.watch.validated) return true;
  1268. if(camObj.current.lat != camObj.watch.lat) return true;
  1269. if(camObj.current.lon != camObj.watch.lon) return true;
  1270. return false;
  1271. }
  1272. function uroFindCWLGroupByIdx(groupIdx)
  1273. {
  1274. var groupName = '';
  1275. for(var loop=0;loop<uroCWLGroups.length;loop++)
  1276. {
  1277. if(uroCWLGroups[loop].groupID == groupIdx)
  1278. {
  1279. groupName = uroCWLGroups[loop].groupName;
  1280. break;
  1281. }
  1282. }
  1283. return groupName;
  1284. }
  1285. function uroIsCamOnWatchList(fid)
  1286. {
  1287. for(var loop=0;loop<uroCamWatchObjects.length;loop++)
  1288. {
  1289. if(uroCamWatchObjects[loop].fid == fid) return loop;
  1290. }
  1291. return -1;
  1292. }
  1293. function uroAddCurrentCamWatchData(idx, lat, lon, type, azymuth, speed, validated, server)
  1294. {
  1295. var camObj = uroCamWatchObjects[idx];
  1296. camObj.loaded = true;
  1297. camObj.server = server;
  1298. camObj.current = new uroCamWatchObjCheckProps(type, azymuth, speed, validated, lat, lon);
  1299. return(uroCamDataChanged(idx));
  1300. }
  1301. function uroAddCamToWatchList()
  1302. {
  1303. if(uroIsCamOnWatchList(uroShownFID) == -1)
  1304. {
  1305. var camObj = W.model.cameras.objects[uroShownFID];
  1306. 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));
  1307. 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);
  1308. uroAddLog('added camera '+uroShownFID+' to watchlist');
  1309. uroOWLUpdateHTML();
  1310. }
  1311. }
  1312. function uroRemoveCamFromWatchList()
  1313. {
  1314. var camidx = uroIsCamOnWatchList(uroShownFID);
  1315. if(camidx != -1)
  1316. {
  1317. uroCamWatchObjects.splice(camidx,1);
  1318. uroAddLog('removed camera '+uroShownFID+' from watchlist');
  1319. uroOWLUpdateHTML();
  1320. }
  1321. }
  1322. function uroUpdateCamWatchList()
  1323. {
  1324. var camIdx = uroIsCamOnWatchList(uroShownFID);
  1325. if(camIdx != -1)
  1326. {
  1327. var camObj = W.model.cameras.objects[uroShownFID];
  1328. uroCamWatchObjects[camIdx].watch = new uroCamWatchObjCheckProps(camObj.attributes.type, camObj.attributes.azymuth, camObj.attributes.speed, camObj.attributes.validated, camObj.geometry.y, camObj.geometry.x);
  1329. }
  1330. }
  1331. function uroClearCamWatchList()
  1332. {
  1333. if(confirm('Removing all cameras from the OWL cannot be undone\nAre you sure you want to do this?') === true)
  1334. {
  1335. uroCamWatchObjects = [];
  1336. uroOWLUpdateHTML();
  1337. }
  1338. }
  1339. function uroRetrieveCameras(lat, lon)
  1340. {
  1341. var camPos = new OpenLayers.LonLat();
  1342. var camChanged = false;
  1343.  
  1344. camPos.lon = lon;
  1345. camPos.lat = lat;
  1346. camPos.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326"));
  1347.  
  1348. var camURL = 'https://' + document.location.host;
  1349. camURL += Waze.Config.api_base;
  1350. camURL += '/Features?language=en&cameras=true&bbox=';
  1351. var latl = camPos.lat - 0.25;
  1352. var latu = camPos.lat + 0.25;
  1353. var lonl = camPos.lon - 0.25;
  1354. var lonr = camPos.lon + 0.25;
  1355. camURL += lonl+','+latl+','+lonr+','+latu;
  1356. uroAddLog('retrieving camera data around '+camPos.lon+','+camPos.lat);
  1357.  
  1358. var camReq = new XMLHttpRequest();
  1359. camReq.open('GET',camURL,false);
  1360. try
  1361. {
  1362. camReq.send();
  1363. uroAddLog('response '+camReq.status+' received');
  1364. if (camReq.status === 200)
  1365. {
  1366. var camData = JSON.parse(camReq.responseText);
  1367. for(var camIdx = 0; camIdx < camData.cameras.objects.length; camIdx++)
  1368. {
  1369. var camObj = camData.cameras.objects[camIdx];
  1370. var listIdx = uroIsCamOnWatchList(camObj.id);
  1371. if(listIdx != -1)
  1372. {
  1373. camPos.lon = camObj.geometry.coordinates[0];
  1374. camPos.lat = camObj.geometry.coordinates[1];
  1375. camPos.transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913"));
  1376. camPos.lon = uroTruncate(camPos.lon);
  1377. camPos.lat = uroTruncate(camPos.lat);
  1378. camChanged |= uroAddCurrentCamWatchData(listIdx, camPos.lat, camPos.lon, camObj.type, camObj.azymuth, camObj.speed, camObj.validated, W.location.code);
  1379. }
  1380. else if(camObj.validated === false)
  1381. {
  1382.  
  1383. }
  1384. }
  1385. }
  1386. else
  1387. {
  1388. uroAddLog('request failed (status != 200)');
  1389. }
  1390. }
  1391. catch(err)
  1392. {
  1393. uroAddLog('camera load request failed (exception '+err+' caught)');
  1394. }
  1395. return camChanged;
  1396. }
  1397. function uroGetCurrentCamWatchListObjects()
  1398. {
  1399. var camChanged = false;
  1400. var camsChanged = [];
  1401. var camsDeleted = [];
  1402. var camidx;
  1403. var camObj;
  1404. for(camidx=0;camidx<uroCamWatchObjects.length;camidx++)
  1405. {
  1406. camObj = uroCamWatchObjects[camidx];
  1407. if((camObj.loaded === false) && ((camObj.server == W.location.code) || (camObj.server == '??')))
  1408. {
  1409. if(typeof W.model.cameras.objects[camObj.fid] == 'object')
  1410. {
  1411. if(W.model.cameras.objects[camObj.fid].state != "Delete")
  1412. {
  1413. var wazeObj = W.model.cameras.objects[camObj.fid];
  1414. camChanged |= uroAddCurrentCamWatchData(camidx, wazeObj.geometry.y, wazeObj.geometry.x, wazeObj.attributes.type, wazeObj.attributes.azymuth, wazeObj.attributes.speed, wazeObj.attributes.validated);
  1415. }
  1416. else
  1417. {
  1418. camChanged |= uroRetrieveCameras(camObj.watch.lat, camObj.watch.lon);
  1419. }
  1420. }
  1421. else
  1422. {
  1423. camChanged |= uroRetrieveCameras(camObj.watch.lat, camObj.watch.lon);
  1424. }
  1425. }
  1426. }
  1427.  
  1428. if(camChanged)
  1429. {
  1430. for(camidx=0;camidx<uroCamWatchObjects.length;camidx++)
  1431. {
  1432. if(uroCamDataChanged(camidx))
  1433. {
  1434. camsChanged.push(uroCamWatchObjects[camidx]);
  1435. }
  1436. }
  1437. }
  1438.  
  1439. for(camidx=0;camidx<uroCamWatchObjects.length;camidx++)
  1440. {
  1441. camObj = uroCamWatchObjects[camidx];
  1442. if((camObj.loaded === false) && (camObj.server == W.location.code))
  1443. {
  1444. camsDeleted.push(camObj);
  1445. }
  1446. }
  1447.  
  1448. if((camsChanged.length > 0) || (camsDeleted.length > 0))
  1449. {
  1450. var alertStr = 'Camera WatchList Alert!!!\r\n';
  1451. for(camidx=0;camidx<camsChanged.length;camidx++)
  1452. {
  1453. alertStr += 'Camera ID '+camsChanged[camidx].fid+' in group "'+uroFindCWLGroupByIdx(camsChanged[camidx].groupID)+'" has been changed\r\n';
  1454. }
  1455. for(camidx=0;camidx<camsDeleted.length;camidx++)
  1456. {
  1457. alertStr += 'Camera ID '+camsDeleted[camidx].fid+' in group "'+uroFindCWLGroupByIdx(camsDeleted[camidx].groupID)+'" has been deleted\r\n';
  1458. }
  1459. alert(alertStr);
  1460. }
  1461. }
  1462. function uroClearDeletedCameras()
  1463. {
  1464. for(var camidx=uroCamWatchObjects.length-1;camidx>=0;camidx--)
  1465. {
  1466. if(uroCamWatchObjects[camidx].loaded === false)
  1467. {
  1468. uroShownFID = uroCamWatchObjects[camidx].fid;
  1469. uroRemoveCamFromWatchList();
  1470. }
  1471. }
  1472. }
  1473. function uroClearUnknownServerCameras()
  1474. {
  1475. var confirmMsg = 'Cameras with an unknown server cannot be automatically verified by URO+.\n';
  1476. 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.\n';
  1477. confirmMsg += 'If the cameras then continue to show up as an unknown server, it is safe to delete them...\n\n';
  1478. confirmMsg += 'Do you still wish to proceed with deleting all unknown server cameras?';
  1479.  
  1480. if(confirm(confirmMsg) === true)
  1481. {
  1482. for(var camidx=uroCamWatchObjects.length-1;camidx>=0;camidx--)
  1483. {
  1484. if(uroCamWatchObjects[camidx].server == '??')
  1485. {
  1486. uroShownFID = uroCamWatchObjects[camidx].fid;
  1487. uroRemoveCamFromWatchList();
  1488. }
  1489. }
  1490. }
  1491. }
  1492. function uroRescanCamWatchList()
  1493. {
  1494. for(var camidx=0;camidx<uroCamWatchObjects.length;camidx++)
  1495. {
  1496. uroCamWatchObjects[camidx].loaded = false;
  1497. }
  1498. uroGetCurrentCamWatchListObjects();
  1499. uroOWLUpdateHTML();
  1500. }
  1501. function uroGotoCam()
  1502. {
  1503. var camidx = this.id.substr(13);
  1504. var camPos = new OpenLayers.LonLat();
  1505. camPos.lon = uroCamWatchObjects[camidx].watch.lon;
  1506. camPos.lat = uroCamWatchObjects[camidx].watch.lat;
  1507. W.map.setCenter(camPos,4);
  1508. W.map.camerasLayer.setVisibility(true);
  1509. return false;
  1510. }
  1511.  
  1512. // Segment Functions
  1513. function uroSegWatchObjCheckProps(left, right, bottom, top, fromNode, toNode, fwdDir, revDir, length, level, rank, roadType, updatedOn)
  1514. {
  1515. if(left !== null) left = uroTruncate(uroTypeCast(left));
  1516. if(right !== null) right = uroTruncate(uroTypeCast(right));
  1517. if(bottom !== null) bottom = uroTruncate(uroTypeCast(bottom));
  1518. if(top !== null) top = uroTruncate(uroTypeCast(top));
  1519. if(fromNode !== null) fromNode = uroTypeCast(fromNode);
  1520. if(toNode !== null) toNode = uroTypeCast(toNode);
  1521. if(fwdDir !== null) fwdDir = uroTypeCast(fwdDir);
  1522. if(revDir !== null) revDir = uroTypeCast(revDir);
  1523. if(length !== null) length = uroTypeCast(length);
  1524. if(level !== null) level = uroTypeCast(level);
  1525. if(rank !== null) rank = uroTypeCast(rank);
  1526. if(roadType !== null) roadType = uroTypeCast(roadType);
  1527. if(updatedOn !== null) updatedOn = uroTypeCast(updatedOn);
  1528.  
  1529. this.left = left;
  1530. this.right = right;
  1531. this.bottom = bottom;
  1532. this.top = top;
  1533. this.fromNode = fromNode;
  1534. this.toNode = toNode;
  1535. this.fwdDir = fwdDir;
  1536. this.revDir = revDir;
  1537. this.length = length;
  1538. this.level = level;
  1539. this.rank = rank;
  1540. this.roadType = roadType;
  1541. this.updatedOn = updatedOn;
  1542. }
  1543. function uroSegWatchObj(persistent, fid, left, right, bottom, top, fromNode, toNode, fwdDir, revDir, length, level, rank, roadType, updatedOn, groupID, server)
  1544. {
  1545. fid = uroTypeCast(fid);
  1546. groupID = uroTypeCast(groupID);
  1547. if(typeof persistent == "string") persistent = (persistent == "true");
  1548.  
  1549. this.fid = fid;
  1550. this.persistent = persistent;
  1551. this.loaded = false;
  1552. this.server = server;
  1553. this.groupID = groupID;
  1554.  
  1555. this.watch = new uroSegWatchObjCheckProps(left, right, bottom, top, fromNode, toNode, fwdDir, revDir, length, level, rank, roadType, updatedOn);
  1556. this.current = new uroSegWatchObjCheckProps(null, null, null, null, null, null, null, null, null, null, null, null, null);
  1557. }
  1558. function uroSegDataChanged(idx)
  1559. {
  1560. var segObj = uroSegWatchObjects[idx];
  1561. if(segObj.loaded === false) return false;
  1562. if(segObj.current.left != segObj.watch.left) return true;
  1563. if(segObj.current.right != segObj.watch.right) return true;
  1564. if(segObj.current.bottom != segObj.watch.bottom) return true;
  1565. if(segObj.current.top != segObj.watch.top) return true;
  1566. if(segObj.current.fromNode != segObj.watch.fromNode) return true;
  1567. if(segObj.current.toNode != segObj.watch.toNode) return true;
  1568. if(segObj.current.fwdDir != segObj.watch.fwdDir) return true;
  1569. if(segObj.current.revDir != segObj.watch.revDir) return true;
  1570. if(segObj.current.length != segObj.watch.length) return true;
  1571. if(segObj.current.level != segObj.watch.level) return true;
  1572. if(segObj.current.rank != segObj.watch.rank) return true;
  1573. if(segObj.current.roadType != segObj.watch.roadType) return true;
  1574. if(segObj.current.updatedOn != segObj.watch.updatedOn) return true;
  1575. return false;
  1576. }
  1577. function uroIsSegOnWatchList(fid)
  1578. {
  1579. for(var loop=0;loop<uroSegWatchObjects.length;loop++)
  1580. {
  1581. if(uroSegWatchObjects[loop].fid == fid) return loop;
  1582. }
  1583. return -1;
  1584. }
  1585. function uroAddCurrentSegWatchData(idx, left, right, bottom, top, fromNode, toNode, fwdDir, revDir, length, level, rank, roadType, updatedOn, server)
  1586. {
  1587. var segObj = uroSegWatchObjects[idx];
  1588. segObj.loaded = true;
  1589. segObj.server = server;
  1590. segObj.current = new uroSegWatchObjCheckProps(left, right, bottom, top, fromNode, toNode, fwdDir, revDir, length, level, rank, roadType, updatedOn);
  1591. return(uroSegDataChanged(idx));
  1592. }
  1593. function uroClearSegWatchList()
  1594. {
  1595. if(confirm('Removing all segments from the OWL cannot be undone\nAre you sure you want to do this?') === true)
  1596. {
  1597. uroSegWatchObjects = [];
  1598. uroOWLUpdateHTML();
  1599. }
  1600. }
  1601. function uroAddUpdateSegWatchList()
  1602. {
  1603. var selectedCount = W.selectionManager.selectedItems.length;
  1604. if(selectedCount === 0)
  1605. {
  1606. return;
  1607. }
  1608.  
  1609. for(var loop=0;loop < selectedCount; loop++)
  1610. {
  1611. var segObj = W.selectionManager.selectedItems[loop].model.attributes;
  1612. var fid = segObj.id;
  1613. var idx = uroIsSegOnWatchList(fid);
  1614. if(idx != -1)
  1615. {
  1616. 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);
  1617. uroAddLog('updated watchlist details for segment '+fid);
  1618. }
  1619. else
  1620. {
  1621. 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));
  1622. 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);
  1623. uroAddLog('added segment '+fid+' to watchlist');
  1624. }
  1625. }
  1626. //uroOWLUpdateHTML();
  1627. }
  1628. function uroRemoveSegFromWatchList()
  1629. {
  1630. var selectedCount = W.selectionManager.selectedItems.length;
  1631. if(selectedCount === 0)
  1632. {
  1633. return;
  1634. }
  1635.  
  1636. for(var loop=0;loop < selectedCount; loop++)
  1637. {
  1638. var fid = W.selectionManager.selectedItems[loop].model.attributes.id;
  1639. var idx = uroIsSegOnWatchList(fid);
  1640. if(idx != -1)
  1641. {
  1642. uroSegWatchObjects.splice(idx,1);
  1643. uroAddLog('removed segment '+fid+' from watchlist');
  1644. }
  1645. }
  1646. //uroOWLUpdateHTML();
  1647. }
  1648. function uroRetrieveSegments(lat, lon)
  1649. {
  1650. var pos = new OpenLayers.LonLat();
  1651. var changed = false;
  1652.  
  1653. pos.lon = lon;
  1654. pos.lat = lat;
  1655. pos.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326"));
  1656.  
  1657. var URL = 'https://' + document.location.host;
  1658. URL += Waze.Config.api_base;
  1659. URL += '/Features?roadTypes=1%2C2%2C3%2C4%2C5%2C6%2C7%2C8%2C9%2C10%2C11%2C12%2C13%2C14%2C15%2C16%2C17%2C18%2C19%2C20%2C21';
  1660. URL += '&bbox=';
  1661. var latl = pos.lat - 0.25;
  1662. var latu = pos.lat + 0.25;
  1663. var lonl = pos.lon - 0.25;
  1664. var lonr = pos.lon + 0.25;
  1665. URL += lonl+','+latl+','+lonr+','+latu;
  1666. URL += '&language=en';
  1667. uroAddLog('retrieving segment data around '+pos.lon+','+pos.lat);
  1668.  
  1669. var req = new XMLHttpRequest();
  1670. req.open('GET',URL,false);
  1671. try
  1672. {
  1673. req.send();
  1674. uroAddLog('response '+req.status+' received');
  1675. if (req.status === 200)
  1676. {
  1677. var data = JSON.parse(req.responseText);
  1678. for(var idx = 0; idx < data.segments.objects.length; idx++)
  1679. {
  1680. var obj = data.segments.objects[idx];
  1681. var listIdx = uroIsSegOnWatchList(obj.id);
  1682. if(listIdx != -1)
  1683. {
  1684. //pos.lon = obj.geometry.coordinates[0];
  1685. //pos.lat = obj.geometry.coordinates[1];
  1686. //pos.transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913"));
  1687. //camPos.lon = uroTruncate(camPos.lon);
  1688. //camPos.lat = uroTruncate(camPos.lat);
  1689. //camChanged |= uroAddCurrentCamWatchData(listIdx, camPos.lat, camPos.lon, camObj.type, camObj.azymuth, camObj.speed, camObj.validated, W.location.code);
  1690. }
  1691. else if(obj.validated === false)
  1692. {
  1693.  
  1694. }
  1695. }
  1696. }
  1697. else
  1698. {
  1699. uroAddLog('request failed (status != 200)');
  1700. }
  1701. }
  1702. catch(err)
  1703. {
  1704. uroAddLog('segment load request failed (exception '+err+' caught)');
  1705. }
  1706. return changed;
  1707. }
  1708. function uroGetCurrentSegWatchListObjects()
  1709. {
  1710. var segChanged = false;
  1711. var segsChanged = [];
  1712. var segsDeleted = [];
  1713. var idx;
  1714. var segObj;
  1715.  
  1716. for(idx=0;idx<uroSegWatchObjects.length;idx++)
  1717. {
  1718. segObj = uroSegWatchObjects[idx];
  1719. if((segObj.loaded === false) && ((segObj.server == W.location.code) || (segObj.server == '??')))
  1720. {
  1721. var segLat = (segObj.watch.top + segObj.watch.bottom) / 2;
  1722. var segLon = (segObj.watch.right + segObj.watch.left) / 2;
  1723. if(typeof W.model.segments.objects[segObj.fid] == 'object')
  1724. {
  1725. if(W.model.segments.objects[segObj.fid].state != "Delete")
  1726. {
  1727. var wazeObj = W.model.segments.objects[segObj.fid];
  1728. 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);
  1729. }
  1730. else
  1731. {
  1732. segChanged |= uroRetrieveSegments(segLat, segLon);
  1733. }
  1734. }
  1735. else
  1736. {
  1737. segChanged |= uroRetrieveSegments(segLat, segLon);
  1738. }
  1739. }
  1740. }
  1741.  
  1742. if(segChanged)
  1743. {
  1744. for(idx=0;idx<uroSegWatchObjects.length;idx++)
  1745. {
  1746. if(uroSegDataChanged(idx))
  1747. {
  1748. segsChanged.push(uroSegWatchObjects[idx]);
  1749. }
  1750. }
  1751. }
  1752.  
  1753. for(idx=0;idx<uroSegWatchObjects.length;idx++)
  1754. {
  1755. segObj = uroSegWatchObjects[idx];
  1756. if((segObj.loaded === false) && (segObj.server == W.location.code))
  1757. {
  1758. segsDeleted.push(segObj);
  1759. }
  1760. }
  1761.  
  1762. if((segsChanged.length > 0) || (segsDeleted.length > 0))
  1763. {
  1764. var alertStr = 'Segment WatchList Alert!!!\r\n';
  1765. for(idx=0;idx<segsChanged.length;idx++)
  1766. {
  1767. alertStr += 'Segment ID '+segsChanged[idx].fid+' in group "'+uroFindCWLGroupByIdx(segsChanged[idx].groupID)+'" has been changed\r\n';
  1768. }
  1769. for(idx=0;idx<segsDeleted.length;idx++)
  1770. {
  1771. alertStr += 'Segment ID '+segsDeleted[idx].fid+' in group "'+uroFindCWLGroupByIdx(segsDeleted[idx].groupID)+'" has been deleted\r\n';
  1772. }
  1773. alert(alertStr);
  1774. }
  1775. }
  1776.  
  1777. // Places Functions
  1778. function uroPlaceWatchObjCheckProps(left, right, bottom, top, name, imageCount, residential, updatedOn)
  1779. {
  1780. if(left !== null) left = uroTruncate(uroTypeCast(left));
  1781. if(right !== null) right = uroTruncate(uroTypeCast(right));
  1782. if(bottom !== null) bottom = uroTruncate(uroTypeCast(bottom));
  1783. if(top !== null) top = uroTruncate(uroTypeCast(top));
  1784. if(imageCount !== null) imageCount = uroTypeCast(imageCount);
  1785. if(typeof residential == "string") residential = (residential == "true");
  1786. if(updatedOn !== null) updatedOn = uroTypeCast(updatedOn);
  1787.  
  1788. this.left = left;
  1789. this.right = right;
  1790. this.bottom = bottom;
  1791. this.top = top;
  1792. this.name = name;
  1793. this.imageCount = imageCount;
  1794. this.residential = residential;
  1795. this.updatedOn = updatedOn;
  1796. }
  1797. function uroPlaceWatchObj(persistent, fid, left, right, bottom, top, imageCount, name, residential, updatedOn, groupID, server)
  1798. {
  1799. groupID = uroTypeCast(groupID);
  1800. if(typeof persistent == "string") persistent = (persistent == "true");
  1801.  
  1802. this.fid = fid;
  1803. this.persistent = persistent;
  1804. this.loaded = false;
  1805. this.server = server;
  1806. this.groupID = groupID;
  1807. this.watch = new uroPlaceWatchObjCheckProps(left, right, bottom, top, name, imageCount, residential, updatedOn);
  1808. this.current = new uroPlaceWatchObjCheckProps(null, null, null, null, null, null, null, null);
  1809. }
  1810. function uroPlaceDataChanged(idx)
  1811. {
  1812. var placeObj = uroPlaceWatchObjects[idx];
  1813. if(placeObj.loaded === false) return false;
  1814. if(placeObj.current.left != placeObj.watch.left) return true;
  1815. if(placeObj.current.right != placeObj.watch.right) return true;
  1816. if(placeObj.current.bottom != placeObj.watch.bottom) return true;
  1817. if(placeObj.current.top != placeObj.watch.top) return true;
  1818. if(placeObj.current.name != placeObj.watch.name) return true;
  1819. if(placeObj.current.imageCount != placeObj.watch.imageCount) return true;
  1820. if(placeObj.current.residential != placeObj.watch.residential) return true;
  1821. if(placeObj.current.updatedOn != placeObj.watch.updatedOn) return true;
  1822. return false;
  1823. }
  1824. function uroIsPlaceOnWatchList(fid)
  1825. {
  1826. for(var loop=0;loop<uroPlaceWatchObjects.length;loop++)
  1827. {
  1828. if(uroPlaceWatchObjects[loop].fid == fid) return loop;
  1829. }
  1830. return -1;
  1831. }
  1832. function uroClearPlaceWatchList()
  1833. {
  1834. if(confirm('Removing all places from the OWL cannot be undone\nAre you sure you want to do this?') === true)
  1835. {
  1836. uroPlaceWatchObjects = [];
  1837. uroOWLUpdateHTML();
  1838. }
  1839. }
  1840.  
  1841.  
  1842. function uroHighlightCWLEntry()
  1843. {
  1844. this.style.backgroundColor = '#FFFFAA';
  1845. return false;
  1846. }
  1847. function uroUnhighlightCWLEntry()
  1848. {
  1849. var camidx = this.id.substr(8);
  1850. var changed = uroCamDataChanged(camidx);
  1851. var deleted = (uroCamWatchObjects[camidx].loaded === false);
  1852.  
  1853. if(uroCamWatchObjects[camidx].server != W.location.code)
  1854. {
  1855. if(uroCamWatchObjects[camidx].server == '??') this.style.backgroundColor = '#A0A0A0';
  1856. else this.style.backgroundColor = '#AAFFAA';
  1857. }
  1858. else if(changed) this.style.backgroundColor = '#AAAAFF';
  1859. else if(deleted) this.style.backgroundColor = '#FFAAAA';
  1860. else this.style.backgroundColor = '#FFFFFF';
  1861. return false;
  1862. }
  1863. function uroCWLIconHighlight()
  1864. {
  1865. var iconType = this.id.substr(11,1);
  1866. this.src = uroIcons[iconType][0];
  1867. return false;
  1868. }
  1869. function uroCWLIconLowlight()
  1870. {
  1871. var iconType = this.id.substr(11,1);
  1872. this.src = uroIcons[iconType][1];
  1873. return false;
  1874. }
  1875. function uroPopulateCWLGroupSelect()
  1876. {
  1877. var selector = document.getElementById('_uroCWLGroupSelect');
  1878. while(selector.options.length > 0)
  1879. {
  1880. selector.options.remove(0);
  1881. }
  1882. for(var loop=0;loop<uroCWLGroups.length;loop++)
  1883. {
  1884. var groupObj = uroCWLGroups[loop];
  1885. if(groupObj.groupID != -1)
  1886. {
  1887. selector.options.add(new Option(groupObj.groupName,groupObj.groupID));
  1888. }
  1889. }
  1890. }
  1891. function uroGetNextCWLGroupID()
  1892. {
  1893. var nextID = 1;
  1894. for(var loop=0;loop<uroCWLGroups.length;loop++)
  1895. {
  1896. if(uroCWLGroups[loop].groupID >= nextID)
  1897. {
  1898. nextID = uroCWLGroups[loop].groupID + 1;
  1899. }
  1900. }
  1901. return nextID;
  1902. }
  1903. function uroFindCWLGroupByName(groupName)
  1904. {
  1905. var groupID = -1;
  1906. for(var loop=0;loop<uroCWLGroups.length;loop++)
  1907. {
  1908. if((uroCWLGroups[loop].groupName == groupName) && (uroCWLGroups[loop].groupID != -1))
  1909. {
  1910. groupID = uroCWLGroups[loop].groupID;
  1911. break;
  1912. }
  1913. }
  1914. return groupID;
  1915. }
  1916. function uroAddCWLGroup()
  1917. {
  1918. var groupID = uroGetNextCWLGroupID();
  1919. var groupName = uroGetElmValue('_uroCWLGroupEntry');
  1920. if(uroFindCWLGroupByName(groupName) == -1)
  1921. {
  1922. uroCWLGroups.push(new uroOWLGroupObj(groupID,groupName,false));
  1923. uroPopulateCWLGroupSelect();
  1924. }
  1925. }
  1926. function uroRemoveCWLGroup()
  1927. {
  1928. var loop;
  1929. var selector = document.getElementById('_uroCWLGroupSelect');
  1930. var groupID = parseInt(selector.selectedOptions[0].value);
  1931. if(groupID === 0) return false; // prevent deletion of the default group
  1932.  
  1933. for(loop=0;loop<uroCamWatchObjects.length;loop++)
  1934. {
  1935. var cwObj = uroCamWatchObjects[loop];
  1936. if(cwObj.groupID == groupID)
  1937. {
  1938. cwObj.groupID = 0;
  1939. }
  1940. }
  1941. for(loop=0;loop<uroCWLGroups.length;loop++)
  1942. {
  1943. var groupObj = uroCWLGroups[loop];
  1944. if(groupObj.groupID == groupID)
  1945. {
  1946. groupObj.groupID = -1;
  1947. }
  1948. }
  1949. uroOWLUpdateHTML();
  1950. }
  1951. function uroAssignCameraToGroup()
  1952. {
  1953. var camidx = this.id.substr(13);
  1954. var selector = document.getElementById('_uroCWLGroupSelect');
  1955. uroCamWatchObjects[camidx].groupID = parseInt(selector.selectedOptions[0].value);
  1956. uroOWLUpdateHTML();
  1957. return false;
  1958. }
  1959. function uroAddBtnEvl(btnID, evlType, evlFunction)
  1960. {
  1961. var btnObj = document.getElementById(btnID);
  1962. if(btnObj !== null)
  1963. {
  1964. btnObj.addEventListener(evlType, evlFunction, true);
  1965. }
  1966. }
  1967. function uroCWLGroupCollapseExpand()
  1968. {
  1969. var groupidx = this.id.substr(18);
  1970. if(uroCWLGroups[groupidx].groupCollapsed === true) uroCWLGroups[groupidx].groupCollapsed = false;
  1971. else uroCWLGroups[groupidx].groupCollapsed = true;
  1972. uroOWLUpdateHTML();
  1973. return false;
  1974. }
  1975. function uroOWLUpdateHTML()
  1976. {
  1977. var camTypes = new Array("","","Speed", "Dummy", "Red Light");
  1978. var selectedGroup = 0;
  1979. var iHTML = '';
  1980. var camidx;
  1981. var groupidx;
  1982.  
  1983. if(document.getElementById('_uroCWLGroupSelect') !== null)
  1984. {
  1985. selectedGroup = document.getElementById('_uroCWLGroupSelect').selectedIndex;
  1986. }
  1987. iHTML = '<br><b>Camera Watchlist:</b><br><br>';
  1988. iHTML += '<div id="_uroCWLCamList" style="height:65%;overflow:auto;">';
  1989. if(uroCWLGroups.length > 0)
  1990. {
  1991. for(groupidx=0;groupidx<uroCWLGroups.length;groupidx++)
  1992. {
  1993. var groupObj = uroCWLGroups[groupidx];
  1994. iHTML += '<div id="_uroCWLGroup-'+groupidx+'">';
  1995. if(groupObj.groupCollapsed === true)
  1996. {
  1997. iHTML += '<img src="'+uroIcons[0][1]+'" id="_uroCWLGroupState-'+groupidx+'">';
  1998. }
  1999. else
  2000. {
  2001. iHTML += '<img src="'+uroIcons[0][0]+'" id="_uroCWLGroupState-'+groupidx+'">';
  2002. }
  2003. iHTML += '<b>'+groupObj.groupName+'</b><br>';
  2004. groupObj.groupCount = 0;
  2005. if(uroCamWatchObjects.length > 0)
  2006. {
  2007. for(camidx=0;camidx<uroCamWatchObjects.length;camidx++)
  2008. {
  2009. var camObj = uroCamWatchObjects[camidx];
  2010. if(camObj.groupID == groupObj.groupID)
  2011. {
  2012. groupObj.groupCount++;
  2013. var changed = uroCamDataChanged(camidx);
  2014. var deleted = (camObj.loaded === false);
  2015. iHTML += '<div id="_uroCWL-'+camidx+'" style="padding:3px;border-width:2px;border-style:solid;border-color:#FFFFFF;background-color:';
  2016. if(camObj.server != W.location.code)
  2017. {
  2018. if(camObj.server == '??') iHTML += '#A0A0A0;';
  2019. else iHTML += '#AAFFAA;';
  2020. }
  2021. else if(changed) iHTML += '#AAAAFF;';
  2022. else if(deleted) iHTML += '#FFAAAA;';
  2023. else iHTML += '#FFFFFF;';
  2024.  
  2025. if(groupObj.groupCollapsed === true) iHTML += 'display:none;">';
  2026. else iHTML += 'display:block;">';
  2027.  
  2028. iHTML += 'ID: '+camObj.fid;
  2029. iHTML += ' ('+camObj.server+')';
  2030. iHTML += ' Type: '+camTypes[camObj.watch.type];
  2031. if(camObj.server != W.location.code)
  2032. {
  2033. if(camObj.server == '??')
  2034. {
  2035. iHTML += '<br><i>Unknown server</i>';
  2036. }
  2037. else
  2038. {
  2039. iHTML += '<br><i>Not on this server</i>';
  2040. }
  2041. }
  2042. else if(deleted)
  2043. {
  2044. iHTML += '<br>DELETED';
  2045. }
  2046. else if(changed)
  2047. {
  2048. if(camObj.current.type != camObj.watch.type)
  2049. {
  2050. iHTML += '<br>&nbsp;&nbsp;Type changed';
  2051. iHTML += ' ('+camObj.watch.type+' to '+camObj.current.type+')';
  2052. }
  2053. if(camObj.current.azymuth != camObj.watch.azymuth)
  2054. {
  2055. iHTML += '<br>&nbsp;&nbsp;Azimuth changed';
  2056. iHTML += ' ('+camObj.watch.azymuth+' to '+camObj.current.azymuth+')';
  2057. }
  2058. if(camObj.current.speed != camObj.watch.speed)
  2059. {
  2060. iHTML += '<br>&nbsp;&nbsp;Speed changed';
  2061. iHTML += ' ('+camObj.watch.speed+' to '+camObj.current.speed+')';
  2062. }
  2063. if(camObj.current.validated != camObj.watch.validated)
  2064. {
  2065. iHTML += '<br>&nbsp;&nbsp;Approval state changed';
  2066. iHTML += ' ('+camObj.watch.validated+' to '+camObj.current.validated+')';
  2067. }
  2068. if(camObj.current.lat != camObj.watch.lat)
  2069. {
  2070. iHTML += '<br>&nbsp;&nbsp;Latitude changed';
  2071. iHTML += ' ('+camObj.watch.lat+' to '+camObj.current.lat+')';
  2072. }
  2073. if(camObj.current.lon != camObj.watch.lon)
  2074. {
  2075. iHTML += '<br>&nbsp;&nbsp;Longitude changed';
  2076. iHTML += ' ('+camObj.watch.lon+' to '+camObj.current.lon+')';
  2077. }
  2078. }
  2079.  
  2080. if(camObj.server == W.location.code)
  2081. {
  2082. if(deleted === false)
  2083. {
  2084. iHTML += '&nbsp;<img id="_uroCWLIcon1-'+camidx+'" src="'+uroIcons[1][1]+'">';
  2085. }
  2086. iHTML += '&nbsp;<img id="_uroCWLIcon2-'+camidx+'" src="'+uroIcons[2][1]+'">';
  2087. }
  2088. iHTML += '</div>';
  2089. }
  2090. }
  2091. }
  2092. iHTML += '</div>';
  2093. }
  2094. }
  2095. iHTML += '</div><div id="_uroCWLControls">';
  2096. iHTML += '<hr>Group control:<br>';
  2097. iHTML += '<select id="_uroCWLGroupSelect" style="width:40%;height:22px;"></select>&nbsp;<input type="button" id="_btnCWLGroupDel" value="Delete group"><br>';
  2098. iHTML += '<input type="text" id="_uroCWLGroupEntry" style="width:40%;height:22px;">&nbsp;<input type="button" id="_btnCWLGroupAdd" value="Add group">';
  2099. iHTML += '<br><input type="button" id="_btnRescanCamWatchList" value="Refresh Camera Data"><br><br>';
  2100. iHTML += '<b>Remove cameras from OWL:</b><br>';
  2101. iHTML += '<input type="button" id="_btnRemoveDeletedCameras" value="Deleted">&nbsp;&nbsp;';
  2102. iHTML += '<input type="button" id="_btnRemoveUnknownServerCameras" value="Unknown Server">&nbsp;&nbsp;';
  2103. iHTML += '<input type="button" id="_btnClearCamWatchList" value="ALL Cameras">';
  2104. iHTML += '</div>';
  2105. uroOWL.innerHTML = iHTML;
  2106.  
  2107. if(uroCamWatchObjects.length > 0)
  2108. {
  2109. for(camidx=0;camidx<uroCamWatchObjects.length;camidx++)
  2110. {
  2111. document.getElementById("_uroCWL-"+camidx).onmouseover = uroHighlightCWLEntry;
  2112. document.getElementById("_uroCWL-"+camidx).onmouseleave = uroUnhighlightCWLEntry;
  2113.  
  2114. if(uroCamWatchObjects[camidx].server == W.location.code)
  2115. {
  2116. var icon1 = document.getElementById("_uroCWLIcon1-"+camidx);
  2117. var icon2 = document.getElementById("_uroCWLIcon2-"+camidx);
  2118. if(icon1 !== null)
  2119. {
  2120. icon1.onmouseover = uroCWLIconHighlight;
  2121. icon1.onmouseleave = uroCWLIconLowlight;
  2122. icon1.onclick = uroAssignCameraToGroup;
  2123. }
  2124. if(icon2 !== null)
  2125. {
  2126. icon2.onmouseover = uroCWLIconHighlight;
  2127. icon2.onmouseleave = uroCWLIconLowlight;
  2128. icon2.onclick = uroGotoCam;
  2129. }
  2130. }
  2131. }
  2132. }
  2133.  
  2134. uroAddBtnEvl('_btnClearCamWatchList', 'click', uroClearCamWatchList);
  2135. uroAddBtnEvl('_btnRemoveDeletedCameras', 'click', uroClearDeletedCameras);
  2136. uroAddBtnEvl('_btnRemoveUnknownServerCameras', 'click', uroClearUnknownServerCameras);
  2137. uroAddBtnEvl('_btnRescanCamWatchList', 'click', uroRescanCamWatchList);
  2138. uroAddBtnEvl('_btnCWLGroupDel', 'click', uroRemoveCWLGroup);
  2139. uroAddBtnEvl('_btnCWLGroupAdd', 'click', uroAddCWLGroup);
  2140. if(document.getElementById('_uroCWLGroupSelect') !== null)
  2141. {
  2142. uroAddLog('populating CWL group list');
  2143. uroPopulateCWLGroupSelect();
  2144. var selector = document.getElementById('_uroCWLGroupSelect');
  2145. if(selectedGroup >= selector.length)
  2146. {
  2147. selectedGroup = 0;
  2148. }
  2149. selector.selectedIndex = selectedGroup;
  2150. }
  2151.  
  2152. if(uroCWLGroups.length > 0)
  2153. {
  2154. for(groupidx=0;groupidx<uroCWLGroups.length;groupidx++)
  2155. {
  2156. if(uroCWLGroups[groupidx].groupCount === 0)
  2157. {
  2158. uroSetStyleDisplay('_uroCWLGroup-'+groupidx,'none');
  2159. }
  2160. else
  2161. {
  2162. uroSetOnClick('_uroCWLGroupState-'+groupidx,uroCWLGroupCollapseExpand);
  2163. }
  2164. }
  2165. }
  2166. }
  2167.  
  2168. // --------------------------------------------------------------------------------------------------------------------
  2169. // END OF WATCHLIST STUFF
  2170. // --------------------------------------------------------------------------------------------------------------------
  2171.  
  2172.  
  2173. function uroIsOnIgnoreList(fid)
  2174. {
  2175. if(sessionStorage.UROverview_FID_IgnoreList.indexOf('fid:'+fid) == -1) return false;
  2176. else return true;
  2177. }
  2178.  
  2179. function uroEnableIgnoreListControls()
  2180. {
  2181. var btnState = "visible";
  2182. if(sessionStorage.UROverview_FID_IgnoreList === '')
  2183. {
  2184. btnState = "hidden";
  2185. }
  2186. document.getElementById('_btnUndoLastHide').style.visibility = btnState;
  2187. document.getElementById('_btnClearSessionHides').style.visibility = btnState;
  2188. uroFilterItems();
  2189. }
  2190.  
  2191. function uroAddToIgnoreList()
  2192. {
  2193. if(!uroIsOnIgnoreList(uroShownFID))
  2194. {
  2195. sessionStorage.UROverview_FID_IgnoreList += 'fid:'+uroShownFID;
  2196. uroAddLog('added fid '+uroShownFID+' to ignore list');
  2197. uroAddLog(sessionStorage.UROverview_FID_IgnoreList);
  2198. uroDiv.style.visibility = 'hidden';
  2199. uroEnableIgnoreListControls();
  2200. W.map.events.register("mousemove", null, uroFilterItemsOnMove);
  2201. }
  2202. return false;
  2203. }
  2204.  
  2205. /*
  2206. function uroRemoveFromIgnoreList(fid)
  2207. {
  2208. var ignorelist = sessionStorage.UROverview_FID_IgnoreList;
  2209. var fidpos = ignorelist.indexOf('fid:'+fid);
  2210. if(fidpos != -1)
  2211. {
  2212. var preFID = ignorelist.slice(0,fidpos);
  2213. ignorelist = ignorelist.slice(fidpos+1);
  2214. fidpos = ignorelist.indexOf('fid:');
  2215. if(fidpos == -1) ignorelist = '';
  2216. else ignorelist = ignorelist.slice(fidpos);
  2217. sessionStorage.UROverview_FID_IgnoreList = preFID + ignorelist;
  2218. uroAddLog('removed fid '+fid+' from ignore list');
  2219. uroAddLog(sessionStorage.UROverview_FID_IgnoreList);
  2220. uroEnableIgnoreListControls();
  2221. }
  2222. }
  2223. */
  2224.  
  2225. function uroRemoveLastAddedIgnore()
  2226. {
  2227. var ignorelist = sessionStorage.UROverview_FID_IgnoreList;
  2228. var fidpos = ignorelist.lastIndexOf('fid:');
  2229. if(fidpos != -1)
  2230. {
  2231. ignorelist = ignorelist.slice(0,fidpos);
  2232. sessionStorage.UROverview_FID_IgnoreList = ignorelist;
  2233. uroAddLog('removed last fid from ignore list');
  2234. uroAddLog(sessionStorage.UROverview_FID_IgnoreList);
  2235. uroEnableIgnoreListControls();
  2236. }
  2237. }
  2238.  
  2239. function uroRemoveAllIgnores()
  2240. {
  2241. sessionStorage.UROverview_FID_IgnoreList = '';
  2242. uroEnableIgnoreListControls();
  2243. }
  2244.  
  2245.  
  2246. function uroKeywordPresent(desc, keyword)
  2247. {
  2248. var re;
  2249. if(uroGetCBChecked('_cbCaseInsensitive') === true) re = RegExp(keyword,'i');
  2250. else re = RegExp(keyword);
  2251.  
  2252. if(desc.search(re) != -1) return true;
  2253. else return false;
  2254. }
  2255.  
  2256.  
  2257. function uroClickify(desc)
  2258. {
  2259. var linkStartPos = desc.indexOf('http://');
  2260. if(linkStartPos == -1) linkStartPos = desc.indexOf('https://');
  2261. if(linkStartPos != -1)
  2262. {
  2263. var descPreLink = desc.slice(0,linkStartPos);
  2264. var descURL = desc.slice(linkStartPos);
  2265. var linkEndPos = descURL.indexOf(' ');
  2266. var descPostLink = '';
  2267. if(linkEndPos != -1)
  2268. {
  2269. descPostLink = descURL.slice(linkEndPos);
  2270. descURL = descURL.slice(0,linkEndPos);
  2271. }
  2272. var linkTarget = '';
  2273. if(descURL.indexOf('cryosphere') != -1) linkTarget = '_cryosphere';
  2274. else if(descURL.indexOf('waze.com') != -1) linkTarget = '_wazeUR';
  2275. desc = descPreLink + '<a target="'+linkTarget+'" href="'+descURL+'">here</a>' + descPostLink;
  2276. }
  2277. return desc;
  2278. }
  2279.  
  2280.  
  2281. function uroRefreshUpdateRequestSessions()
  2282. {
  2283. for (var urID in W.model.mapUpdateRequests.objects)
  2284. {
  2285. if(W.model.mapUpdateRequests.objects.hasOwnProperty(urID))
  2286. {
  2287. var reqPos = uroRequestedURSessionIDs.indexOf(urID);
  2288. var pendPos = uroPendingURSessionIDs.indexOf(urID);
  2289. if(W.model.updateRequestSessions.objects[urID] === undefined)
  2290. {
  2291. if((reqPos == -1) && (pendPos == -1))
  2292. {
  2293. uroPendingURSessionIDs.push(urID);
  2294. }
  2295. }
  2296. else
  2297. {
  2298. if(reqPos != -1)
  2299. {
  2300. uroRequestedURSessionIDs.splice(reqPos,1);
  2301. }
  2302. if(pendPos != -1)
  2303. {
  2304. uroPendingURSessionIDs.splice(pendPos,1);
  2305. }
  2306. }
  2307. }
  2308. }
  2309.  
  2310. var idList = [];
  2311.  
  2312. while((idList.length < 500) && (uroPendingURSessionIDs.length))
  2313. {
  2314. var id = uroPendingURSessionIDs.pop();
  2315. idList.push(id);
  2316. uroRequestedURSessionIDs.push(id);
  2317. }
  2318.  
  2319. if(idList.length > 0)
  2320. {
  2321. uroAddLog('grabbing updateRequestSessions with IDs '+idList);
  2322. W.model.updateRequestSessions.get(idList);
  2323. }
  2324.  
  2325. if((uroPendingURSessionIDs.length) || (uroRequestedURSessionIDs.length))
  2326. {
  2327. setTimeout(uroRefreshUpdateRequestSessions,10);
  2328. }
  2329. }
  2330.  
  2331. function uroURHasMyComments(fid)
  2332. {
  2333. var nComments = W.model.updateRequestSessions.objects[fid].comments.length;
  2334. if(nComments === 0) return false;
  2335.  
  2336. for(var cidx=0; cidx<nComments; cidx++)
  2337. {
  2338. if(W.model.updateRequestSessions.objects[fid].comments[cidx].userID == uroUserID) return true;
  2339. }
  2340.  
  2341. return false;
  2342. }
  2343.  
  2344.  
  2345. function uroACMObj(urID, customType, hasMyComments, nComments)
  2346. {
  2347. this.urID = urID;
  2348. this.customType = customType;
  2349. this.hasMyComments = hasMyComments;
  2350. this.nComments = nComments;
  2351. }
  2352.  
  2353. function uroAddCustomMarkers(urID, customType, hasMyComments, nComments)
  2354. {
  2355. var useCustomMarker = false;
  2356.  
  2357. if(uroGetCBChecked('_cbMasterEnable') === true)
  2358. {
  2359. if(customType === 0) useCustomMarker = (uroGetCBChecked('_cbCustomRoadworksMarkers'));
  2360. else if(customType === 1) useCustomMarker = (uroGetCBChecked('_cbCustomConstructionMarkers'));
  2361. else if(customType === 2) useCustomMarker = (uroGetCBChecked('_cbCustomClosuresMarkers'));
  2362. else if(customType === 3) useCustomMarker = (uroGetCBChecked('_cbCustomEventsMarkers'));
  2363. else if(customType === 4) useCustomMarker = (uroGetCBChecked('_cbCustomNotesMarkers'));
  2364. else if(customType === 100) useCustomMarker = (uroGetCBChecked('_cbCustomElginMarkers'));
  2365. else if(customType === 101) useCustomMarker = (uroGetCBChecked('_cbCustomTrafficCastMarkers'));
  2366. else if(customType === 102) useCustomMarker = (uroGetCBChecked('_cbCustomTrafficMasterMarkers'));
  2367. }
  2368. if(!useCustomMarker) customType = -1;
  2369. uroCustomMarkerList.push(new uroACMObj(urID, customType, hasMyComments, nComments));
  2370. }
  2371.  
  2372. function uroRenderCustomMarkers(markerType)
  2373. {
  2374. var urID;
  2375. var elmID;
  2376. var newSpan;
  2377. var divElem;
  2378. var objIdx;
  2379. var customType;
  2380. var customMarker;
  2381.  
  2382. if(markerType == 'ur')
  2383. {
  2384. var useDefaultConvoMarker = false;
  2385. var addCommentCount = false;
  2386.  
  2387. if(uroGetCBChecked('_cbMasterEnable') === true)
  2388. {
  2389. if((uroGetCBChecked('_cbNativeConvoMarkers')) && (uroBetaEditor === false)) useDefaultConvoMarker = true;
  2390. if((uroGetCBChecked('_cbNativeBetaConvoMarkers')) && (uroBetaEditor === true)) useDefaultConvoMarker = true;
  2391. if(uroGetCBChecked('_cbCommentCount')) addCommentCount = true;
  2392. }
  2393. else
  2394. {
  2395. useDefaultConvoMarker = true;
  2396. }
  2397.  
  2398. var uRCM_masterEnable = uroGetCBChecked('_cbMasterEnable');
  2399. divElem = document.getElementById(W.map.updateRequestLayer.id);
  2400. if(divElem.childNodes.length > 0)
  2401. {
  2402. for(objIdx = 0; objIdx < uroCustomMarkerList.length; objIdx++)
  2403. {
  2404. customType = -1;
  2405. var cmlObj = uroCustomMarkerList[objIdx];
  2406. if(uRCM_masterEnable === true)
  2407. {
  2408. customType = cmlObj.customType;
  2409. }
  2410. if(customType < 100)
  2411. {
  2412. urID = cmlObj.urID;
  2413. var nComments = cmlObj.nComments;
  2414. var iconObj = W.map.updateRequestLayer.markers[urID].icon;
  2415. newSpan = '';
  2416. if(nComments !== 0)
  2417. {
  2418. var classList = iconObj.imageDiv.classList;
  2419. elmID = "commentCount_"+urID;
  2420.  
  2421. if(addCommentCount)
  2422. {
  2423. // add a new comment count bubble if the UR doesn't already have one
  2424. if(document.getElementById(elmID) === null)
  2425. {
  2426. newSpan += '<span id="'+elmID+'" style="position:absolute;top:-9px;left:-11px;pointer-events:none;z-index:1">';
  2427. // define the comment-count holding span within the span used to hold the empty bubble image, and before the image is
  2428. // added to the HTML, to avoid z-indexing issues when adjacent comment count bubbles are overlapped...
  2429. newSpan += '<span id="'+elmID+"_inner"+'" style="position:absolute;top:4px;left:11px;font-size:11px;;pointer-events:none"></span>';
  2430. newSpan += '<img src="'+uroMarkers[0]+'">';
  2431. newSpan += '</span>';
  2432. }
  2433. }
  2434. else
  2435. {
  2436. // remove comment count bubble from this UR marker if one has previously been
  2437. // added and the user has now disabled the option...
  2438. if(document.getElementById(elmID) !== null)
  2439. {
  2440. document.getElementById(elmID).remove();
  2441. }
  2442. if(document.getElementById(elmID+"_inner") !== null)
  2443. {
  2444. document.getElementById(elmID+"_inner").remove();
  2445. }
  2446. }
  2447.  
  2448. elmID = "convoMarker_"+urID;
  2449. if(useDefaultConvoMarker === false)
  2450. {
  2451. if(document.getElementById(elmID) === null)
  2452. {
  2453. var hasMyComments = cmlObj.hasMyComments;
  2454. // 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
  2455. // conversation marker, the custom marker remains on top...
  2456. newSpan += '<span id="'+elmID+'" style="position:absolute;top:-9px;left:18px;pointer-events:none;z-index:1">';
  2457. if(hasMyComments) newSpan += '<img src="'+uroMarkers[2]+'">';
  2458. else newSpan += '<img src="'+uroMarkers[1]+'">';
  2459. newSpan += '</span>';
  2460. classList.remove("has-comments");
  2461. }
  2462. }
  2463. else
  2464. {
  2465. // remove custom conversation marker from this UR if one has previously been
  2466. // added and the user has now disabled this option
  2467. if(document.getElementById(elmID) !== null)
  2468. {
  2469. document.getElementById(elmID).remove();
  2470. }
  2471. if(nComments > 0)
  2472. {
  2473. // only replace the native marker class if the UR has comments - if we're just clearing the custom
  2474. // marker following a master enable switchoff, we don't then want to add native markers to URs which
  2475. // didn't have them in the first place...
  2476. classList.add("has-comments");
  2477. }
  2478. }
  2479. }
  2480.  
  2481. elmID = "customMarker_"+urID;
  2482. if(customType != -1)
  2483. {
  2484. if(document.getElementById(elmID) === null)
  2485. {
  2486. newSpan += '<span id="'+elmID+'" style="position:absolute;pointer-events:none;"></span>';
  2487. }
  2488. customType = uroGetCustomMarkerIdx(customType);
  2489. if(W.model.updateRequestSessions.objects[urID] !== undefined)
  2490. {
  2491. if(W.model.updateRequestSessions.objects[urID].open === false) customType += 1;
  2492. }
  2493. customMarker = '<img src="'+uroIcons[customType][0]+'">';
  2494. document.getElementById(elmID).innerHTML = customMarker;
  2495. }
  2496. else
  2497. {
  2498. if(document.getElementById(elmID) !== null)
  2499. {
  2500. document.getElementById(elmID).remove();
  2501. }
  2502. }
  2503. if(newSpan !== '')
  2504. {
  2505. iconObj.$div.prepend(newSpan);
  2506. if(addCommentCount)
  2507. {
  2508. var styleLeft;
  2509. if(nComments < 10) styleLeft = '11px';
  2510. else if(nComments < 100) styleLeft = '8px';
  2511. else styleLeft = '5px';
  2512. elmID = "commentCount_"+urID;
  2513. document.getElementById(elmID+"_inner").innerHTML = nComments;
  2514. document.getElementById(elmID+"_inner").style.left = styleLeft;
  2515. }
  2516. }
  2517. }
  2518. }
  2519. }
  2520. }
  2521.  
  2522. else if(markerType == 'mp')
  2523. {
  2524. divElem = document.getElementById(W.map.problemLayer.id);
  2525. if(divElem.childNodes.length > 0)
  2526. {
  2527. for(objIdx = 0; objIdx < uroCustomMarkerList.length; objIdx++)
  2528. {
  2529. customType = uroCustomMarkerList[objIdx].customType;
  2530. if((customType >= 100) || (customType == -1))
  2531. {
  2532. urID = uroCustomMarkerList[objIdx].urID;
  2533. elmID = "customMarker_"+urID;
  2534. if(customType != -1)
  2535. {
  2536. if(document.getElementById(elmID) === null)
  2537. {
  2538. newSpan = '<span id="'+elmID+'" style="position:absolute;pointer-events:none;"></span>';
  2539. if(W.map.problemLayer.markers[urID] !== undefined)
  2540. {
  2541. W.map.problemLayer.markers[urID].icon.$div.prepend(newSpan);
  2542. }
  2543. }
  2544. if(document.getElementById(elmID) !== null)
  2545. {
  2546. customType = uroGetCustomMarkerIdx(customType);
  2547. if(W.model.problems.objects[urID] !== undefined)
  2548. {
  2549. if(W.model.problems.objects[urID].attributes.open === false) customType += 1;
  2550. }
  2551. customMarker = '<img src="'+uroIcons[customType][0]+'">';
  2552. document.getElementById(elmID).innerHTML = customMarker;
  2553. }
  2554. }
  2555. else
  2556. {
  2557. if(document.getElementById(elmID) !== null)
  2558. {
  2559. document.getElementById(elmID).remove();
  2560. }
  2561. }
  2562. }
  2563. }
  2564. }
  2565. }
  2566.  
  2567. }
  2568.  
  2569.  
  2570. function uroChangeCustomMarkers(urID,isHighlighted,customType,markerType)
  2571. {
  2572. if(document.getElementById('customMarker_'+urID) !== null)
  2573. {
  2574. if(markerType == "ur")
  2575. {
  2576. if(W.model.updateRequestSessions.objects[urID].open === false) customType += 1;
  2577. }
  2578. else if(markerType == "mp")
  2579. {
  2580. if(W.model.problems.objects[urID].attributes.open === false) customType += 1;
  2581. }
  2582.  
  2583. if(isHighlighted === true)
  2584. {
  2585. document.getElementById('customMarker_'+urID).innerHTML = '<img src="'+uroIcons[customType][1]+'">';
  2586. }
  2587. else
  2588. {
  2589. document.getElementById('customMarker_'+urID).innerHTML = '<img src="'+uroIcons[customType][0]+'">';
  2590. }
  2591. }
  2592. }
  2593.  
  2594. function uroFilterPlaces()
  2595. {
  2596. if(uroFilterPreamble() === false) return;
  2597.  
  2598. if(uroPlaceSelected === true) return;
  2599.  
  2600. if(uroGetCBChecked('_cbDisablePlacesFiltering') === true) return;
  2601.  
  2602. var filterCats = [];
  2603. for(var i=0; i<W.Config.venues.categories.length; i++)
  2604. {
  2605. var parentCategory = W.Config.venues.categories[i];
  2606. var subCategory;
  2607.  
  2608. if(uroGetCBChecked('_cbPlacesFilter-'+parentCategory) === true)
  2609. {
  2610. filterCats.push(parentCategory);
  2611. for(var i1=0; i1<W.Config.venues.subcategories[parentCategory].length; i1++)
  2612. {
  2613. subCategory = W.Config.venues.subcategories[parentCategory][i1];
  2614. filterCats.push(subCategory);
  2615. }
  2616. }
  2617. else
  2618. {
  2619. for(var i2=0; i2<W.Config.venues.subcategories[parentCategory].length; i2++)
  2620. {
  2621. subCategory = W.Config.venues.subcategories[parentCategory][i2];
  2622. if(uroGetCBChecked('_cbPlacesFilter-'+subCategory) === true)
  2623. {
  2624. filterCats.push(subCategory);
  2625. }
  2626. }
  2627. }
  2628. }
  2629.  
  2630. var placeStyle;
  2631.  
  2632. var uFP_filterEditedLessThan = uroGetCBChecked('_cbPlaceFilterEditedLessThan');
  2633. var uFP_filterEditedMoreThan = uroGetCBChecked('_cbPlaceFilterEditedMoreThan');
  2634. var uFP_filterL0 = uroGetCBChecked('_cbHidePlacesL0');
  2635. var uFP_filterL1 = uroGetCBChecked('_cbHidePlacesL1');
  2636. var uFP_filterL2 = uroGetCBChecked('_cbHidePlacesL2');
  2637. var uFP_filterL3 = uroGetCBChecked('_cbHidePlacesL3');
  2638. var uFP_filterL4 = uroGetCBChecked('_cbHidePlacesL4');
  2639. var uFP_filterL5 = uroGetCBChecked('_cbHidePlacesL5');
  2640. var uFP_filterOnLockLevel = (uFP_filterL0 || uFP_filterL1 || uFP_filterL2 || uFP_filterL3 || uFP_filterL4 || uFP_filterL5);
  2641. var uFP_filterNoPhotos = uroGetCBChecked('_cbHideNoPhotoPlaces');
  2642. var uFP_filterWithPhotos = uroGetCBChecked('_cbHidePhotoPlaces');
  2643. var uFP_filterPrivate = uroGetCBChecked('_cbFilterPrivatePlaces');
  2644. var uFP_invertFilters = uroGetCBChecked('_cbInvertPlacesFilter');
  2645. var uFP_masterEnable = uroGetCBChecked('_cbMasterEnable');
  2646. var uFP_thresholdMinDays = document.getElementById('_inputFilterPlaceEditMinDays').value;
  2647. var uFP_thresholdMaxDays = document.getElementById('_inputFilterPlaceEditMaxDays').value;
  2648. for(var v=0; v<W.map.landmarkLayer.features.length; v++)
  2649. {
  2650. placeStyle = 'visible';
  2651. if(uFP_masterEnable === true)
  2652. {
  2653. var lmObj = W.map.landmarkLayer.features[v];
  2654.  
  2655. // when an area place is selected, the drag points for editing the place outline now get added as objects into W.map.landmarkLayer.features,
  2656. // however none of these objects have the .model property - we must therefore check each entry in features[] to see if it has .model before
  2657. // attempting to filter it...
  2658. if(lmObj.model !== undefined)
  2659. {
  2660. if(lmObj.model.attributes.id < 0)
  2661. {
  2662. // don't apply filtering to newly-created places - this allows the user to leave their filtering settings unchanged whilst
  2663. // adding a new place which, once saved, would then be hidden...
  2664. break;
  2665. }
  2666.  
  2667. if((uFP_filterEditedLessThan) || (uFP_filterEditedMoreThan))
  2668. {
  2669. var editDate = lmObj.model.attributes.updatedOn;
  2670. if(editDate === undefined)
  2671. {
  2672. // where a place has never been edited since its creation, use the creation date instead...
  2673. editDate = lmObj.model.attributes.createdOn;
  2674. }
  2675. if(editDate !== undefined)
  2676. {
  2677. var editDaysAgo = uroDateToDays(editDate);
  2678. if(uFP_filterEditedLessThan)
  2679. {
  2680. if(editDaysAgo < uFP_thresholdMinDays)
  2681. {
  2682. placeStyle = 'hidden';
  2683. }
  2684. }
  2685. if(uFP_filterEditedMoreThan)
  2686. {
  2687. if(editDaysAgo > uFP_thresholdMaxDays)
  2688. {
  2689. placeStyle = 'hidden';
  2690. }
  2691. }
  2692. }
  2693. }
  2694.  
  2695. if(placeStyle == 'visible')
  2696. {
  2697. if(uFP_filterOnLockLevel)
  2698. {
  2699. var lockLevel = lmObj.model.attributes.lockRank;
  2700. if ((uFP_filterL0) && (lockLevel === 0)) placeStyle = 'hidden';
  2701. if ((uFP_filterL1) && (lockLevel === 1)) placeStyle = 'hidden';
  2702. if ((uFP_filterL2) && (lockLevel === 2)) placeStyle = 'hidden';
  2703. if ((uFP_filterL3) && (lockLevel === 3)) placeStyle = 'hidden';
  2704. if ((uFP_filterL4) && (lockLevel === 4)) placeStyle = 'hidden';
  2705. if ((uFP_filterL5) && (lockLevel === 5)) placeStyle = 'hidden';
  2706. }
  2707. }
  2708.  
  2709. if(placeStyle == 'visible')
  2710. {
  2711. if(uFP_filterNoPhotos || uFP_filterWithPhotos)
  2712. {
  2713. var nPhotos = 0;
  2714. for(var loop=0; loop<lmObj.model.attributes.images.length; loop++)
  2715. {
  2716. if(lmObj.model.attributes.images[loop].attributes.approved) nPhotos++;
  2717. }
  2718. if((uFP_filterNoPhotos) && (nPhotos === 0)) placeStyle = 'hidden';
  2719. if((uFP_filterWithPhotos) && (nPhotos !== 0)) placeStyle = 'hidden';
  2720. }
  2721. }
  2722.  
  2723.  
  2724. if(placeStyle == 'visible')
  2725. {
  2726. if((uFP_filterPrivate === true) && (lmObj.model.attributes.residential === true))
  2727. {
  2728. placeStyle = 'hidden';
  2729. }
  2730. else
  2731. {
  2732. for(var cat=0; cat<filterCats.length; cat++)
  2733. {
  2734. if(lmObj.model.attributes.categories.contains(filterCats[cat]))
  2735. {
  2736. placeStyle = 'hidden';
  2737. break;
  2738. }
  2739. }
  2740. }
  2741. }
  2742. }
  2743.  
  2744. if(uFP_invertFilters === true)
  2745. {
  2746. if(placeStyle == 'hidden') placeStyle = 'visible';
  2747. else placeStyle = 'hidden';
  2748. }
  2749. }
  2750.  
  2751. var geoID = W.map.landmarkLayer.features[v].geometry.id;
  2752. if(document.getElementById(geoID) !== null)
  2753. {
  2754. document.getElementById(geoID).style.visibility = placeStyle;
  2755. }
  2756. }
  2757. var uFP_filterUneditable = uroGetCBChecked('_cbFilterUneditablePlaceUpdates');
  2758. var uFP_filterLockRanked = uroGetCBChecked('_cbFilterLockRankedPlaceUpdates');
  2759. var uFP_filterFlagged = uroGetCBChecked("_cbFilterFlaggedPUR");
  2760. var uFP_filterNewPlace = uroGetCBChecked("_cbFilterNewPlacePUR");
  2761. var uFP_filterUpdatedDetails = uroGetCBChecked("_cbFilterUpdatedDetailsPUR");
  2762. var uFP_filterNewPhoto = uroGetCBChecked("_cbFilterNewPhotoPUR");
  2763. var uFP_filterMinPURAge = uroGetCBChecked('_cbEnablePURMinAgeFilter');
  2764. var uFP_filterMaxPURAge = uroGetCBChecked('_cbEnablePURMaxAgeFilter');
  2765. var uFP_invertPURFilters = uroGetCBChecked('_cbInvertPURFilters');
  2766. var uFP_filterHighSeverity = uroGetCBChecked('_cbPURFilterHighSeverity');
  2767. var uFP_filterMedSeverity = uroGetCBChecked('_cbPURFilterMediumSeverity');
  2768. var uFP_filterLowSeverity = uroGetCBChecked('_cbPURFilterLowSeverity');
  2769. var uFP_leavePURGeos = uroGetCBChecked('_cbLeavePURGeos');
  2770. var uFP_thresholdMinPURDays = uroGetElmValue('_inputPURFilterMinDays');
  2771. var uFP_thresholdMaxPURDays = uroGetElmValue('_inputPURFilterMaxDays');
  2772. var uFP_isLoggedIn = W.model.loginManager.isLoggedIn();
  2773. var uFP_userRank = W.model.loginManager.user.rank;
  2774. var purAge = null;
  2775. for(var pu in W.map.placeUpdatesLayer.markers)
  2776. {
  2777. if(W.map.placeUpdatesLayer.markers.hasOwnProperty(pu))
  2778. {
  2779. var puObj = W.map.placeUpdatesLayer.markers[pu];
  2780. if(W.map.placeUpdatesLayer.getVisibility() === true)
  2781. {
  2782. placeStyle = 'visible';
  2783. if(uFP_filterUneditable === true)
  2784. {
  2785. if(puObj.model.attributes.permissions === 0)
  2786. {
  2787. placeStyle = 'hidden';
  2788. }
  2789. if((placeStyle == 'visible') && (uFP_isLoggedIn))
  2790. {
  2791. if(uFP_userRank < puObj.model.attributes.lockRank)
  2792. {
  2793. placeStyle = 'hidden';
  2794. }
  2795. }
  2796. if((placeStyle == 'visible') && (puObj.model.attributes.adLocked))
  2797. {
  2798. placeStyle = 'hidden';
  2799. }
  2800. }
  2801.  
  2802. if((placeStyle == 'visible') && (uFP_filterLockRanked === true))
  2803. {
  2804. if(puObj.model.attributes.lockRank !== 0)
  2805. {
  2806. placeStyle = 'hidden';
  2807. }
  2808. }
  2809.  
  2810. if((placeStyle == 'visible') && (uFP_filterFlagged === true))
  2811. {
  2812. if(puObj.icon.imageDiv.className.indexOf('flag') != -1)
  2813. {
  2814. placeStyle = 'hidden';
  2815. }
  2816. }
  2817. if((placeStyle == 'visible') && (uFP_filterNewPlace === true))
  2818. {
  2819. if(puObj.icon.imageDiv.className.indexOf('add_venue') != -1)
  2820. {
  2821. placeStyle = 'hidden';
  2822. }
  2823. }
  2824. if((placeStyle == 'visible') && (uFP_filterUpdatedDetails === true))
  2825. {
  2826. if((puObj.icon.imageDiv.className.indexOf('update_venue') != -1) || (puObj.icon.imageDiv.className.indexOf('multiple') != -1))
  2827. {
  2828. placeStyle = 'hidden';
  2829. }
  2830. }
  2831. if((placeStyle == 'visible') && (uFP_filterNewPhoto === true))
  2832. {
  2833. if(puObj.icon.imageDiv.className.indexOf('add_image') != -1)
  2834. {
  2835. placeStyle = 'hidden';
  2836. }
  2837. }
  2838.  
  2839. if(uFP_invertPURFilters === true)
  2840. {
  2841. if(placeStyle == 'hidden') placeStyle = 'visible';
  2842. else placeStyle = 'hidden';
  2843. }
  2844.  
  2845. if(uFP_filterMinPURAge || uFP_filterMaxPURAge)
  2846. {
  2847. purAge = uroGetPURAge(puObj.model);
  2848. if(uFP_filterMinPURAge === true)
  2849. {
  2850. if(purAge < uFP_thresholdMinPURDays) placeStyle = 'hidden';
  2851. }
  2852. if(uFP_filterMaxPURAge === true)
  2853. {
  2854. if(purAge > uFP_thresholdMaxPURDays) placeStyle = 'hidden';
  2855. }
  2856. }
  2857.  
  2858. if(placeStyle == 'visible')
  2859. {
  2860. var purSeverity = puObj._getSeverity();
  2861. if((uFP_filterHighSeverity) && (purSeverity == "high")) placeStyle = 'hidden';
  2862. if((placeStyle == 'visible') && (uFP_filterMedSeverity) && (purSeverity == "medium")) placeStyle = 'hidden';
  2863. if((placeStyle == 'visible') && (uFP_filterLowSeverity) && (purSeverity == "low")) placeStyle = 'hidden';
  2864. }
  2865.  
  2866. puObj.icon.imageDiv.style.visibility = placeStyle;
  2867.  
  2868. if(uFP_leavePURGeos === false)
  2869. {
  2870. if(puObj.model !== undefined)
  2871. {
  2872. if(puObj.model.geometry !== undefined)
  2873. {
  2874. var puGeo = document.getElementById(puObj.model.geometry.id);
  2875. if(puGeo !== null)
  2876. {
  2877. puGeo.style.visibility = placeStyle;
  2878. }
  2879. }
  2880. }
  2881. }
  2882. }
  2883. }
  2884. }
  2885. }
  2886.  
  2887. function uroFilterCameras()
  2888. {
  2889. if(uroFilterPreamble() === false) return;
  2890. var camLayer = document.getElementById(uroRootContainer+'_svgRoot');
  2891. if(camLayer === null)
  2892. {
  2893. if(uroNullCamLayer === false)
  2894. {
  2895. uroAddLog('caught null camLayer');
  2896. uroNullCamLayer = true;
  2897. }
  2898. return;
  2899. }
  2900. uroNullCamLayer = false;
  2901. if(uroMouseIsDown === false) W.map.camerasLayer.redraw();
  2902. if(uroGetCBChecked('_cbMasterEnable') === true)
  2903. {
  2904. for (var uroCamObj in W.model.cameras.objects)
  2905. {
  2906. if(W.model.cameras.objects.hasOwnProperty(uroCamObj))
  2907. {
  2908. var uroCamUpdater = '';
  2909. var uroCamUpdaterRank = -1;
  2910. var uroCamCreator = '';
  2911. var uroCamCreatorRank = -1;
  2912. var uroCam = W.model.cameras.objects[uroCamObj];
  2913. var uroCamStyle = 'visible';
  2914. if(uroCam.attributes.createdBy !== null)
  2915. {
  2916. if(W.model.users.objects[uroCam.attributes.createdBy] !== undefined)
  2917. {
  2918. uroCamCreator = W.model.users.objects[uroCam.attributes.createdBy].userName;
  2919. uroCamCreatorRank = W.model.users.objects[uroCam.attributes.createdBy].rank;
  2920. }
  2921. }
  2922.  
  2923. if(uroCam.attributes.updatedBy !== null)
  2924. {
  2925. if(W.model.users.objects[uroCam.attributes.updatedBy] !== undefined)
  2926. {
  2927. uroCamUpdater = W.model.users.objects[uroCam.attributes.updatedBy].userName;
  2928. uroCamUpdaterRank = W.model.users.objects[uroCam.attributes.updatedBy].rank;
  2929. }
  2930. }
  2931.  
  2932. var uroCamApproved = uroCam.attributes.validated;
  2933. var uroCamType = uroCam.attributes.type;
  2934.  
  2935. if(uroGetCBChecked('_cbShowOnlyMyCams') === true)
  2936. {
  2937. if((uroUserID != uroCam.attributes.createdBy)&&(uroUserID != uroCam.attributes.updatedBy)) uroCamStyle = 'hidden';
  2938. }
  2939.  
  2940. if((uroGetCBChecked('_cbShowWorldCams') === false) || (uroGetCBChecked('_cbShowUSACams') === false) || (uroGetCBChecked('_cbShowNonWorldCams') === false))
  2941. {
  2942. var posWorld = uroCamCreator.indexOf('world_');
  2943. var posUSA = uroCamCreator.indexOf('usa_');
  2944.  
  2945. if((uroGetCBChecked('_cbShowWorldCams') === false) && (posWorld === 0)) uroCamStyle = 'hidden';
  2946. if((uroGetCBChecked('_cbShowUSACams') === false) && (posUSA === 0)) uroCamStyle = 'hidden';
  2947. if((uroGetCBChecked('_cbShowNonWorldCams') === false) && (posWorld !== 0) && (posUSA !== 0)) uroCamStyle = 'hidden';
  2948. }
  2949.  
  2950. if((uroGetCBChecked('_cbShowApprovedCams') === false) || (uroGetCBChecked('_cbShowNonApprovedCams') === false))
  2951. {
  2952. if((uroGetCBChecked('_cbShowApprovedCams') === false) && (uroCamApproved === true)) uroCamStyle = 'hidden';
  2953. if((uroGetCBChecked('_cbShowNonApprovedCams') === false) && (uroCamApproved === false)) uroCamStyle = 'hidden';
  2954. }
  2955.  
  2956. if((uroGetCBChecked('_cbShowNonApprovedCams') === true) && (uroCamApproved === false))
  2957. {
  2958. if(((uroGetCBChecked('_cbShowOlderCreatedNonApproved') === true)) && (uroGetCameraAge(uroCam,1) <= uroGetElmValue('_inputCameraMinCreatedDays'))) uroCamStyle = 'hidden';
  2959. if(((uroGetCBChecked('_cbShowOlderUpdatedNonApproved') === true)) && (uroGetCameraAge(uroCam,0) <= uroGetElmValue('_inputCameraMinUpdatedDays'))) uroCamStyle = 'hidden';
  2960. }
  2961.  
  2962. if((uroGetCBChecked('_cbShowSpeedCams') === false) || (uroGetCBChecked('_cbShowRedLightCams') === false) || (uroGetCBChecked('_cbShowDummyCams') === false))
  2963. {
  2964. if((uroGetCBChecked('_cbShowSpeedCams') === false) && (uroCamType == 2)) uroCamStyle = 'hidden';
  2965. if((uroGetCBChecked('_cbShowRedLightCams') === false) && (uroCamType == 4)) uroCamStyle = 'hidden';
  2966. if((uroGetCBChecked('_cbShowDummyCams') === false) && (uroCamType == 3)) uroCamStyle = 'hidden';
  2967. }
  2968.  
  2969. if(uroGetCBChecked('_cbShowSpeedCams') === true)
  2970. {
  2971. if((uroGetCBChecked('_cbShowIfNoSpeedSet') === false) && (uroCam.attributes.speed === null)) uroCamStyle = 'hidden';
  2972. if((uroGetCBChecked('_cbShowIfSpeedSet') === false) && (uroCam.attributes.speed !== null)) uroCamStyle = 'hidden';
  2973. }
  2974.  
  2975. if(uroGetCBChecked('_cbHideCreatedByMe') === true)
  2976. {
  2977. if(uroUserID == uroCam.attributes.createdBy) uroCamStyle = 'hidden';
  2978. }
  2979. if((uroGetCBChecked('_cbHideCreatedByRank0') === true) && (uroCamCreatorRank === 0)) uroCamStyle = 'hidden';
  2980. if((uroGetCBChecked('_cbHideCreatedByRank1') === true) && (uroCamCreatorRank == 1)) uroCamStyle = 'hidden';
  2981. if((uroGetCBChecked('_cbHideCreatedByRank2') === true) && (uroCamCreatorRank == 2)) uroCamStyle = 'hidden';
  2982. if((uroGetCBChecked('_cbHideCreatedByRank3') === true) && (uroCamCreatorRank == 3)) uroCamStyle = 'hidden';
  2983. if((uroGetCBChecked('_cbHideCreatedByRank4') === true) && (uroCamCreatorRank == 4)) uroCamStyle = 'hidden';
  2984. if((uroGetCBChecked('_cbHideCreatedByRank5') === true) && (uroCamCreatorRank == 5)) uroCamStyle = 'hidden';
  2985.  
  2986. if(uroGetCBChecked('_cbHideUpdatedByMe') === true)
  2987. {
  2988. if(uroUserID == uroCam.attributes.updatedBy) uroCamStyle = 'hidden';
  2989. }
  2990. if((uroGetCBChecked('_cbHideUpdatedByRank0') === true) && (uroCamUpdaterRank === 0)) uroCamStyle = 'hidden';
  2991. if((uroGetCBChecked('_cbHideUpdatedByRank1') === true) && (uroCamUpdaterRank == 1)) uroCamStyle = 'hidden';
  2992. if((uroGetCBChecked('_cbHideUpdatedByRank2') === true) && (uroCamUpdaterRank == 2)) uroCamStyle = 'hidden';
  2993. if((uroGetCBChecked('_cbHideUpdatedByRank3') === true) && (uroCamUpdaterRank == 3)) uroCamStyle = 'hidden';
  2994. if((uroGetCBChecked('_cbHideUpdatedByRank4') === true) && (uroCamUpdaterRank == 4)) uroCamStyle = 'hidden';
  2995. if((uroGetCBChecked('_cbHideUpdatedByRank5') === true) && (uroCamUpdaterRank == 5)) uroCamStyle = 'hidden';
  2996.  
  2997. if((uroGetCBChecked('_cbHideCWLCams') === true) && (uroIsCamOnWatchList(uroCam.attributes.id) != -1)) uroCamStyle = 'hidden';
  2998.  
  2999. var uroCamGeometryID = uroCam.geometry.id;
  3000. if(camLayer.getElementById(uroCamGeometryID) !== null)
  3001. {
  3002. if(uroCamStyle == "hidden")
  3003. {
  3004. camLayer.getElementById(uroCamGeometryID).remove();
  3005. }
  3006. }
  3007. }
  3008. }
  3009. }
  3010. }
  3011.  
  3012. function uroFilterURs_onObjectsChanged()
  3013. {
  3014. if(uroBackfilling === false)
  3015. {
  3016. uroURBackfill();
  3017. uroFilterURs();
  3018. }
  3019. }
  3020. function uroFilterURs_onObjectsAdded()
  3021. {
  3022. if(uroBackfilling === false)
  3023. {
  3024. uroURBackfill();
  3025. uroFilterURs();
  3026. }
  3027. }
  3028. function uroFilterURs_onObjectsRemoved()
  3029. {
  3030. if(uroBackfilling === false)
  3031. {
  3032. uroURBackfill();
  3033. uroFilterURs();
  3034. }
  3035. }
  3036.  
  3037.  
  3038. function uroURBackfill_GetData(lon, lat, blockSize)
  3039. {
  3040. lon = parseFloat(lon);
  3041. lat = parseFloat(lat);
  3042. blockSize = parseFloat(blockSize);
  3043. uroAddLog('Backfill square '+lon+','+lat);
  3044. var xmlReq = new XMLHttpRequest();
  3045.  
  3046. var tURL = 'https://' + document.location.host;
  3047. tURL += Waze.Config.api_base;
  3048. tURL += '/Features?language=en&mapUpdateRequestFilter=0';
  3049. if(uroPracticeMode === true) tURL += '&sandbox=true';
  3050. tURL += '&bbox='+(lon)+','+(lat)+','+(lon + blockSize)+','+(lat + blockSize);
  3051. xmlReq.open('GET',tURL,false);
  3052. try
  3053. {
  3054. xmlReq.send();
  3055. uroAddLog('response '+xmlReq.status+' received');
  3056. if (xmlReq.status === 200)
  3057. {
  3058. var tResp = JSON.parse(xmlReq.responseText);
  3059. var urCount = tResp.mapUpdateRequests.objects.length;
  3060.  
  3061. uroAddLog(urCount+' URs loaded for backfill processing');
  3062. if(urCount == 500)
  3063. {
  3064. uroAddLog('WARNING - backfill data may have been pre-filtered by server');
  3065. }
  3066.  
  3067. var backfilled = 0;
  3068. for(var i=0; i<urCount; i++)
  3069. {
  3070. var urID = tResp.mapUpdateRequests.objects[i].id;
  3071. if(W.model.mapUpdateRequests.objects[urID] === undefined)
  3072. {
  3073. var newUR = require('Waze/Feature/Vector/UpdateRequest');
  3074. var tUR = new newUR(tResp.mapUpdateRequests.objects[i]);
  3075. var tPoint = new OpenLayers.Geometry.Point();
  3076. tPoint.x = tResp.mapUpdateRequests.objects[i].geometry.coordinates[0];
  3077. tPoint.y = tResp.mapUpdateRequests.objects[i].geometry.coordinates[1];
  3078. tPoint.transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913"));
  3079. tUR.geometry = tPoint;
  3080. W.model.mapUpdateRequests.put(tUR);
  3081. backfilled++;
  3082. }
  3083. }
  3084.  
  3085. uroAddLog(backfilled+' URs backfilled');
  3086. }
  3087. else
  3088. {
  3089. uroAddLog('request failed (status != 200)');
  3090. }
  3091. }
  3092. catch(err)
  3093. {
  3094. uroAddLog('UR backfill request failed (exception '+err+' caught)');
  3095. }
  3096. }
  3097.  
  3098. function uroURBackfill()
  3099. {
  3100. if((uroGetCBChecked('_cbURBackfill') === false) || (uroGetCBChecked('_cbMasterEnable') === false))
  3101. {
  3102. return;
  3103. }
  3104.  
  3105. var nativeURCount = Object.keys(W.model.mapUpdateRequests.objects).length;
  3106. if(nativeURCount < 500)
  3107. {
  3108. return;
  3109. }
  3110.  
  3111. uroAddLog('exactly 500 URs loaded, possible server-side filtering requiring backfill...');
  3112.  
  3113. var subSize = 0.1;
  3114. var vpWidth = W.map.getExtent().getWidth();
  3115. var vpHeight = W.map.getExtent().getHeight();
  3116. var vpCentre = W.map.getCenter();
  3117. var vpLL = new OpenLayers.LonLat();
  3118. var vpUR = new OpenLayers.LonLat();
  3119. vpLL.lon = vpCentre.lon - (vpWidth / 2);
  3120. vpLL.lat = vpCentre.lat - (vpHeight / 2);
  3121. vpUR.lon = vpCentre.lon + (vpWidth / 2);
  3122. vpUR.lat = vpCentre.lat + (vpHeight / 2);
  3123. vpLL = vpLL.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326"));
  3124. vpUR = vpUR.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326"));
  3125. vpLL.lon -= (subSize / 2);
  3126. vpLL.lat -= (subSize / 2);
  3127. vpUR.lon += (subSize / 2);
  3128. vpUR.lat += (subSize / 2);
  3129. vpLL.lon = +vpLL.lon.toFixed(1);
  3130. vpLL.lat = +vpLL.lat.toFixed(1);
  3131. vpUR.lon = +vpUR.lon.toFixed(1);
  3132. vpUR.lat = +vpUR.lat.toFixed(1);
  3133.  
  3134. uroBackfilling = true;
  3135. for(var bfLat = vpLL.lat; bfLat <= vpUR.lat; bfLat += subSize)
  3136. {
  3137. for(var bfLon = vpLL.lon; bfLon <= vpUR.lon; bfLon += subSize)
  3138. {
  3139. uroURBackfill_GetData(bfLon, bfLat, subSize);
  3140. }
  3141. }
  3142. uroBackfilling = false;
  3143. uroFilterURs();
  3144. }
  3145.  
  3146.  
  3147. function uroFilterURs()
  3148. {
  3149. // compatibility fix for URComments - based on code supplied by RickZabel
  3150. var hasActiveURFilters = false;
  3151. if(uroGetCBChecked('_cbMasterEnable') === true)
  3152. {
  3153. var urTabInputs = document.getElementById('uroCtrlURs').getElementsByTagName('input');
  3154. for(var loop = 0; loop < urTabInputs.length; loop++)
  3155. {
  3156. if(urTabInputs[loop].type == 'checkbox')
  3157. {
  3158. var ignoreCB = false;
  3159. ignoreCB |= (urTabInputs[loop].id == '_cbCaseInsensitive');
  3160. ignoreCB |= (urTabInputs[loop].id == '_cbNoFilterForTaggedURs');
  3161. if((urTabInputs[loop].checked) && (ignoreCB === false))
  3162. {
  3163. hasActiveURFilters = true;
  3164. break;
  3165. }
  3166. }
  3167. }
  3168. }
  3169. sessionStorage.UROverview_hasActiveURFilters = hasActiveURFilters;
  3170. if(uroFilterPreamble() === false) return;
  3171. uroRefreshUpdateRequestSessions();
  3172. var selectorResolver = document.getElementById('_selectURResolverID');
  3173. var selectorCommentUser = document.getElementById('_selectURUserID');
  3174.  
  3175. if(uroGetCBChecked('_cbURResolverIDFilter') === false)
  3176. {
  3177. while(selectorResolver.options.length > 0)
  3178. {
  3179. selectorResolver.options.remove(0);
  3180. }
  3181. }
  3182. if(uroGetCBChecked('_cbURUserIDFilter') === false)
  3183. {
  3184. while(selectorCommentUser.options.length > 0)
  3185. {
  3186. selectorCommentUser.options.remove(0);
  3187. }
  3188. }
  3189. if(Object.keys(W.model.updateRequestSessions.objects).length === 0)
  3190. {
  3191. return;
  3192. }
  3193. var commenterUser = null;
  3194. if(uroGetCBChecked('_cbURUserIDFilter') === true)
  3195. {
  3196. if(selectorCommentUser.options.length === 0)
  3197. {
  3198. uroUpdateUserList();
  3199. }
  3200. if(selectorCommentUser.selectedOptions[0] !== undefined)
  3201. {
  3202. commenterUser = parseInt(selectorCommentUser.selectedOptions[0].value);
  3203. }
  3204. }
  3205. var resolverUser = null;
  3206. if(uroGetCBChecked('_cbURResolverIDFilter') === true)
  3207. {
  3208. if(selectorResolver.options.length === 0)
  3209. {
  3210. uroUpdateResolverList();
  3211. }
  3212. if(selectorResolver.selectedOptions[0] !== undefined)
  3213. {
  3214. resolverUser = parseInt(selectorResolver.selectedOptions[0].value);
  3215. }
  3216. }
  3217. uroCustomMarkerList = [];
  3218.  
  3219. var uFURs_masterEnable = uroGetCBChecked('_cbMasterEnable');
  3220. var filterOutsideEditableArea = uroGetCBChecked('_cbURFilterOutsideArea');
  3221. var filterSolved = uroGetCBChecked('_cbFilterSolved');
  3222. var filterUnidentified = uroGetCBChecked('_cbFilterUnidentified');
  3223. var filterClosed = uroGetCBChecked('_cbFilterClosedUR');
  3224. var filterOpen = uroGetCBChecked('_cbFilterOpenUR');
  3225. var filterDescMustBePresent = uroGetCBChecked('_cbURDescriptionMustBePresent');
  3226. var filterDescMustBeAbsent = uroGetCBChecked('_cbURDescriptionMustBeAbsent');
  3227. var filterKeywordMustBePresent = uroGetCBChecked('_cbEnableKeywordMustBePresent');
  3228. var filterKeywordMustBeAbsent = uroGetCBChecked('_cbEnableKeywordMustBeAbsent');
  3229. var filterMinURAge = uroGetCBChecked('_cbEnableMinAgeFilter');
  3230. var filterMaxURAge = uroGetCBChecked('_cbEnableMaxAgeFilter');
  3231. var filterMinComments = uroGetCBChecked('_cbEnableMinCommentsFilter');
  3232. var filterMaxComments = uroGetCBChecked('_cbEnableMaxCommentsFilter');
  3233. var filterReporterLastCommenter = uroGetCBChecked('_cbHideIfReporterLastCommenter');
  3234. var filterReporterNotLastCommenter = uroGetCBChecked('_cbHideIfReporterNotLastCommenter');
  3235. var filterHideAnyComments = uroGetCBChecked('_cbHideAnyComments');
  3236. var filterHideNotLastCommenter = uroGetCBChecked('_cbHideIfNotLastCommenter');
  3237. var filterHideMyComments = uroGetCBChecked('_cbHideMyComments');
  3238. var filterIfLastCommenter = uroGetCBChecked('_cbHideIfLastCommenter');
  3239. var filterIfNotLastCommenter = uroGetCBChecked('_cbHideIfNotLastCommenter');
  3240. var filterCommentMinAge = uroGetCBChecked('_cbEnableCommentAgeFilter2');
  3241. var filterCommentMaxAge = uroGetCBChecked('_cbEnableCommentAgeFilter');
  3242. var filterUserID = uroGetCBChecked('_cbURUserIDFilter');
  3243. var filterMyFollowed = uroGetCBChecked('_cbHideMyFollowed');
  3244. var filterMyUnfollowed = uroGetCBChecked('_cbHideMyUnfollowed');
  3245. var filterWazeAuto = uroGetCBChecked('_cbFilterWazeAuto');
  3246. var filterRoadworks = uroGetCBChecked('_cbFilterRoadworks');
  3247. var filterConstruction = uroGetCBChecked('_cbFilterConstruction');
  3248. var filterClosure = uroGetCBChecked('_cbFilterClosure');
  3249. var filterEvent = uroGetCBChecked('_cbFilterEvent');
  3250. var filterNote = uroGetCBChecked('_cbFilterNote');
  3251. var filterIncorrectTurn = uroGetCBChecked('_cbFilterIncorrectTurn');
  3252. var filterIncorrectAddress = uroGetCBChecked('_cbFilterIncorrectAddress');
  3253. var filterIncorrectRoute = uroGetCBChecked('_cbFilterIncorrectRoute');
  3254. var filterMissingRoundabout = uroGetCBChecked('_cbFilterMissingRoundabout');
  3255. var filterGeneralError = uroGetCBChecked('_cbFilterGeneralError');
  3256. var filterTurnNotAllowed = uroGetCBChecked('_cbFilterTurnNotAllowed');
  3257. var filterIncorrectJunction = uroGetCBChecked('_cbFilterIncorrectJunction');
  3258. var filterMissingBridgeOverpass = uroGetCBChecked('_cbFilterMissingBridgeOverpass');
  3259. var filterWrongDrivingDirection = uroGetCBChecked('_cbFilterWrongDrivingDirection');
  3260. var filterMissingExit = uroGetCBChecked('_cbFilterMissingExit');
  3261. var filterMissingRoad = uroGetCBChecked('_cbFilterMissingRoad');
  3262. var filterMissingLandmark = uroGetCBChecked('_cbFilterMissingLandmark');
  3263. var filterBlockedRoad = uroGetCBChecked('_cbFilterBlockedRoad');
  3264. var filterUndefined = uroGetCBChecked('_cbFilterUndefined');
  3265. var invertURFilters = uroGetCBChecked('_cbInvertURFilter');
  3266. var noFilterTaggedURs = uroGetCBChecked('_cbNoFilterForTaggedURs');
  3267. var keywordPresent = uroGetElmValue('_textKeywordPresent');
  3268. var keywordAbsent = uroGetElmValue('_textKeywordAbsent');
  3269. var thresholdMinAge = uroGetElmValue('_inputFilterMinDays');
  3270. var thresholdMaxAge = uroGetElmValue('_inputFilterMaxDays');
  3271. var thresholdMinComments = uroGetElmValue('_inputFilterMinComments');
  3272. var thresholdMaxComments = uroGetElmValue('_inputFilterMaxComments');
  3273. var thresholdMaxCommentAge = uroGetElmValue('_inputFilterCommentDays');
  3274. var thresholdMinCommentAge = uroGetElmValue('_inputFilterCommentDays2');
  3275. var urcCB = document.getElementById('URCommentsFilterEnabled');
  3276. for (var urobj in W.model.mapUpdateRequests.objects)
  3277. {
  3278. if(W.model.mapUpdateRequests.objects.hasOwnProperty(urobj))
  3279. {
  3280. var ureq = W.model.mapUpdateRequests.objects[urobj];
  3281. var urStyle = 'visible';
  3282. var ureqID = null;
  3283. if(ureq.fid === null) ureqID = ureq.attributes.id;
  3284. else ureqID = ureq.fid;
  3285. var hasMyComments = false;
  3286. var nComments = 0;
  3287. var customType = uroGetCustomType(ureqID, "ur");
  3288. if(W.model.updateRequestSessions.objects[ureqID] !== undefined)
  3289. {
  3290. nComments = W.model.updateRequestSessions.objects[ureqID].comments.length;
  3291. if((uFURs_masterEnable === false) && (nComments === 0))
  3292. {
  3293. // when master enable is turned off, we want to make sure that all URs, including ones that were previously hidden, are correctly
  3294. // displayed in their native form - i.e. no comment count or custom conversation bubbles. The easiest way to achieve this is to
  3295. // force the uroRenderCustomMarkers code to test for the presence of these bubbles on each UR, which we do by setting a non-zero
  3296. // comment count for each UR... For URs which genuinely do have no comments we use -1 to indicate that we're not really setting
  3297. // a comment count, but that we still need to do something that wouldn't be achieved by using 0.
  3298. nComments = -1;
  3299. }
  3300. }
  3301.  
  3302. var urcFilteringIsActive = false;
  3303. if(uFURs_masterEnable === true)
  3304. {
  3305. var wazeauto_ur = false;
  3306. var ukroadworks_ur = false;
  3307. var construction_ur = false;
  3308. var closure_ur = false;
  3309. var event_ur = false;
  3310. var note_ur = false;
  3311.  
  3312. var filterByNotIncludedKeyword = false;
  3313. var filterByIncludedKeyword = true;
  3314.  
  3315. var desc = '';
  3316. if(ureq.attributes.description !== null) desc = ureq.attributes.description.replace(/<\/?[^>]+(>|$)/g, "");
  3317.  
  3318. if(customType === 0) ukroadworks_ur = true;
  3319. else if(customType === 1) construction_ur = true;
  3320. else if(customType === 2) closure_ur = true;
  3321. else if(customType === 3) event_ur = true;
  3322. else if(customType === 4) note_ur = true;
  3323.  
  3324. // check UR against editable area...
  3325.  
  3326. if(filterOutsideEditableArea === true)
  3327. {
  3328. if(ureq.canEdit() === false) urStyle = 'hidden';
  3329. }
  3330. // check UR against current session ignore list...
  3331. if(uroIsOnIgnoreList(ureqID)) urStyle = 'hidden';
  3332.  
  3333. // check against closed/not identified filtering if enabled...
  3334. if(filterSolved === true)
  3335. {
  3336. if(ureq.attributes.resolution === 0) urStyle = 'hidden';
  3337. }
  3338. if(filterUnidentified === true)
  3339. {
  3340. if(ureq.attributes.resolution == 1) urStyle = 'hidden';
  3341. }
  3342.  
  3343. if((ureq.attributes.resolvedOn !== null) && (filterClosed === true))
  3344. {
  3345. urStyle = 'hidden';
  3346. }
  3347.  
  3348. if((ureq.attributes.resolvedOn === null) && (filterOpen === true))
  3349. {
  3350. urStyle = 'hidden';
  3351. }
  3352.  
  3353. if(urStyle == 'visible')
  3354. {
  3355. // check UR against keyword filtering if enabled...
  3356. if(filterDescMustBePresent === true)
  3357. {
  3358. if(desc === '') urStyle = 'hidden';
  3359. }
  3360. if(filterDescMustBeAbsent === true)
  3361. {
  3362. if(desc !== '') urStyle = 'hidden';
  3363. }
  3364.  
  3365. if(filterKeywordMustBePresent === true)
  3366. {
  3367. var keywordIsPresentInDesc = uroKeywordPresent(desc,keywordPresent);
  3368. filterByIncludedKeyword &= (!keywordIsPresentInDesc);
  3369. }
  3370. if(filterKeywordMustBeAbsent === true)
  3371. {
  3372. var keywordIsAbsentInDesc = uroKeywordPresent(desc,keywordAbsent);
  3373. filterByNotIncludedKeyword |= keywordIsAbsentInDesc;
  3374. }
  3375. }
  3376.  
  3377. if(urStyle == 'visible')
  3378. {
  3379. // do age-based filtering if enabled
  3380. if(filterMinURAge === true)
  3381. {
  3382. if(uroGetURAge(ureq,0,false) < thresholdMinAge) urStyle = 'hidden';
  3383. }
  3384. if(filterMaxURAge === true)
  3385. {
  3386. if(uroGetURAge(ureq,0,false) > thresholdMaxAge) urStyle = 'hidden';
  3387. }
  3388. }
  3389.  
  3390. if(urStyle == 'visible')
  3391. {
  3392. if(resolverUser !== null)
  3393. {
  3394. if(ureq.attributes.resolvedBy != resolverUser) urStyle = 'hidden';
  3395. }
  3396. }
  3397.  
  3398. if(urStyle == 'visible')
  3399. {
  3400. // do comments/following filtering
  3401. if(W.model.updateRequestSessions.objects[ureqID] !== undefined)
  3402. {
  3403. nComments = W.model.updateRequestSessions.objects[ureqID].comments.length;
  3404. var commentDaysOld = -1;
  3405.  
  3406.  
  3407. if(filterMinComments === true)
  3408. {
  3409. if(nComments < thresholdMinComments) urStyle = 'hidden';
  3410. }
  3411. if(filterMaxComments === true)
  3412. {
  3413. if(nComments > thresholdMaxComments) urStyle = 'hidden';
  3414. }
  3415.  
  3416.  
  3417. if(nComments > 0)
  3418. {
  3419. var reporterIsLastCommenter = false;
  3420. if(W.model.updateRequestSessions.objects[ureqID].comments[nComments-1].userID == -1) reporterIsLastCommenter = true;
  3421.  
  3422. if(filterReporterLastCommenter === true)
  3423. {
  3424. if(reporterIsLastCommenter === true) urStyle = 'hidden';
  3425. }
  3426. else if(filterReporterNotLastCommenter === true)
  3427. {
  3428. if(reporterIsLastCommenter === false) urStyle = 'hidden';
  3429. }
  3430.  
  3431. hasMyComments = uroURHasMyComments(ureqID);
  3432. if(hasMyComments === false)
  3433. {
  3434. if(filterHideAnyComments === true) urStyle = 'hidden';
  3435. if(filterHideNotLastCommenter === true) urStyle = 'hidden';
  3436. }
  3437. else
  3438. {
  3439. if(filterHideMyComments === true) urStyle = 'hidden';
  3440.  
  3441. var userIsLastCommenter = false;
  3442. if(W.model.updateRequestSessions.objects[ureqID].comments[nComments-1].userID == uroUserID) userIsLastCommenter = true;
  3443.  
  3444. if(filterIfLastCommenter === true)
  3445. {
  3446. if(userIsLastCommenter === true) urStyle = 'hidden';
  3447. }
  3448. else if(filterIfNotLastCommenter === true)
  3449. {
  3450. if(userIsLastCommenter === false) urStyle = 'hidden';
  3451. }
  3452. }
  3453. commentDaysOld = uroGetCommentAge(W.model.updateRequestSessions.objects[ureqID].comments[nComments-1]);
  3454. if((filterCommentMinAge === true) && (commentDaysOld != -1))
  3455. {
  3456. if(thresholdMaxCommentAge < commentDaysOld) urStyle = 'hidden';
  3457. }
  3458. if((filterCommentMaxAge === true) && (commentDaysOld != -1))
  3459. {
  3460. if(thresholdMinCommentAge > commentDaysOld) urStyle = 'hidden';
  3461. }
  3462.  
  3463. var cidx;
  3464. if((commenterUser !== null) && (urStyle != 'hidden'))
  3465. {
  3466. urStyle = 'hidden';
  3467. for(cidx=0; cidx<nComments; cidx++)
  3468. {
  3469. if(W.model.updateRequestSessions.objects[ureqID].comments[cidx].userID == commenterUser)
  3470. {
  3471. urStyle = 'visible';
  3472. break;
  3473. }
  3474. }
  3475. }
  3476.  
  3477. var commentText = '';
  3478. for(cidx=0; cidx<nComments; cidx++)
  3479. {
  3480. commentText += W.model.updateRequestSessions.objects[ureqID].comments[cidx].text;
  3481. }
  3482.  
  3483. if(filterKeywordMustBePresent === true)
  3484. {
  3485. var keywordIsPresentInComments = uroKeywordPresent(commentText,keywordPresent);
  3486. filterByIncludedKeyword &= (!keywordIsPresentInComments);
  3487. }
  3488. if(filterKeywordMustBeAbsent === true)
  3489. {
  3490. var keywordIsAbsentInComments = uroKeywordPresent(commentText,keywordAbsent);
  3491. filterByNotIncludedKeyword |= keywordIsAbsentInComments;
  3492. }
  3493. }
  3494. else
  3495. {
  3496. if(filterUserID === true)
  3497. {
  3498. urStyle = 'hidden';
  3499. }
  3500. }
  3501.  
  3502. filterByNotIncludedKeyword &= filterKeywordMustBeAbsent;
  3503. filterByIncludedKeyword &= filterKeywordMustBePresent;
  3504. if(filterByNotIncludedKeyword || filterByIncludedKeyword)
  3505. {
  3506. urStyle = 'hidden';
  3507. }
  3508.  
  3509.  
  3510. if(W.model.updateRequestSessions.objects[ureqID].isFollowing === true)
  3511. {
  3512. if(filterMyFollowed === true) urStyle = 'hidden';
  3513. }
  3514. else
  3515. {
  3516. if(filterMyUnfollowed === true) urStyle = 'hidden';
  3517. }
  3518. }
  3519. }
  3520.  
  3521. if(urStyle == 'visible')
  3522. {
  3523. // Test for Waze automatic URs before any others - these always (?) get inserted as General Error URs,
  3524. // so we can't filter them by type...
  3525. if(desc.indexOf('Waze Automatic:') != -1)
  3526. {
  3527. wazeauto_ur = true;
  3528. }
  3529.  
  3530. if(wazeauto_ur === true)
  3531. {
  3532. if(filterWazeAuto === true) urStyle = 'hidden';
  3533. }
  3534.  
  3535. else if(ukroadworks_ur === true)
  3536. {
  3537. if(filterRoadworks === true) urStyle = 'hidden';
  3538. }
  3539. else if(construction_ur === true)
  3540. {
  3541. if(filterConstruction === true) urStyle = 'hidden';
  3542. }
  3543. else if(closure_ur === true)
  3544. {
  3545. if(filterClosure === true) urStyle = 'hidden';
  3546. }
  3547. else if(event_ur === true)
  3548. {
  3549. if(filterEvent === true) urStyle = 'hidden';
  3550. }
  3551. else if(note_ur === true)
  3552. {
  3553. if(filterNote === true) urStyle = 'hidden';
  3554. }
  3555.  
  3556. else if(ureq.attributes.type == 6)
  3557. {
  3558. if(filterIncorrectTurn === true) urStyle = 'hidden';
  3559. }
  3560. else if(ureq.attributes.type == 7)
  3561. {
  3562. if (filterIncorrectAddress === true) urStyle = 'hidden';
  3563. }
  3564. else if(ureq.attributes.type == 8)
  3565. {
  3566. if(filterIncorrectRoute === true) urStyle = 'hidden';
  3567. }
  3568. else if(ureq.attributes.type == 9)
  3569. {
  3570. if(filterMissingRoundabout === true) urStyle = 'hidden';
  3571. }
  3572. else if(ureq.attributes.type == 10)
  3573. {
  3574. if(filterGeneralError === true) urStyle = 'hidden';
  3575. }
  3576. else if(ureq.attributes.type == 11)
  3577. {
  3578. if(filterTurnNotAllowed === true) urStyle = 'hidden';
  3579. }
  3580. else if(ureq.attributes.type == 12)
  3581. {
  3582. if(filterIncorrectJunction === true) urStyle = 'hidden';
  3583. }
  3584. else if(ureq.attributes.type == 13)
  3585. {
  3586. if(filterMissingBridgeOverpass === true) urStyle = 'hidden';
  3587. }
  3588. else if(ureq.attributes.type == 14)
  3589. {
  3590. if(filterWrongDrivingDirection === true) urStyle = 'hidden';
  3591. }
  3592. else if(ureq.attributes.type == 15)
  3593. {
  3594. if(filterMissingExit === true) urStyle = 'hidden';
  3595. }
  3596. else if(ureq.attributes.type == 16)
  3597. {
  3598. if(filterMissingRoad === true) urStyle = 'hidden';
  3599. }
  3600. else if(ureq.attributes.type == 18)
  3601. {
  3602. if(filterMissingLandmark === true) urStyle = 'hidden';
  3603. }
  3604. else if(ureq.attributes.type == 19)
  3605. {
  3606. if(filterBlockedRoad === true) urStyle = 'hidden';
  3607. }
  3608. else if(filterUndefined === true) urStyle = 'hidden';
  3609.  
  3610. if(invertURFilters === true)
  3611. {
  3612. if(urStyle == 'hidden') urStyle = 'visible';
  3613. else urStyle = 'hidden';
  3614. }
  3615. }
  3616.  
  3617. // filtering override for tagged URs
  3618. if(noFilterTaggedURs === true)
  3619. {
  3620. if(ukroadworks_ur === true)
  3621. {
  3622. if(filterRoadworks === false) urStyle = 'visible';
  3623. }
  3624. else if(construction_ur === true)
  3625. {
  3626. if(filterConstruction === false) urStyle = 'visible';
  3627. }
  3628. else if(closure_ur === true)
  3629. {
  3630. if(filterClosure === false) urStyle = 'visible';
  3631. }
  3632. else if(event_ur === true)
  3633. {
  3634. if(filterEvent === false) urStyle = 'visible';
  3635. }
  3636. else if(note_ur === true)
  3637. {
  3638. if(filterNote === false) urStyle = 'visible';
  3639. }
  3640. }
  3641.  
  3642. ////var urcCB = document.getElementById('URCommentsFilterEnabled');
  3643. if(urcCB !== null)
  3644. {
  3645. if(urcCB.checked)
  3646. {
  3647. urcFilteringIsActive = true;
  3648. }
  3649. }
  3650. }
  3651. // only touch marker visibility if we've got active filter settings, or if URComments is not
  3652. // doing any filtering of its own
  3653. if((hasActiveURFilters === true) || (urcFilteringIsActive === false) || (uFURs_masterEnable === false))
  3654. {
  3655. W.map.updateRequestLayer.markers[urobj].icon.imageDiv.style.visibility = urStyle;
  3656. }
  3657.  
  3658. if(urStyle != 'hidden')
  3659. {
  3660. uroAddCustomMarkers(ureqID,customType, hasMyComments, nComments);
  3661. }
  3662. }
  3663. }
  3664. uroRenderCustomMarkers('ur');
  3665. }
  3666.  
  3667.  
  3668. function uroFilterProblems()
  3669. {
  3670. if(uroFilterPreamble() === false) return;
  3671. var selector;
  3672.  
  3673. if((uroGetCBChecked('_cbMPNotClosedUserIDFilter') === false) && (uroGetCBChecked('_cbMPClosedUserIDFilter') === false))
  3674. {
  3675. selector = document.getElementById('_selectMPUserID');
  3676. while(selector.options.length > 0)
  3677. {
  3678. selector.options.remove(0);
  3679. }
  3680. }
  3681.  
  3682. var solverUser = null;
  3683. if((uroGetCBChecked('_cbMPNotClosedUserIDFilter') === true) || (uroGetCBChecked('_cbMPClosedUserIDFilter') === true))
  3684. {
  3685. selector = document.getElementById('_selectMPUserID');
  3686. if(selector.options.length === 0)
  3687. {
  3688. uroUpdateMPSolverList();
  3689. }
  3690. if(selector.selectedOptions[0] !== undefined)
  3691. {
  3692. solverUser = parseInt(selector.selectedOptions[0].value);
  3693. }
  3694. }
  3695.  
  3696. var urobj;
  3697. var problem;
  3698. var problemStyle;
  3699. var problem_marker_img;
  3700.  
  3701. for (urobj in W.model.problems.objects)
  3702. {
  3703. if(W.model.problems.objects.hasOwnProperty(urobj))
  3704. {
  3705. problem = W.model.problems.objects[urobj];
  3706. problemStyle = 'visible';
  3707. var ureqID = null;
  3708. var customType = null;
  3709.  
  3710. if(uroGetCBChecked('_cbMasterEnable') === true)
  3711. {
  3712. ureqID = problem.attributes.id;
  3713. customType = uroGetCustomType(ureqID, "mp");
  3714.  
  3715. // check problem against current session ignore list...
  3716. if(uroIsOnIgnoreList(ureqID)) problemStyle = 'hidden';
  3717.  
  3718.  
  3719. if(uroGetCBChecked('_cbMPFilterOutsideArea') === true)
  3720. {
  3721. if(problem.canEdit() === false)
  3722. {
  3723. problemStyle = 'hidden';
  3724. }
  3725. }
  3726.  
  3727. // check against closed/not identified filtering if enabled...
  3728. problem_marker_img = '';
  3729. if(problem.geometry.id !== null)
  3730. {
  3731. if(document.getElementById(problem.geometry.id) !== null)
  3732. {
  3733. problem_marker_img = document.getElementById(problem.geometry.id).href.baseVal;
  3734. if(uroGetCBChecked('_cbMPFilterSolved') === true)
  3735. {
  3736. if(problem_marker_img.indexOf('_solved') != -1) problemStyle = 'hidden';
  3737. }
  3738. if(uroGetCBChecked('_cbMPFilterUnidentified') === true)
  3739. {
  3740. if(problem_marker_img.indexOf('_rejected') != -1) problemStyle = 'hidden';
  3741. }
  3742. }
  3743. }
  3744.  
  3745. if(uroGetCBChecked('_cbMPFilterClosed') === true)
  3746. {
  3747. if(problem.attributes.open === false)
  3748. {
  3749. problemStyle = 'hidden';
  3750. }
  3751. }
  3752.  
  3753. if(problemStyle == 'visible')
  3754. {
  3755. if(solverUser !== null)
  3756. {
  3757. if((uroGetCBChecked('_cbMPNotClosedUserIDFilter') === true) && (problem.attributes.resolvedBy == solverUser)) problemStyle = 'hidden';
  3758. if((uroGetCBChecked('_cbMPClosedUserIDFilter') === true) && (problem.attributes.resolvedBy != solverUser)) problemStyle = 'hidden';
  3759. }
  3760. }
  3761.  
  3762. if(problemStyle == 'visible')
  3763. {
  3764. var problemType = null;
  3765. if(uroDOMHasTurnProblems)
  3766. {
  3767. problemType = problem.attributes.problemType;
  3768. }
  3769. else
  3770. {
  3771. problemType = problem.attributes.subType;
  3772. }
  3773.  
  3774. if(problemType == 101)
  3775. {
  3776. if(uroGetCBChecked('_cbMPFilterDrivingDirectionMismatch') === true) problemStyle = 'hidden';
  3777. }
  3778. else if(problemType == 102)
  3779. {
  3780. if(uroGetCBChecked('_cbMPFilterMissingJunction') === true) problemStyle = 'hidden';
  3781. }
  3782. else if(problemType == 103)
  3783. {
  3784. if(uroGetCBChecked('_cbMPFilterMissingRoad') === true) problemStyle = 'hidden';
  3785. }
  3786. else if(problemType == 104)
  3787. {
  3788. if(uroGetCBChecked('_cbMPFilterCrossroadsJunctionMissing') === true) problemStyle = 'hidden';
  3789. }
  3790. else if(problemType == 105)
  3791. {
  3792. if(uroGetCBChecked('_cbMPFilterRoadTypeMismatch') === true) problemStyle = 'hidden';
  3793. }
  3794. else if(problemType == 106)
  3795. {
  3796. if(uroGetCBChecked('_cbMPFilterRestrictedTurn') === true) problemStyle = 'hidden';
  3797. }
  3798. else if(problemType == 200)
  3799. {
  3800. if(uroGetCBChecked('_cbMPFilterTurnProblem') === true) problemStyle = 'hidden';
  3801. }
  3802. else if(problemType == 300)
  3803. {
  3804. if(uroGetCBChecked('_cbMPFilterRoadClosureProblem') === true) problemStyle = 'hidden';
  3805. }
  3806. else if(uroGetCBChecked('_cbMPFilterUnknownProblem') === true) problemStyle = 'hidden';
  3807.  
  3808.  
  3809. if(uroGetCBChecked('_cbMPFilterReopenedProblem') === true)
  3810. {
  3811. if((problem.attributes.open === true) && (problem.attributes.resolvedOn !== null))
  3812. {
  3813. problemStyle = 'hidden';
  3814. }
  3815. }
  3816.  
  3817.  
  3818. if(uroGetCBChecked('_cbInvertMPFilter') === true)
  3819. {
  3820. if(problemStyle == 'hidden') problemStyle = 'visible';
  3821. else problemStyle = 'hidden';
  3822. }
  3823.  
  3824.  
  3825. if(problem.attributes.weight <= 3)
  3826. {
  3827. if(uroGetCBChecked('_cbMPFilterLowSeverity') === true) problemStyle = 'hidden';
  3828. }
  3829. else if(problem.attributes.weight <= 7)
  3830. {
  3831. if(uroGetCBChecked('_cbMPFilterMediumSeverity') === true) problemStyle = 'hidden';
  3832. }
  3833. else if(uroGetCBChecked('_cbMPFilterHighSeverity') === true) problemStyle = 'hidden';
  3834. }
  3835. }
  3836.  
  3837. W.map.problemLayer.markers[urobj].icon.imageDiv.style.visibility = problemStyle;
  3838.  
  3839. if((problemStyle != 'hidden') && (ureqID !== null) && (customType !== null))
  3840. {
  3841. uroAddCustomMarkers(ureqID,customType, false, 0);
  3842. }
  3843. }
  3844. }
  3845.  
  3846. if(uroDOMHasTurnProblems)
  3847. {
  3848. for (urobj in W.model.turnProblems.objects)
  3849. {
  3850. if(W.model.turnProblems.objects.hasOwnProperty(urobj))
  3851. {
  3852. problem = W.model.turnProblems.objects[urobj];
  3853. problemStyle = 'visible';
  3854.  
  3855. if(uroGetCBChecked('_cbMasterEnable') === true)
  3856. {
  3857. // check problem against current session ignore list...
  3858. if(uroIsOnIgnoreList(problem.attributes.id)) problemStyle = 'hidden';
  3859.  
  3860. // check against closed/not identified filtering if enabled...
  3861. problem_marker_img = '';
  3862. if(problem.geometry.id !== null)
  3863. {
  3864. if(document.getElementById(problem.geometry.id) !== null)
  3865. {
  3866. problem_marker_img = document.getElementById(problem.geometry.id).href.baseVal;
  3867. if(uroGetCBChecked('_cbMPFilterSolved') === true)
  3868. {
  3869. if(problem_marker_img.indexOf('_solved') != -1) problemStyle = 'hidden';
  3870. }
  3871. if(uroGetCBChecked('_cbMPFilterUnidentified') === true)
  3872. {
  3873. if(problem_marker_img.indexOf('_rejected') != -1) problemStyle = 'hidden';
  3874. }
  3875. }
  3876. }
  3877.  
  3878. if(uroGetCBChecked('_cbMPFilterClosed') === true)
  3879. {
  3880. if(problem.attributes.open === false)
  3881. {
  3882. problemStyle = 'hidden';
  3883. }
  3884. }
  3885.  
  3886. if(problemStyle == 'visible')
  3887. {
  3888. if(uroGetCBChecked('_cbMPFilterTurnProblem') === true) problemStyle = 'hidden';
  3889.  
  3890. if(uroGetCBChecked('_cbMPFilterReopenedProblem') === true)
  3891. {
  3892. if((problem.attributes.open === true) && (problem.attributes.resolvedOn !== null))
  3893. {
  3894. problemStyle = 'hidden';
  3895. }
  3896. }
  3897.  
  3898. if(uroGetCBChecked('_cbInvertMPFilter') === true)
  3899. {
  3900. if(problemStyle == 'hidden') problemStyle = 'visible';
  3901. else problemStyle = 'hidden';
  3902. }
  3903. }
  3904. }
  3905. W.map.problemLayer.markers[urobj].icon.imageDiv.style.visibility = problemStyle;
  3906. }
  3907. }
  3908. }
  3909. uroRenderCustomMarkers('mp');
  3910. }
  3911.  
  3912. function uroToHex(decValue,digits)
  3913. {
  3914. var modifier = 1;
  3915. for(var i=0; i<digits; i++)
  3916. {
  3917. modifier *= 16;
  3918. }
  3919. decValue = parseInt(decValue);
  3920. decValue += modifier;
  3921. var retval = decValue.toString(16);
  3922. retval = retval.substr(-digits);
  3923. retval = retval.toUpperCase();
  3924. return retval;
  3925. }
  3926.  
  3927. function uroFilterPreamble()
  3928. {
  3929. var mapviewport = document.getElementsByClassName("olMapViewport")[0];
  3930. if(mapviewport === null)
  3931. {
  3932. if(uroNullMapViewport === false)
  3933. {
  3934. uroAddLog('caught null mapviewport');
  3935. uroNullMapViewport = true;
  3936. }
  3937. return false;
  3938. }
  3939. uroNullMapViewport = false;
  3940.  
  3941. if((uroGetCBChecked('_cbWhiteBackground') === true) && (uroGetCBChecked('_cbMasterEnable') === true))
  3942. {
  3943. var customColour = '#' + uroToHex(uroGetElmValue('_inputCustomBackgroundRed'),2);
  3944. customColour += uroToHex(uroGetElmValue('_inputCustomBackgroundGreen'),2);
  3945. customColour += uroToHex(uroGetElmValue('_inputCustomBackgroundBlue'),2);
  3946. mapviewport.style.backgroundColor = customColour;
  3947. }
  3948. else
  3949. {
  3950. mapviewport.style.backgroundColor = "#C2C2C2";
  3951. }
  3952.  
  3953. if((uroGetCBChecked('_cbHideAMLayer')) && (uroGetCBChecked('_cbMasterEnable') === true))
  3954. {
  3955. W.map.managedAreasLayer.setOpacity(0);
  3956. }
  3957. else
  3958. {
  3959. W.map.managedAreasLayer.setOpacity(1);
  3960. }
  3961.  
  3962. return true;
  3963. }
  3964.  
  3965. function uroFilterItems_URTabClick()
  3966. {
  3967. uroFilterURs();
  3968. }
  3969. function uroFilterItems_MPTabClick()
  3970. {
  3971. uroFilterProblems();
  3972. }
  3973. function uroFilterItems_PlacesTabClick()
  3974. {
  3975. uroFilterPlaces();
  3976. }
  3977. function uroFilterItems_CamerasTabClick()
  3978. {
  3979. uroFilterCameras();
  3980. }
  3981. function uroFilterItems_MiscTabClick()
  3982. {
  3983. uroFilterItems();
  3984. }
  3985. function uroFilterItems_MasterEnableClick()
  3986. {
  3987. if(uroGetCBChecked('_cbMasterEnable') === false)
  3988. {
  3989. uroHidePopup();
  3990. }
  3991. uroFilterItems();
  3992. }
  3993.  
  3994. function uroFilterItems()
  3995. {
  3996. uroFilterProblems();
  3997. uroFilterPlaces();
  3998. uroFilterCameras();
  3999. uroFilterURs();
  4000. }
  4001.  
  4002. function uroFilterItemsOnMove()
  4003. {
  4004. W.map.events.unregister('mousemove',null,uroFilterItemsOnMove);
  4005. uroFilterItems();
  4006. }
  4007.  
  4008.  
  4009. function uroDeleteObject()
  4010. {
  4011. uroAddLog('delete camera ID '+uroShownFID);
  4012. if(W.model.cameras.objects[uroShownFID] === null)
  4013. {
  4014. uroAddLog('camera object not found...');
  4015. return false;
  4016. }
  4017. uroRemoveCamFromWatchList();
  4018. var actionObj = require('Waze/Action/DeleteObject');
  4019. var deleteAction = new actionObj(W.model.cameras.objects[uroShownFID], null);
  4020. W.model.actionManager.add(deleteAction);
  4021. uroExitPopup();
  4022. uroHidePopup();
  4023. return false;
  4024. }
  4025.  
  4026.  
  4027. function uroGetUserNameAndRank(userID)
  4028. {
  4029. var userName;
  4030. var userLevel;
  4031. if(W.model.users.objects[userID] !== undefined)
  4032. {
  4033. userName = W.model.users.objects[userID].userName;
  4034. if(userName === undefined)
  4035. {
  4036. userName = userID;
  4037. }
  4038. userLevel = W.model.users.objects[userID].rank + 1;
  4039. }
  4040. else
  4041. {
  4042. userName = userID;
  4043. userLevel = '?';
  4044. }
  4045. return userName + ' (' + userLevel + ')';
  4046. }
  4047.  
  4048.  
  4049. function uroCheckCommentsForKeyword(idSrc, keyword)
  4050. {
  4051. var ursObj = W.model.updateRequestSessions.objects[idSrc];
  4052. if(typeof(ursObj) == 'undefined') return false;
  4053. if(ursObj.comments.length === 0) return false;
  4054.  
  4055. for(var idx=0; idx<ursObj.comments.length; idx++)
  4056. {
  4057. if(ursObj.comments[idx].text.indexOf(keyword) != -1)
  4058. {
  4059. return true;
  4060. }
  4061. }
  4062. return false;
  4063. }
  4064.  
  4065.  
  4066. function uroGetCustomMarkerIdx(customType)
  4067. {
  4068. if(customType === 0) return 3;
  4069. if(customType === 1) return 3;
  4070. if(customType === 2) return 5;
  4071. if(customType === 3) return 7;
  4072. if(customType === 4) return 9;
  4073. if(customType === 100) return 11;
  4074. if(customType === 101) return 13;
  4075. if(customType === 102) return 15;
  4076. return -1;
  4077. }
  4078.  
  4079. function uroGetCustomType(idSrc, markerType)
  4080. {
  4081. var desc = '';
  4082. if(markerType == "ur")
  4083. {
  4084. var ureq = W.model.mapUpdateRequests.objects[idSrc];
  4085. if(ureq.attributes.description !== null)
  4086. {
  4087. desc = ureq.attributes.description;
  4088. }
  4089. }
  4090. else if(markerType == "mp")
  4091. {
  4092. var mp = W.model.problems.objects[idSrc];
  4093. if(mp.attributes.description !== null)
  4094. {
  4095. desc = mp.attributes.description;
  4096. }
  4097. }
  4098.  
  4099. if(desc !== '')
  4100. {
  4101. if(desc.indexOf('[ROADWORKS]') != -1) return 0;
  4102. if(desc.indexOf('[CONSTRUCTION]') != -1) return 1;
  4103. if(desc.indexOf('[CLOSURE]') != -1) return 2;
  4104. if(desc.indexOf('[EVENT]') != -1) return 3;
  4105. if(desc.indexOf('[NOTE]') != -1) return 4;
  4106. if(desc.indexOf('[Elgin]') != -1) return 100;
  4107. if(desc.indexOf('[TrafficCast]') != -1) return 101;
  4108. if(desc.indexOf('[TM]') != -1) return 102;
  4109. }
  4110. if(markerType == "ur")
  4111. {
  4112. if(uroCheckCommentsForKeyword(idSrc,'[ROADWORKS]')) return 0;
  4113. if(uroCheckCommentsForKeyword(idSrc,'[CONSTRUCTION]')) return 1;
  4114. if(uroCheckCommentsForKeyword(idSrc,'[CLOSURE]')) return 2;
  4115. if(uroCheckCommentsForKeyword(idSrc,'[EVENT]')) return 3;
  4116. if(uroCheckCommentsForKeyword(idSrc,'[NOTE]')) return 4;
  4117. }
  4118.  
  4119. return -1;
  4120. }
  4121.  
  4122.  
  4123. function uroFormatRestriction(restObj)
  4124. {
  4125. var retval = '<tr>';
  4126. retval += '<td style="text-align:center;">';
  4127. if((restObj.days & 1) == 1) retval += 'S';
  4128. else retval += '-';
  4129. retval += '</td><td style="text-align:center;">';
  4130. if((restObj.days & 2) == 2) retval += 'M';
  4131. else retval += '-';
  4132. retval += '</td><td style="text-align:center;">';
  4133. if((restObj.days & 4) == 4) retval += 'T';
  4134. else retval += '-';
  4135. retval += '</td><td style="text-align:center;">';
  4136. if((restObj.days & 8) == 8) retval += 'W';
  4137. else retval += '-';
  4138. retval += '</td><td style="text-align:center;">';
  4139. if((restObj.days & 16) == 16) retval += 'T';
  4140. else retval += '-';
  4141. retval += '</td><td style="text-align:center;">';
  4142. if((restObj.days & 32) == 32) retval += 'F';
  4143. else retval += '-';
  4144. retval += '</td><td style="text-align:center;">';
  4145. if((restObj.days & 64) == 64) retval += 'S';
  4146. else retval += '-';
  4147.  
  4148. retval += '</td><td>';
  4149.  
  4150. if(restObj.fromDate === null) retval += 'All dates';
  4151. else retval += restObj.fromDate+' to '+restObj.toDate;
  4152.  
  4153. retval += '</td><td>';
  4154.  
  4155. if(restObj.allDay === true) retval += 'All day';
  4156. else retval += restObj.fromTime+' to '+restObj.toTime;
  4157.  
  4158. retval += '</td><td>';
  4159.  
  4160. if(restObj.allVehicleTypes == restObj.vehicleTypes) retval += 'All vehicles';
  4161. else retval += 'Some vehicles';
  4162.  
  4163. retval += '</td><td>';
  4164.  
  4165. if(restObj.description !== null)
  4166. {
  4167. var desc = restObj.description.replace(/<\/?[^>]+(>|$)/g, "");
  4168. desc = uroClickify(desc);
  4169. retval += desc;
  4170. }
  4171.  
  4172. retval += '</td></tr>';
  4173.  
  4174. return retval;
  4175. }
  4176.  
  4177. function uroHidePopup()
  4178. {
  4179. if(uroPopupShown)
  4180. {
  4181. uroDiv.style.visibility = 'hidden';
  4182. uroPopupShown = false;
  4183. uroPopupTimer = -2;
  4184. uroShownFID = -1;
  4185. }
  4186. }
  4187.  
  4188. function uroRecentreSessionOnUR()
  4189. {
  4190. W.map.updateRequestLayer.markers[uroShownFID].icon.imageDiv.click();
  4191. W.map.moveTo(W.map.updateRequestLayer.markers[uroShownFID].lonlat, 5);
  4192. uroHidePopup();
  4193. return false;
  4194. }
  4195.  
  4196. function uroRecentreSessionOnMP()
  4197. {
  4198. W.map.problemLayer.markers[uroShownFID].icon.imageDiv.click();
  4199. W.map.moveTo(W.map.problemLayer.markers[uroShownFID].lonlat, 5);
  4200. uroHidePopup();
  4201. return false;
  4202. }
  4203.  
  4204. function uroRecentreSessionOnPUR()
  4205. {
  4206. W.map.placeUpdatesLayer.markers[uroShownFID].icon.imageDiv.click();
  4207. W.map.moveTo(W.map.placeUpdatesLayer.markers[uroShownFID].lonlat, 5);
  4208. uroHidePopup();
  4209. return false;
  4210. }
  4211.  
  4212. function uroRecentreSessionOnVenueNavPoint()
  4213. {
  4214. W.map.moveTo(uroGetVenueNavPoint(uroShownFID), 5);
  4215. uroHidePopup();
  4216. return false;
  4217. }
  4218.  
  4219. function uroGetDateTimeString(ts)
  4220. {
  4221. var tDateObj = new Date(ts);
  4222. var dateLocale;
  4223. var timeLocale;
  4224. if(uroGetCBChecked('_cbDateFmtDDMMYY')) dateLocale = 'en-gb';
  4225. if(uroGetCBChecked('_cbDateFmtMMDDYY')) dateLocale = 'en-us';
  4226. if(uroGetCBChecked('_cbDateFmtYYMMDD')) dateLocale = 'ja';
  4227. if(uroGetCBChecked('_cbTimeFmt24H')) timeLocale = 'en-gb';
  4228. if(uroGetCBChecked('_cbTimeFmt12H')) timeLocale = 'en-us';
  4229. return tDateObj.toLocaleDateString(dateLocale) + ' ' + tDateObj.toLocaleTimeString(timeLocale);
  4230. }
  4231.  
  4232. function uroParsePxString(pxString)
  4233. {
  4234. return parseInt(pxString.split("px")[0]);
  4235. }
  4236.  
  4237. function uroStackListObj(fid,x,y)
  4238. {
  4239. this.fid = fid;
  4240. this.x = uroTypeCast(x);
  4241. this.y = uroTypeCast(y);
  4242. }
  4243.  
  4244. function uroRestackMarkers()
  4245. {
  4246. if(uroStackList.length === 0) return;
  4247.  
  4248. var markerCollection = null;
  4249. if(uroStackType == 1) markerCollection = W.map.updateRequestLayer.markers;
  4250. else if(uroStackType == 2) markerCollection = W.map.problemLayer.markers;
  4251. else if(uroStackType == 3) markerCollection = W.map.placeUpdatesLayer.markers;
  4252.  
  4253. if(markerCollection !== null)
  4254. {
  4255. for(var idx=0; idx<uroStackList.length; idx++)
  4256. {
  4257. var orig_x = uroStackList[idx].x + 'px';
  4258. var orig_y = uroStackList[idx].y + 'px';
  4259. var fid = uroStackList[idx].fid;
  4260.  
  4261. if(markerCollection[fid] !== undefined)
  4262. {
  4263. markerCollection[fid].icon.imageDiv.style.left = orig_x;
  4264. markerCollection[fid].icon.imageDiv.style.top = orig_y;
  4265. }
  4266. }
  4267. uroStackList = [];
  4268. uroUnstackedMasterID = null;
  4269. uroStackType = null;
  4270. }
  4271. }
  4272.  
  4273. function uroIsIDAlreadyUnstacked(idSrc)
  4274. {
  4275. if(uroStackList.length === 0) return false;
  4276. for(var idx=0; idx<uroStackList.length; idx++)
  4277. {
  4278. if(uroStackList[idx].fid == idSrc) return true;
  4279. }
  4280. return false;
  4281. }
  4282.  
  4283. function uroCheckStacking(stackType, masterID, unstackedX, unstackedY)
  4284. {
  4285. if(W.map.getZoom() < uroGetElmValue('_inputUnstackZoomLevel')) return;
  4286.  
  4287. if(uroIsIDAlreadyUnstacked(masterID) === true) return;
  4288. if(uroPopupDwellTimer > 0) return;
  4289.  
  4290. uroAddLog('checking for marker stack, type '+stackType+'...');
  4291. var stackList = [];
  4292. var threshSquared = uroGetElmValue('_inputUnstackSensitivity');
  4293. threshSquared *= threshSquared;
  4294.  
  4295. var markerCollection = null;
  4296. var marker;
  4297. if(stackType == 1) markerCollection = W.map.updateRequestLayer.markers;
  4298. else if(stackType == 2) markerCollection = W.map.problemLayer.markers;
  4299. else if(stackType == 3) markerCollection = W.map.placeUpdatesLayer.markers;
  4300.  
  4301. if(markerCollection !== null)
  4302. {
  4303. for(marker in markerCollection)
  4304. {
  4305. if(markerCollection.hasOwnProperty(marker))
  4306. {
  4307. var testMarkerObj = markerCollection[marker];
  4308. var includeInStack = (testMarkerObj.icon.imageDiv.style.visibility != 'hidden');
  4309. var suppressClosed = (testMarkerObj.icon.imageDiv.classList.contains("recently-closed") & (W.map.updateRequestLayer.showHidden === false));
  4310.  
  4311. if((includeInStack) && (!suppressClosed))
  4312. {
  4313. if(testMarkerObj.id != masterID)
  4314. {
  4315. var xdiff = unstackedX - uroParsePxString(markerCollection[testMarkerObj.id].icon.imageDiv.style.left);
  4316. var ydiff = unstackedY - uroParsePxString(markerCollection[testMarkerObj.id].icon.imageDiv.style.top);
  4317. var distSquared = ((xdiff * xdiff) + (ydiff * ydiff));
  4318. if(distSquared < threshSquared)
  4319. {
  4320. stackList.push(testMarkerObj.id);
  4321. }
  4322. }
  4323. }
  4324. }
  4325. }
  4326. }
  4327. if(stackList.length > 0)
  4328. {
  4329. uroAddLog('markers are stacked!');
  4330. if(uroUnstackedMasterID != masterID)
  4331. {
  4332. uroAddLog('unstacked ID mismatch, relocating markers...');
  4333. uroRestackMarkers();
  4334. uroStackType = stackType;
  4335. uroUnstackedMasterID = masterID;
  4336. uroStackList = [];
  4337.  
  4338. // push the highlighted marker onto the stacklist so uroIsIDAlreadyUnstacked() will return true
  4339. uroStackList.push(new uroStackListObj(masterID,unstackedX,unstackedY));
  4340.  
  4341. for(var shoveIdx=0; shoveIdx < stackList.length; shoveIdx++)
  4342. {
  4343. var fid = stackList[shoveIdx];
  4344. var x = uroParsePxString(markerCollection[fid].icon.imageDiv.style.left);
  4345. var y = uroParsePxString(markerCollection[fid].icon.imageDiv.style.top);
  4346. // store the unstacked marker positions so they can be reinstated later
  4347. uroStackList.push(new uroStackListObj(fid,x,y));
  4348. unstackedX += 10;
  4349. unstackedY -= 30;
  4350. markerCollection[fid].icon.imageDiv.style.left = unstackedX + 'px';
  4351. markerCollection[fid].icon.imageDiv.style.top = unstackedY + 'px';
  4352. }
  4353.  
  4354. // hide other markers to prevent confusion with the unstacked markers
  4355. for(marker in markerCollection)
  4356. {
  4357. if(markerCollection.hasOwnProperty(marker))
  4358. {
  4359. var toHideID = markerCollection[marker].id;
  4360. if(uroIsIDAlreadyUnstacked(toHideID) === false)
  4361. {
  4362. markerCollection[toHideID].icon.imageDiv.style.visibility = 'hidden';
  4363. }
  4364. }
  4365. }
  4366. }
  4367. }
  4368. else
  4369. {
  4370. uroRestackMarkers();
  4371. }
  4372. }
  4373.  
  4374. function uroGetVenueNavPoint(uroFID)
  4375. {
  4376. for(var vObj in W.model.venues.objects)
  4377. {
  4378. if(W.model.venues.objects.hasOwnProperty(vObj))
  4379. {
  4380. if(uroFID == vObj)
  4381. {
  4382. return W.model.venues.objects[vObj].getNavigationPoint().point.toLonLat();
  4383. }
  4384. }
  4385. }
  4386. // just in case... return a safe value if the requested venue object wasn't found
  4387. return W.map.getCenter();
  4388. }
  4389.  
  4390. function uroOpenNewTab()
  4391. {
  4392. // flush the current settings into localStorage before the new tab opens, so that when its instance of
  4393. // URO+ fires up it'll have the same settings as this one
  4394. uroSaveSettings();
  4395. return true;
  4396. }
  4397.  
  4398. function uroEditTBR()
  4399. {
  4400. if(uroTBRObj === null)
  4401. {
  4402. return;
  4403. }
  4404. uroTBRObj.click();
  4405. return false;
  4406. }
  4407.  
  4408. function uroNewLookHighlightedItemsCheck(e)
  4409. {
  4410. if(e == 'dwellTimeout')
  4411. {
  4412. }
  4413. else
  4414. {
  4415. if((uroMouseIsDown) && (e.buttons === 0))
  4416. {
  4417. uroAddLog('trapped erroneous mousedown state');
  4418. uroMouseIsDown = false;
  4419. }
  4420. }
  4421. if(uroMouseIsDown)
  4422. {
  4423. return;
  4424. }
  4425.  
  4426. if(OpenLayers === null)
  4427. {
  4428. if(uroNullOpenLayers === false)
  4429. {
  4430. uroAddLog('caught null OpenLayers');
  4431. uroNullOpenLayers = true;
  4432. }
  4433. return;
  4434. }
  4435. uroNullOpenLayers = false;
  4436.  
  4437. var rc = document.getElementById(uroRootContainer);
  4438. if(rc === null)
  4439. {
  4440. if(uroNullRootContainer === false)
  4441. {
  4442. uroAddLog('caught null rootContainer');
  4443. uroNullRootContainer = true;
  4444. }
  4445. return;
  4446. }
  4447. uroNullRootContainer = false;
  4448.  
  4449. if(W.map.updateRequestLayer === null)
  4450. {
  4451. if(uroNullURLayer === false)
  4452. {
  4453. uroAddLog('caught null UR layer');
  4454. uroNullURLayer = true;
  4455. }
  4456. return;
  4457. }
  4458. uroNullURLayer = false;
  4459.  
  4460. if(W.map.problemLayer === null)
  4461. {
  4462. if(uroNullProblemLayer === false)
  4463. {
  4464. uroAddLog('caught null problem layer');
  4465. uroNullProblemLayer = true;
  4466. }
  4467. return;
  4468. }
  4469. uroNullProblemLayer = false;
  4470.  
  4471. if(uroGetCBChecked('_cbMasterEnable') === false)
  4472. {
  4473. return;
  4474. }
  4475.  
  4476. var mouseX;
  4477. var mouseY;
  4478. if(e == 'dwellTimeout')
  4479. {
  4480. mouseX = uroPrevMouseX;
  4481. mouseY = uroPrevMouseY;
  4482. }
  4483. else
  4484. {
  4485. mouseX = e.pageX - document.getElementById('map').getBoundingClientRect().left;
  4486. mouseY = e.pageY - document.getElementById('map').getBoundingClientRect().top;
  4487.  
  4488. var maxJitter = uroGetElmValue('_inputMaxJitter');
  4489. if((Math.abs(uroPrevMouseX - mouseX) > maxJitter) || (Math.abs(uroPrevMouseY - mouseY) > maxJitter))
  4490. {
  4491. uroPopupDwellTimer = uroGetElmValue('_inputPopupDwellTimeout');
  4492. }
  4493. uroPrevMouseX = mouseX;
  4494. uroPrevMouseY = mouseY;
  4495. }
  4496.  
  4497. var result = '';
  4498. var rw;
  4499. var rh;
  4500.  
  4501. var popupXOffset = uroParsePxString(window.getComputedStyle(document.getElementById('sidebar')).getPropertyValue("width"));
  4502. var popupYOffset = $(document.getElementById("WazeMap")).offset().top - 100;
  4503. var uroPopupX = mouseX + popupXOffset + 10;
  4504. var uroPopupY = mouseY + popupYOffset + 10;
  4505.  
  4506. var objHasIgnoreLink = false;
  4507. var objHasDeleteLink = false;
  4508. var objHasAddWatchLink = false;
  4509. var objHasRemoveWatchLink = false;
  4510. var objHasUpdateWatchLink = false;
  4511. var objHasRecentreSessionLink = false;
  4512. var objHasOpenInNewTabLink = false;
  4513.  
  4514. var isVenue = false;
  4515. var newPopupType = null;
  4516. var markerObj;
  4517. var markerPos;
  4518. var markerImg;
  4519. var ureq;
  4520. var idx;
  4521. var hovered;
  4522.  
  4523. // popup for segment restrictions
  4524. if(uroGetCBChecked('_cbInhibitSegPopup') === false)
  4525. {
  4526. for(var slIdx=0; slIdx < W.map.segmentLayer.features.length; slIdx++)
  4527. {
  4528. if(W.map.segmentLayer.features[slIdx].renderIntent == 'highlight')
  4529. {
  4530. var doPopUp = false;
  4531. var segObj;
  4532. var restObj;
  4533. if(W.map.segmentLayer.features[slIdx].fid === null) segObj = W.map.segmentLayer.features[slIdx].model;
  4534. else segObj = W.map.segmentLayer.features[slIdx];
  4535. result += '<table cellpadding=4 border=1">';
  4536. if(segObj.attributes.fwdRestrictions.length > 0)
  4537. {
  4538. doPopUp = true;
  4539. result += '<tr><td colspan=11><b>A-B restrictions:</b></td></tr>';
  4540. for(idx = 0; idx < segObj.attributes.fwdRestrictions.length; idx++)
  4541. {
  4542. restObj = segObj.attributes.fwdRestrictions[idx];
  4543. result += uroFormatRestriction(restObj);
  4544. }
  4545. }
  4546. if (segObj.attributes.revRestrictions.length > 0)
  4547. {
  4548. doPopUp = true;
  4549. result += '<tr><td colspan=11><b>B-A restrictions:</b></td></tr>';
  4550. for(idx = 0; idx < segObj.attributes.revRestrictions.length; idx++)
  4551. {
  4552. restObj = segObj.attributes.revRestrictions[idx];
  4553. result += uroFormatRestriction(restObj);
  4554. }
  4555. }
  4556. result += '</table>';
  4557. if(W.map.closuresMarkerLayer.getVisibility() === true)
  4558. {
  4559. result += '<table cellpadding=4 border=1" width="100%">';
  4560. if(segObj.attributes.hasClosures === true)
  4561. {
  4562. var hasFwd = false;
  4563. var hasRev = false;
  4564. var rcObj;
  4565. var roadClosure;
  4566. for(roadClosure in W.model.roadClosures.objects)
  4567. {
  4568. if(W.model.roadClosures.objects.hasOwnProperty(roadClosure))
  4569. {
  4570. rcObj = W.model.roadClosures.objects[roadClosure];
  4571. if(rcObj.segID == segObj.attributes.id)
  4572. {
  4573. if(rcObj.forward === true)
  4574. {
  4575. if(hasFwd === false)
  4576. {
  4577. result += '<tr><td colspan=3><b>A-B closures:</b></td></tr>';
  4578. hasFwd = true;
  4579. }
  4580.  
  4581. if(rcObj.active === true)
  4582. {
  4583. result += '<tr>';
  4584. }
  4585. else
  4586. {
  4587. result += '<tr bgcolor="#C0C0C0">';
  4588. }
  4589.  
  4590. var startDate = rcObj.startDate;
  4591. var endDate = "unknown";
  4592. if(rcObj.endDate !== null)
  4593. {
  4594. endDate = rcObj.endDate;
  4595. }
  4596. var provider = "---";
  4597. if(rcObj.provider !== null)
  4598. {
  4599. provider = rcObj.provider;
  4600. }
  4601. var reason = "---";
  4602. if(rcObj.reason !== null)
  4603. {
  4604. reason = rcObj.reason;
  4605. }
  4606. result += '<td>' + startDate + ' to ' + endDate + '</td>';
  4607. result += '<td>' + provider + '</td>';
  4608. result += '<td>' + reason + '</td>';
  4609. result += '</td></tr>';
  4610. }
  4611. else
  4612. {
  4613. hasRev = true;
  4614. }
  4615. }
  4616. }
  4617. }
  4618. if(hasRev === true)
  4619. {
  4620. result += '<tr><td colspan=3><b>B-A closures:</b></td></tr>';
  4621. for(roadClosure in W.model.roadClosures.objects)
  4622. {
  4623. if(W.model.roadClosures.objects.hasOwnProperty(roadClosure))
  4624. {
  4625. rcObj = W.model.roadClosures.objects[roadClosure];
  4626. if(rcObj.segID == segObj.attributes.id)
  4627. {
  4628. if(rcObj.forward === false)
  4629. {
  4630. if(rcObj.active === true)
  4631. {
  4632. result += '<tr>';
  4633. }
  4634. else
  4635. {
  4636. result += '<tr bgcolor="#C0C0C0">';
  4637. }
  4638.  
  4639. result += '<td>' + rcObj.startDate + ' to ' + rcObj.endDate + '</td>';
  4640. result += '<td>' + rcObj.provider + '</td>';
  4641. result += '<td>' + rcObj.reason + '</td>';
  4642. result += '</td></tr>';
  4643. }
  4644. }
  4645. }
  4646. }
  4647. }
  4648. if((hasFwd === true) || (hasRev === true))
  4649. {
  4650. doPopUp = true;
  4651. }
  4652. }
  4653. result += '</table>';
  4654. }
  4655.  
  4656. if(doPopUp === true)
  4657. {
  4658. if(segObj.attributes.id === null) uroFID = segObj.id;
  4659. else uroFID = segObj.attributes.id;
  4660. newPopupType = 'segment_restriction';
  4661. }
  4662. break;
  4663. }
  4664. }
  4665. }
  4666.  
  4667. // popup for restricted turns
  4668. if(newPopupType === null)
  4669. {
  4670. if(uroGetCBChecked('_cbInhibitTurnsPopup') === false)
  4671. {
  4672. var turnMarkerCount = W.map.layers[uroTurnsLayerIdx].markers.length;
  4673. if(turnMarkerCount > 0)
  4674. {
  4675. for(idx=0; idx<turnMarkerCount; idx++)
  4676. {
  4677. markerObj = W.map.layers[uroTurnsLayerIdx].markers[idx];
  4678. var arrowElm = markerObj.icon.imageDiv.childNodes[0];
  4679. markerImg = window.getComputedStyle(arrowElm).getPropertyValue("background-image");
  4680. markerPos = window.getComputedStyle(arrowElm).getPropertyValue("background-position");
  4681. markerPos = markerPos.split(' ');
  4682. markerPos = parseInt(markerPos[1].substr(0,markerPos[1].length-2));
  4683.  
  4684. hovered = false;
  4685.  
  4686. if(markerImg.indexOf('turns-sa7bd56a5e6.png') != -1)
  4687. {
  4688. if(markerPos == -222)
  4689. {
  4690. hovered = true;
  4691. }
  4692. }
  4693. if(hovered === true)
  4694. {
  4695. uroAddLog('hover over restricted turn marker');
  4696. uroTBRObj = arrowElm.childNodes[0];
  4697. var trObj = ($(arrowElm).data('model'));
  4698. var resObj = null;
  4699. if(trObj.fromSeg.attributes.fromRestrictions !== undefined)
  4700. {
  4701. resObj = trObj.fromSeg.attributes.fromRestrictions[trObj.toSeg.attributes.id];
  4702. }
  4703. if(resObj === null)
  4704. {
  4705. if(trObj.fromSeg.attributes.toRestrictions !== undefined)
  4706. {
  4707. resObj = trObj.fromSeg.attributes.toRestrictions[trObj.toSeg.attributes.id];
  4708. }
  4709. }
  4710.  
  4711. result += '<label id="_editTBR">Click to edit</label><br>';
  4712. result += '<table cellpadding=4 border=1">';
  4713. for(var resIdx=0; resIdx < resObj.length; resIdx++)
  4714. {
  4715. result += uroFormatRestriction(resObj[resIdx]);
  4716. }
  4717. result += '</table>';
  4718. uroFID = markerObj.icon.imageDiv._eventCacheID;
  4719. newPopupType = 'turn_restriction';
  4720. break;
  4721. }
  4722. }
  4723. }
  4724. }
  4725. }
  4726.  
  4727. var targetTab = '';
  4728. // popup for landmarks
  4729. if((newPopupType === null) && (uroGetCBChecked('_cbInhibitLandmarkPopup') === false))
  4730. {
  4731. uroPlaceSelected = false;
  4732. for(var llFeatureIdx=0; llFeatureIdx < W.map.landmarkLayer.features.length; llFeatureIdx++)
  4733. {
  4734. var renderIntent = W.map.landmarkLayer.features[llFeatureIdx].renderIntent;
  4735. if(renderIntent == 'highlight')
  4736. {
  4737. var venueObj;
  4738. if(W.map.landmarkLayer.features[llFeatureIdx].fid === null) venueObj = W.map.landmarkLayer.features[llFeatureIdx].model;
  4739. else venueObj = W.map.landmarkLayer.features[llFeatureIdx];
  4740.  
  4741. if(venueObj.attributes.id === null) uroFID = venueObj.id;
  4742. else uroFID = venueObj.attributes.id;
  4743.  
  4744. var navpointPos=new OpenLayers.LonLat();
  4745. navpointPos = uroGetVenueNavPoint(uroFID);
  4746. navpointPos.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326"));
  4747.  
  4748. result += '<b>';
  4749. if(venueObj.attributes.name === '') result += 'Unnamed landmark';
  4750. else result += venueObj.attributes.name;
  4751. result += '</b><br>';
  4752.  
  4753. result += '<ul>';
  4754. for(idx = 0; idx < venueObj.attributes.categories.length; idx++)
  4755. {
  4756. result += '<li>' + I18n.lookup("venues.categories")[venueObj.attributes.categories[idx]];
  4757. }
  4758. result += '</ul>';
  4759.  
  4760. if(venueObj.attributes.residential === true)
  4761. {
  4762. result += '<i>Residential</i>';
  4763. }
  4764.  
  4765. var npLink = document.location.href;
  4766. var npLayers = '&layers='+W.map.mapState.getLayerVisibilityBitmask();
  4767. npLink = npLink.substr(0,npLink.indexOf('?zoom'));
  4768. npLink += '?zoom=5&lat='+navpointPos.lat+'&lon='+navpointPos.lon+npLayers;
  4769.  
  4770. targetTab = "_uroTab_" + Math.round(Math.random()*1000000);
  4771. result += '<hr>Jump to nav point: <a href="'+npLink+'" id="_openInNewTab" target="'+targetTab+'">in new tab</a> - ';
  4772. objHasOpenInNewTabLink = true;
  4773. result += '<a href="#" id="_recentreSession">in this tab</a>';
  4774. objHasRecentreSessionLink = true;
  4775.  
  4776. newPopupType = 'venue';
  4777. isVenue = true;
  4778. break;
  4779. }
  4780. else if((renderIntent == 'select') || (renderIntent == 'highlightselected'))
  4781. {
  4782. uroPlaceSelected = true;
  4783. }
  4784. }
  4785. }
  4786.  
  4787. var unstackedX;
  4788. var unstackedY;
  4789. var ureqID = null;
  4790. var isUR = false;
  4791. var isProblem = false;
  4792. var isTurnProb = false;
  4793. var isPlaceUpdate = false;
  4794. // look for URs, place updates and problems
  4795. if(newPopupType === null)
  4796. {
  4797. var customIdx;
  4798. var idSrc = null;
  4799. if(uroGetCBChecked('_cbInhibitURPopup') === false)
  4800. {
  4801. hovered = false;
  4802. for(var markerURL in W.map.updateRequestLayer.markers)
  4803. {
  4804. if(W.map.updateRequestLayer.markers.hasOwnProperty(markerURL))
  4805. {
  4806. markerObj = W.map.updateRequestLayer.markers[markerURL];
  4807. markerImg = markerObj.icon.$div.css('background-image');
  4808. markerPos = markerObj.icon.$div.css('background-position');
  4809. markerPos = markerPos.split(' ');
  4810. markerPos = parseInt(markerPos[1].substr(0,markerPos[1].length-2));
  4811. var urIDSrc = markerObj.id;
  4812. if(markerImg.indexOf('problems-s8f369ca968.png') != -1)
  4813. {
  4814. if((markerPos == -403) || (markerPos == -483) || (markerPos == -563) || (markerPos == -643))
  4815. {
  4816. hovered = true;
  4817. uroAddLog('UR image type 1');
  4818. }
  4819. }
  4820. else if(markerImg.indexOf('problems-se224ab677e.png') != -1)
  4821. {
  4822. if((markerPos == -40) || (markerPos == -160) || (markerPos == -200) || (markerPos == -240))
  4823. {
  4824. hovered = true;
  4825. uroAddLog('UR image type 2');
  4826. }
  4827. }
  4828. else
  4829. {
  4830. if(markerPos > -200)
  4831. {
  4832. hovered = true;
  4833. uroAddLog('UR image type 3');
  4834. }
  4835. }
  4836. if(hovered === true)
  4837. {
  4838. isUR = true;
  4839. newPopupType = 'ur';
  4840. uroAddLog('hover over UR ID '+urIDSrc);
  4841.  
  4842. unstackedX = uroParsePxString(W.map.updateRequestLayer.markers[urIDSrc].icon.imageDiv.style.left);
  4843. unstackedY = uroParsePxString(W.map.updateRequestLayer.markers[urIDSrc].icon.imageDiv.style.top);
  4844.  
  4845. // override popup base position
  4846. uroPopupX = unstackedX + popupXOffset + 6;
  4847. uroPopupY = unstackedY + popupYOffset + 46;
  4848. uroPopupX -= uroParsePxString(W.map.segmentLayer.div.style.left);
  4849. uroPopupY -= uroParsePxString(W.map.segmentLayer.div.style.top);
  4850.  
  4851. // check for stacking...
  4852. if(uroShownFID != idSrc)
  4853. {
  4854. uroCheckStacking(1,urIDSrc, unstackedX, unstackedY);
  4855. }
  4856.  
  4857. if(urIDSrc != uroCustomMarkerFID)
  4858. {
  4859. if(uroCustomMarkerFID !== null)
  4860. {
  4861. customIdx = uroGetCustomMarkerIdx(uroGetCustomType(uroCustomMarkerFID, uroCustomMarkerType));
  4862. uroChangeCustomMarkers(uroCustomMarkerFID,false,customIdx,uroCustomMarkerType);
  4863. uroCustomMarkerFID = null;
  4864. }
  4865. customIdx = uroGetCustomMarkerIdx(uroGetCustomType(urIDSrc, "ur"));
  4866. if(customIdx != -1)
  4867. {
  4868. uroCustomMarkerFID = urIDSrc;
  4869. uroCustomMarkerType = "ur";
  4870. uroChangeCustomMarkers(urIDSrc,hovered,customIdx,uroCustomMarkerType);
  4871. }
  4872. }
  4873. idSrc = urIDSrc;
  4874. break;
  4875. }
  4876. }
  4877. }
  4878. if((hovered === false) && (uroStackType == 1))
  4879. {
  4880. uroRestackMarkers();
  4881. uroFilterURs();
  4882. }
  4883.  
  4884. if((idSrc === null) && (uroCustomMarkerFID !== null))
  4885. {
  4886. customIdx = uroGetCustomMarkerIdx(uroGetCustomType(uroCustomMarkerFID, uroCustomMarkerType));
  4887. uroChangeCustomMarkers(uroCustomMarkerFID,false, customIdx,uroCustomMarkerType);
  4888. uroCustomMarkerFID = null;
  4889. uroCustomMarkerType = null;
  4890. }
  4891. }
  4892.  
  4893. if((newPopupType === null) && (uroGetCBChecked('_cbInhibitPUPopup') === false))
  4894. {
  4895. hovered = false;
  4896. for(var markerPUL in W.map.placeUpdatesLayer.markers)
  4897. {
  4898. if(W.map.placeUpdatesLayer.markers.hasOwnProperty(markerPUL))
  4899. {
  4900. markerObj = W.map.placeUpdatesLayer.markers[markerPUL];
  4901. markerImg = markerObj.icon.$div.css('background-image');
  4902. markerPos = markerObj.icon.$div.css('background-position');
  4903. markerPos = markerPos.split(' ');
  4904. markerPos = parseInt(markerPos[1].substr(0,markerPos[1].length-2));
  4905.  
  4906. if(markerImg.indexOf('placeUpdates-sb30471988c.png') != -1)
  4907. {
  4908. // absolute offsets: 0 = new place, -120 = flagged, -240 = new photo, -360 = updated details
  4909. // relative offsets: 0 = green, -40 = highlighted, -80 = default
  4910. if(((markerPos + 40) % 120) === 0)
  4911. {
  4912. hovered = true;
  4913. uroAddLog('PUR marker type 1');
  4914. }
  4915. }
  4916. else if(markerImg.indexOf('placeUpdates-s2e8d9c5ce4.png') != -1)
  4917. {
  4918. if
  4919. (
  4920. (markerObj.icon.$div.css("filter") == "brightness(110%)") ||
  4921. (markerObj.icon.$div.css("webkit-filter") == "brightness(1.1)")
  4922. )
  4923. {
  4924. hovered = true;
  4925. uroAddLog('PUR marker type 2');
  4926. }
  4927. }
  4928. if(hovered === true)
  4929. {
  4930. idSrc = markerObj.id;
  4931. unstackedX = uroParsePxString(W.map.placeUpdatesLayer.markers[idSrc].icon.imageDiv.style.left);
  4932. unstackedY = uroParsePxString(W.map.placeUpdatesLayer.markers[idSrc].icon.imageDiv.style.top);
  4933.  
  4934. // override popup base position
  4935. uroPopupX = unstackedX + popupXOffset + 6;
  4936. uroPopupY = unstackedY + popupYOffset + 46;
  4937. uroPopupX -= uroParsePxString(W.map.segmentLayer.div.style.left);
  4938. uroPopupY -= uroParsePxString(W.map.segmentLayer.div.style.top);
  4939.  
  4940. if(uroShownFID != idSrc)
  4941. {
  4942. // check for stacking...
  4943. uroCheckStacking(3,idSrc, unstackedX, unstackedY);
  4944. }
  4945.  
  4946. isPlaceUpdate = true;
  4947. newPopupType = 'pur';
  4948. uroAddLog('hover over placeUpdate ID '+idSrc);
  4949. break;
  4950. }
  4951. }
  4952. }
  4953. if((hovered === false) && (uroStackType == 3))
  4954. {
  4955. uroRestackMarkers();
  4956. uroFilterPlaces();
  4957. }
  4958. }
  4959.  
  4960. if((newPopupType === null) && (uroGetCBChecked('_cbInhibitMPPopup') === false))
  4961. {
  4962. hovered = false;
  4963. for(var markerPL in W.map.problemLayer.markers)
  4964. {
  4965. if(W.map.problemLayer.markers.hasOwnProperty(markerPL))
  4966. {
  4967. markerObj = W.map.problemLayer.markers[markerPL];
  4968. markerImg = markerObj.icon.$div.css('background-image');
  4969. markerPos = markerObj.icon.$div.css('background-position');
  4970. markerPos = markerPos.split(' ');
  4971. markerPos = parseInt(markerPos[1].substr(0,markerPos[1].length-2));
  4972.  
  4973. if(markerImg.indexOf('problems-s8f369ca968.png') != -1)
  4974. {
  4975. if((markerPos == -65) || (markerPos == -145) || (markerPos == -225) || (markerPos == -305))
  4976. {
  4977. hovered = true;
  4978. uroAddLog('Problem image type 1');
  4979. }
  4980. }
  4981. else if(markerImg.indexOf('problems-se224ab677e.png') != -1)
  4982. {
  4983. if((markerPos == -320) || (markerPos == -560) || (markerPos == -520) || (markerPos == -440))
  4984. {
  4985. hovered = true;
  4986. uroAddLog('Problem image type 2');
  4987. }
  4988. }
  4989. else
  4990. {
  4991. if(markerPos > -200)
  4992. {
  4993. hovered = true;
  4994. uroAddLog('Problem image type 3');
  4995. }
  4996. }
  4997. if(hovered === true)
  4998. {
  4999. idSrc = null;
  5000. if(markerObj.model.fid === null) idSrc = markerObj.id;
  5001. else idSrc = markerObj.model.fid;
  5002.  
  5003. unstackedX = uroParsePxString(W.map.problemLayer.markers[idSrc].icon.imageDiv.style.left);
  5004. unstackedY = uroParsePxString(W.map.problemLayer.markers[idSrc].icon.imageDiv.style.top);
  5005.  
  5006. // override popup base position
  5007. uroPopupX = unstackedX + popupXOffset + 6;
  5008. uroPopupY = unstackedY + popupYOffset + 46;
  5009. uroPopupX -= uroParsePxString(W.map.segmentLayer.div.style.left);
  5010. uroPopupY -= uroParsePxString(W.map.segmentLayer.div.style.top);
  5011.  
  5012. // check for stacking...
  5013. if(uroShownFID != idSrc)
  5014. {
  5015. uroCheckStacking(2,idSrc, unstackedX, unstackedY);
  5016. }
  5017.  
  5018. if(idSrc != uroCustomMarkerFID)
  5019. {
  5020. if(uroCustomMarkerFID !== null)
  5021. {
  5022. customIdx = uroGetCustomMarkerIdx(uroGetCustomType(uroCustomMarkerFID, uroCustomMarkerType));
  5023. uroChangeCustomMarkers(uroCustomMarkerFID,false,customIdx,uroCustomMarkerType);
  5024. uroCustomMarkerFID = null;
  5025. uroCustomMarkerType = null;
  5026. }
  5027. customIdx = uroGetCustomMarkerIdx(uroGetCustomType(idSrc, "mp"));
  5028. if(customIdx != -1)
  5029. {
  5030. uroCustomMarkerFID = idSrc;
  5031. uroCustomMarkerType = "mp";
  5032. uroChangeCustomMarkers(idSrc,hovered,customIdx,uroCustomMarkerType);
  5033. }
  5034. }
  5035.  
  5036.  
  5037. isProblem = true;
  5038. newPopupType = 'map_problem';
  5039. uroAddLog('hover over problem ID '+idSrc);
  5040.  
  5041. break;
  5042. }
  5043. }
  5044. }
  5045. if((hovered === false) && (uroStackType == 2))
  5046. {
  5047. uroRestackMarkers();
  5048. uroFilterProblems();
  5049. }
  5050. if((idSrc === null) && (uroCustomMarkerFID !== null))
  5051. {
  5052. var newCustomIdx = uroGetCustomMarkerIdx(uroGetCustomType(uroCustomMarkerFID, uroCustomMarkerType));
  5053. uroChangeCustomMarkers(uroCustomMarkerFID, false, newCustomIdx, uroCustomMarkerType);
  5054. uroCustomMarkerFID = null;
  5055. uroCustomMarkerType = null;
  5056. }
  5057. }
  5058.  
  5059. if (idSrc !== null)
  5060. {
  5061. ureq = null;
  5062. if(isUR) ureq = W.model.mapUpdateRequests.objects[idSrc];
  5063. else if(isProblem)
  5064. {
  5065. ureq = W.model.problems.objects[idSrc];
  5066. if(ureq === undefined)
  5067. {
  5068. if(uroDOMHasTurnProblems)
  5069. {
  5070. ureq = W.model.turnProblems.objects[idSrc];
  5071. if(ureq !== undefined) isTurnProb = true;
  5072. }
  5073. }
  5074. }
  5075. else if(isPlaceUpdate) ureq = W.map.placeUpdatesLayer.markers[idSrc].model;
  5076.  
  5077. if(ureq.fid !== null) ureqID = ureq.fid;
  5078. else if(ureq.id !== null) ureqID = ureq.id;
  5079. else if(ureq.attributes.id !== null) ureqID = ureq.attributes.id;
  5080.  
  5081. uroFID = ureqID;
  5082. }
  5083. else
  5084. {
  5085. uroFID = -1;
  5086. }
  5087.  
  5088. //if((uroFID != uroShownFID) && (uroFID != -1))
  5089. if(uroFID != -1)
  5090. {
  5091. var uroDaysResolved;
  5092. if(isUR)
  5093. {
  5094. uroAddLog('building popup for UR '+idSrc);
  5095. result = '<b>Update Request ('+idSrc+'): ' + I18n.lookup("update_requests.types")[ureq.attributes.type] + '</b><br>';
  5096. if(ureq.attributes.description !== null)
  5097. {
  5098. var desc = ureq.attributes.description.replace(/<\/?[^>]+(>|$)/g, "");
  5099. if(desc != "null")
  5100. {
  5101. desc = uroClickify(desc);
  5102. result += desc + '<br>';
  5103. }
  5104. }
  5105. var uroDaysOld = uroGetURAge(ureq,0,false);
  5106. var uroSubmittedTS = uroGetURAge(ureq,0,true);
  5107. if(uroSubmittedTS != -1)
  5108. {
  5109. uroSubmittedTS = uroGetDateTimeString(uroSubmittedTS);
  5110. }
  5111. if(uroDaysOld != -1)
  5112. {
  5113. result += '<i>Submitted ' + uroParseDaysAgo(uroDaysOld) + ' ';
  5114. if(uroSubmittedTS != -1) result += '(' + uroSubmittedTS + ') ';
  5115. if(ureq.attributes.guestUserName !== undefined)
  5116. {
  5117. result += 'via Livemap';
  5118. if(ureq.attributes.guestUserName !== '')
  5119. {
  5120. result += ' by '+ureq.attributes.guestUserName.replace(/<\/?[^>]+(>|$)/g, "");
  5121. }
  5122. }
  5123. result += '</i>';
  5124. }
  5125. if(ureq.attributes.resolvedOn !== null)
  5126. {
  5127. uroDaysResolved = uroGetURAge(ureq,1,false);
  5128. var uroResolvedTS = uroGetURAge(ureq,1,true);
  5129. if(uroResolvedTS != -1)
  5130. {
  5131. uroResolvedTS = uroGetDateTimeString(uroResolvedTS);
  5132. }
  5133.  
  5134. if(uroDaysResolved != -1)
  5135. {
  5136. result += '<br><i>Closed ' + uroParseDaysAgo(uroDaysResolved) + ' ';
  5137. if(uroResolvedTS != -1) result += '(' + uroResolvedTS + ')</i>';
  5138.  
  5139. result += '<br><i>Marked as ';
  5140. if(ureq.attributes.resolution === 0) result += 'solved';
  5141. else if(ureq.attributes.resolution == 1) result += 'not identified';
  5142. else result += 'unknown';
  5143. if(ureq.attributes.resolvedBy !== null)
  5144. {
  5145. result += ' by '+uroGetUserNameAndRank(ureq.attributes.resolvedBy);
  5146. }
  5147. result += '</i>';
  5148. }
  5149. }
  5150. if(W.model.updateRequestSessions.objects[ureqID] !== undefined)
  5151. {
  5152. var hasMyComments = uroURHasMyComments(ureqID);
  5153. var nComments = W.model.updateRequestSessions.objects[ureqID].comments.length;
  5154. result += '<br>' + nComments + ' comment';
  5155. if(nComments != 1) result += 's';
  5156. if((hasMyComments === false) && (nComments > 0)) result += ' (none by me)';
  5157. if(nComments > 0)
  5158. {
  5159. var commentDaysOld = uroGetCommentAge(W.model.updateRequestSessions.objects[ureqID].comments[nComments-1]);
  5160. if(commentDaysOld != -1)
  5161. {
  5162. result += ', last update '+uroParseDaysAgo(commentDaysOld);
  5163. }
  5164. }
  5165. }
  5166. }
  5167. else if(isProblem)
  5168. {
  5169. uroAddLog('building popup for problem '+idSrc);
  5170. if(isTurnProb) result = '<b>Turn Problem ('+idSrc+'): ' + I18n.lookup("problems.types").turn.title;
  5171. else
  5172. {
  5173. result = '<b>Map Problem ('+idSrc+'): ';
  5174.  
  5175. var problemType = null;
  5176. if(uroDOMHasTurnProblems)
  5177. {
  5178. problemType = ureq.attributes.problemType;
  5179. }
  5180. else
  5181. {
  5182. problemType = ureq.attributes.subType;
  5183. }
  5184.  
  5185. if(problemType == 300)
  5186. {
  5187. result += I18n.lookup("problems.panel.closure.title");
  5188. }
  5189. else
  5190. {
  5191. if(I18n.lookup("problems.types")[problemType] === undefined) result += 'Unknown problem type ('+problemType+')';
  5192. else result += I18n.lookup("problems.types")[problemType].title;
  5193. }
  5194. }
  5195. result += '</b><br>';
  5196. if(ureq.attributes.description !== null)
  5197. {
  5198. result += 'Description: ' + ureq.attributes.description + '<br>';
  5199. }
  5200. if(ureq.attributes.extraInfo !== null)
  5201. {
  5202. result += 'ExtraInfo: ' + ureq.attributes.extraInfo + '<br>';
  5203. }
  5204. if(ureq.attributes.provider !== null)
  5205. {
  5206. result += 'Provider: ' + ureq.attributes.provider + '<br>';
  5207. }
  5208. if(ureq.attributes.resolvedOn !== null)
  5209. {
  5210. uroDaysResolved = uroGetURAge(ureq,1,false);
  5211. if(uroDaysResolved != -1)
  5212. {
  5213. result += '<br><i>Closed ' + uroParseDaysAgo(uroDaysResolved) + ' ';
  5214. if(ureq.attributes.resolvedBy !== null)
  5215. {
  5216. result += ' by '+uroGetUserNameAndRank(ureq.attributes.resolvedBy);
  5217. }
  5218.  
  5219. if((ureq.attributes.open === true) && (ureq.attributes.resolvedOn !== null))
  5220. {
  5221. result += '<br>Reopened by Waze';
  5222. }
  5223. result += '</i>';
  5224. }
  5225. }
  5226. }
  5227. else if(isPlaceUpdate)
  5228. {
  5229. uroAddLog('building popup for placeUpdate '+idSrc);
  5230. result = '<b>';
  5231. if(ureq.attributes.name === '') result += 'Unnamed landmark';
  5232. else result += ureq.attributes.name;
  5233. result += '</b><br>';
  5234.  
  5235. result += '<ul>';
  5236. for(idx = 0; idx < ureq.attributes.categories.length; idx++)
  5237. {
  5238. result += '<li>' + I18n.lookup("venues.categories")[ureq.attributes.categories[idx]];
  5239. }
  5240. result += '</ul>';
  5241.  
  5242. if(ureq.attributes.residential === true)
  5243. {
  5244. result += '<i>Residential</i>';
  5245. }
  5246.  
  5247. var daysOld = uroGetPURAge(ureq);
  5248. if(daysOld != -1)
  5249. {
  5250. result += '<br><i>Submitted '+uroParseDaysAgo(daysOld)+'</i>';
  5251. }
  5252. }
  5253.  
  5254. // add "open new WME tab" link
  5255. var urPos=new OpenLayers.LonLat();
  5256. if(isPlaceUpdate)
  5257. {
  5258. urPos=ureq.geometry.bounds.centerLonLat.clone();
  5259. }
  5260. else
  5261. {
  5262. urPos.lon=ureq.geometry.x;
  5263. urPos.lat=ureq.geometry.y;
  5264. }
  5265. urPos.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326"));
  5266. var urLink = document.location.href;
  5267. var urLayers = '&layers='+W.map.mapState.getLayerVisibilityBitmask();
  5268. urLink = urLink.substr(0,urLink.indexOf('?zoom'));
  5269. urLink += '?zoom=5&lat='+urPos.lat+'&lon='+urPos.lon+urLayers;
  5270.  
  5271. if(isUR) urLink += '&mapUpdateRequest='+idSrc;
  5272. else if(isTurnProb) urLink += '&showturn='+idSrc+'&endshow';
  5273. else if(isProblem) urLink += '&mapProblem='+idSrc;
  5274. else if(isPlaceUpdate) urLink += '&showpur='+idSrc+'&endshow';
  5275.  
  5276. targetTab = "_uroTab_" + Math.round(Math.random()*1000000);
  5277. result += '<hr><ul><li><a href="'+urLink+'" id="_openInNewTab" target="'+targetTab+'">Open in new tab</a> - ';
  5278. objHasOpenInNewTabLink = true;
  5279. result += '<a href="#" id="_recentreSession">centre in current tab</a>';
  5280. objHasRecentreSessionLink = true;
  5281.  
  5282. // add "open new livemap tab" link
  5283. var lmLink = null;
  5284. if(document.getElementsByClassName("waze-header-menu").length === 0)
  5285. {
  5286. uroAddLog('Livemap link in livemap element');
  5287. lmLink = document.getElementById('livemap').href;
  5288. }
  5289. else
  5290. {
  5291. uroAddLog('Livemap link in header menu, locating...');
  5292. var menuItems = document.getElementsByClassName("waze-header-menu")[0];
  5293. for(var miloop = 0; miloop<menuItems.childElementCount; miloop++)
  5294. {
  5295. if(menuItems.children[miloop].innerHTML.indexOf('livemap') != -1)
  5296. {
  5297. uroAddLog('found link in menu entry '+miloop);
  5298. lmLink = menuItems.children[miloop].getElementsByTagName('a')[0].href;
  5299. uroAddLog(lmLink);
  5300. }
  5301. }
  5302. }
  5303. if(lmLink !== null)
  5304. {
  5305. var zpos = lmLink.indexOf('?');
  5306. if(zpos > -1) lmLink = lmLink.substr(0,zpos);
  5307. lmLink += '?zoom=17&lat='+urPos.lat+'&lon='+urPos.lon+'&layers=BTTTT';
  5308. result += '<li><a href="'+lmLink+'" target="_lmTab">Open in new livemap tab</a>';
  5309. }
  5310.  
  5311. if(!isPlaceUpdate)
  5312. {
  5313. // add "ignore for this session" link
  5314. result += '<li><a href="#" id="_addtoignore">Hide for this session</a></ul>';
  5315. objHasIgnoreLink = true;
  5316. }
  5317. }
  5318. }
  5319.  
  5320. // look for cameras
  5321. if((newPopupType === null) && (uroGetCBChecked('_cbInhibitCamPopup') === false))
  5322. {
  5323. for(var clFeatureIdx = 0; clFeatureIdx < W.map.camerasLayer.features.length; clFeatureIdx++)
  5324. {
  5325. if(W.map.camerasLayer.features[clFeatureIdx].renderIntent == 'highlight')
  5326. {
  5327. if(W.map.camerasLayer.features[clFeatureIdx].fid === null) ureq = W.map.camerasLayer.features[clFeatureIdx].model;
  5328. else ureq = W.map.camerasLayer.features[clFeatureIdx];
  5329.  
  5330. if(ureq.fid === null) ureqID = ureq.attributes.id;
  5331. else ureqID = ureq.fid;
  5332.  
  5333. // test isSelected() so that we only do overview data on cameras that are being hovered over
  5334. if(ureq.isSelected() === false)
  5335. {
  5336. newPopupType = 'camera';
  5337. uroFID = ureqID;
  5338. uroAddLog('generating popup for camera '+uroFID);
  5339. if(I18n.lookup("edit.camera.fields.type") === undefined)
  5340. {
  5341. result += '<b>Camera: ' + ureq.TYPES[ureq.attributes.type] + '</b><br>';
  5342. }
  5343. else
  5344. {
  5345. result += '<b>Camera: ' + I18n.lookup("edit.camera.fields.type")[ureq.attributes.type] + '</b><br>';
  5346. }
  5347. result += 'ID: '+uroFID+'<br>';
  5348. result += 'Created by ';
  5349. var userID;
  5350. if(W.model.users.get(ureq.attributes.createdBy) !== undefined)
  5351. {
  5352. userID = ureq.attributes.createdBy;
  5353. result += uroGetUserNameAndRank(userID);
  5354. }
  5355. else result += 'unknown';
  5356. result += ', ';
  5357. var camAge = uroGetCameraAge(ureq,1);
  5358. if(camAge != -1)
  5359. {
  5360. result += uroParseDaysAgo(camAge);
  5361. }
  5362. else result += 'unknown days ago';
  5363. result += '<br>Updated by ';
  5364. if(W.model.users.get(ureq.attributes.updatedBy) !== undefined)
  5365. {
  5366. userID = ureq.attributes.updatedBy;
  5367. var userName = W.model.users.objects[userID].userName;
  5368. var userLevel = W.model.users.objects[userID].rank + 1;
  5369. result += userName + ' (' + userLevel + ')';
  5370. }
  5371. else result += 'unknown';
  5372. result += ', ';
  5373. camAge = uroGetCameraAge(ureq,0);
  5374. if(camAge != -1)
  5375. {
  5376. result += uroParseDaysAgo(camAge);
  5377. }
  5378. else result += 'unknown days ago';
  5379. result += '<br>Speed data: ';
  5380. result += uroGetCameraSpeedString(ureq.attributes.speed);
  5381. result += '<hr><ul>';
  5382. if(uroIsCamOnWatchList(uroFID) != -1)
  5383. {
  5384. result += '<li><a href="#" id="_updatewatchlist">Update watchlist entry</a>';
  5385. result += '<li><a href="#" id="_removefromwatchlist">Remove from watchlist</a>';
  5386. objHasUpdateWatchLink = true;
  5387. objHasRemoveWatchLink = true;
  5388. }
  5389. else
  5390. {
  5391. result += '<li><a href="#" id="_addtowatchlist">Add to watchlist</a>';
  5392. objHasAddWatchLink = true;
  5393. }
  5394. if(ureq.attributes.permissions !== 0)
  5395. {
  5396. result += '<li><a href="#" id="_deleteobject">Delete Camera</a>';
  5397. objHasDeleteLink = true;
  5398. }
  5399. result += '</ul>';
  5400. }
  5401. break;
  5402. }
  5403. }
  5404. }
  5405.  
  5406.  
  5407. if((newPopupType !== null) && (uroPopupDwellTimer === 0))
  5408. {
  5409. if((uroFID != uroShownFID) || (newPopupType != uroShownPopupType))
  5410. {
  5411. if(uroFID != uroShownFID) uroAddLog('FID mismatch, show popup: '+uroFID+'/'+uroShownFID);
  5412. else uroAddLog('Popup type mismatch: '+newPopupType+'/'+uroShownPopupType);
  5413. uroShownFID = uroFID;
  5414. uroShownPopupType = newPopupType;
  5415. uroPopupShown = false;
  5416. }
  5417.  
  5418. if(uroPopupShown === false)
  5419. {
  5420. uroAddLog('display popup at '+uroPopupX+','+uroPopupY);
  5421. uroPopupShown = true;
  5422. uroDiv.innerHTML = result;
  5423. if((uroFID != -1) && (objHasIgnoreLink === true))
  5424. {
  5425. uroAddEventListener('_addtoignore','click', uroAddToIgnoreList, true);
  5426. }
  5427. if(objHasDeleteLink === true)
  5428. {
  5429. uroAddEventListener('_deleteobject','click', uroDeleteObject, true);
  5430. }
  5431. if(objHasRemoveWatchLink === true)
  5432. {
  5433. uroAddEventListener('_removefromwatchlist','click', uroRemoveCamFromWatchList, true);
  5434. }
  5435. if(objHasAddWatchLink === true)
  5436. {
  5437. uroAddEventListener('_addtowatchlist','click', uroAddCamToWatchList, true);
  5438. }
  5439. if(objHasUpdateWatchLink === true)
  5440. {
  5441. uroAddEventListener('_updatewatchlist','click', uroUpdateCamWatchList, true);
  5442. }
  5443. if(objHasOpenInNewTabLink === true)
  5444. {
  5445. uroAddEventListener('_openInNewTab','mouseup', uroOpenNewTab, true);
  5446. }
  5447. if(objHasRecentreSessionLink === true)
  5448. {
  5449. if(isUR) uroAddEventListener('_recentreSession', 'click', uroRecentreSessionOnUR, true);
  5450. else if((isProblem)||(isTurnProb)) uroAddEventListener('_recentreSession', 'click', uroRecentreSessionOnMP, true);
  5451. else if(isPlaceUpdate) uroAddEventListener('_recentreSession', 'click', uroRecentreSessionOnPUR, true);
  5452. else if(isVenue) uroAddEventListener('_recentreSession', 'click', uroRecentreSessionOnVenueNavPoint, true);
  5453. }
  5454. if(newPopupType == 'turn_restriction')
  5455. {
  5456. uroAddEventListener('_editTBR','click', uroEditTBR, true);
  5457. }
  5458. rw = parseInt(uroDiv.clientWidth);
  5459. rh = parseInt(uroDiv.clientHeight);
  5460.  
  5461. if(rw > (window.innerWidth / 2)) rw = (window.innerWidth / 2);
  5462. if(rh > (window.innerHeight / 2)) rh = (window.innerHeight / 2);
  5463.  
  5464. if((uroPopupX + rw) > window.innerWidth)
  5465. {
  5466. // where the popup would be off the right hand side of the screen, move it completely over to the
  5467. // other side of the mouse pointer
  5468. uroPopupX -= (rw + 20);
  5469. if(uroPopupX < 0) uroPopupX = 0;
  5470. }
  5471. if((uroPopupY + rh) > window.innerHeight)
  5472. {
  5473. // where the popup would be off the bottom of the screen, shift it up just far enough to be
  5474. // fully visible
  5475. uroPopupY -= (((uroPopupY + rh) - window.innerHeight) + 10);
  5476. if(uroPopupY < 0) uroPopupY = 0;
  5477. }
  5478.  
  5479. uroDiv.style.top = uroPopupY+'px';
  5480. uroDiv.style.left = uroPopupX+'px';
  5481. uroDiv.clientWidth = rw+'px';
  5482. uroDiv.clientHeight = rh+'px';
  5483. uroDiv.style.visibility = 'visible';
  5484. }
  5485. uroPopupTimer = -1;
  5486. }
  5487. else if((newPopupType === null) && (uroPopupDwellTimer !== 0) && (uroPopupShown === true))
  5488. {
  5489. uroHidePopup();
  5490. }
  5491. else
  5492. {
  5493. if((uroPopupTimer == -1) && (uroFID != uroShownFID))
  5494. {
  5495. uroPopupTimer = uroGetElmValue('_inputPopupEntryTimeout');
  5496. }
  5497. }
  5498. }
  5499.  
  5500. function uroRestyleWMETabs()
  5501. {
  5502. var navTabs = document.getElementById(uroUserTabId).children[1].children;
  5503. for(var loop = 0; loop<navTabs.length; loop++)
  5504. {
  5505. navTabs[loop].children[0].style.padding = "4px";
  5506. }
  5507. setTimeout(uroRestyleWMETabs,1000);
  5508. }
  5509.  
  5510. function uroExclusiveCB()
  5511. {
  5512. var cbChecked = uroGetCBChecked(this.id);
  5513.  
  5514. if(cbChecked === true)
  5515. {
  5516. var pairedList = this.attributes.pairedWith.value.split(',');
  5517. for(var i=0; i<pairedList.length; i++)
  5518. {
  5519. uroSetCBChecked(pairedList[i], false);
  5520. }
  5521. }
  5522. }
  5523.  
  5524.  
  5525. function uroGetAMs(e)
  5526. {
  5527. var amList = '';
  5528. if(W.map.managedAreasLayer.getVisibility() === true)
  5529. {
  5530. var mouseX = e.pageX - document.getElementById('map').getBoundingClientRect().left;
  5531. var mouseY = e.pageY - document.getElementById('map').getBoundingClientRect().top - document.getElementById('toolbar').clientHeight;
  5532. var mousePixel = new OL.Pixel(mouseX, mouseY);
  5533. var mousePoint = W.map.getLonLatFromPixel(mousePixel).toPoint();
  5534.  
  5535. for(var amObj in W.model.managedAreas.objects)
  5536. {
  5537. if(W.model.managedAreas.objects[amObj].geometry.containsPoint(mousePoint))
  5538. {
  5539. if(amList !== '') amList += ', ';
  5540. amList += uroGetUserNameAndRank(W.model.managedAreas.objects[amObj].userID);
  5541. }
  5542. }
  5543. if(amList === '')
  5544. {
  5545. amList = 'none';
  5546. }
  5547. amList = "<b>Area Managers:</b> "+amList;
  5548. }
  5549. document.getElementById("uroAMList").innerHTML = amList;
  5550. }
  5551.  
  5552.  
  5553. function uroMouseDown()
  5554. {
  5555. uroMouseIsDown = true;
  5556. }
  5557.  
  5558. function uroMouseUp()
  5559. {
  5560. uroMouseIsDown = false;
  5561. }
  5562.  
  5563. function uroUREvent_onObjectsChanged()
  5564. {
  5565. }
  5566.  
  5567. function uroUREvent_onObjectsAdded()
  5568. {
  5569. if(uroGetCBChecked('_cbURResolverIDFilter') === true)
  5570. {
  5571. uroUpdateResolverList();
  5572. }
  5573. uroFilterURs();
  5574. }
  5575.  
  5576. function uroUREvent_onObjectsRemoved()
  5577. {
  5578. }
  5579.  
  5580. function uroGetSelectedURCommentCount()
  5581. {
  5582. if(W.model.updateRequestSessions.objects[uroSelectedURID] !== undefined)
  5583. {
  5584. var cachedCommentCount = W.model.updateRequestSessions.objects[uroSelectedURID].comments.length;
  5585. uroAddLog(uroSelectedURID+':'+cachedCommentCount+' '+uroExpectedCommentCount);
  5586.  
  5587. // if there aren't the same number of cached comments as there are comments in the UR dialog list, initiate
  5588. // a refresh of the comment data...
  5589. if(cachedCommentCount != uroExpectedCommentCount)
  5590. {
  5591. if(uroPendingCommentDataRefresh === true)
  5592. {
  5593. if(cachedCommentCount > 0)
  5594. {
  5595. uroCachedLastCommentID = W.model.updateRequestSessions.objects[uroSelectedURID].comments[cachedCommentCount-1].id;
  5596. }
  5597. else
  5598. {
  5599. uroCachedLastCommentID = null;
  5600. }
  5601. uroAddLog('updateRequestSessions refresh required for UR '+uroSelectedURID);
  5602. if(uroCachedLastCommentID !== null)
  5603. {
  5604. uroAddLog('last comment ID for this UR is '+uroCachedLastCommentID);
  5605. }
  5606. else
  5607. {
  5608. uroAddLog('first comment for this UR, no previous comment to ID');
  5609. }
  5610. var idList = [];
  5611. idList.push(uroSelectedURID);
  5612. // need to delete the existing cache object first, as .get() is only capable of creating new objects,
  5613. // it doesn't seem able to update an existing object with new data
  5614. W.model.updateRequestSessions.remove(W.model.updateRequestSessions.objects[uroSelectedURID]);
  5615. W.model.updateRequestSessions.get(idList);
  5616. // the call to .get() initiates a XMLHttpRequest for the data, so we now need to switch modes - the
  5617. // refresh process has started so we're no longer pending, but we are now waiting for the XMLHttpRequest
  5618. // to return something...
  5619. uroPendingCommentDataRefresh = false;
  5620. uroWaitingCommentDataRefresh = true;
  5621. }
  5622. else
  5623. {
  5624. if(cachedCommentCount > 0)
  5625. {
  5626. var currentLastCommentID = W.model.updateRequestSessions.objects[uroSelectedURID].comments[cachedCommentCount-1].id;
  5627. if(currentLastCommentID == uroCachedLastCommentID)
  5628. {
  5629. // most recent comment loaded for this UR is the same one that was present at the start of this
  5630. // refresh process, so kick back into pending mode so we can retry the .get()...
  5631. uroAddLog('latest comment ID still the same, reverting to pending mode...');
  5632. uroPendingCommentDataRefresh = true;
  5633. }
  5634. else
  5635. {
  5636. // something may have gone awry here - the most recent comment loaded for this UR doesn't have the
  5637. // same ID as the one present at the start of the refresh process, yet the comment counts still don't
  5638. // match up, which suggests either a comment got lost along the way or someone else has commented on
  5639. // the same UR at almost the same time. To get out of the loop this would create, assume that a
  5640. // mismatch in the IDs means the .get() has completed successfully no matter what the new comment
  5641. // count is, and take this new count to be the count we were expecting all along...
  5642. uroAddLog('latest comment ID different, but expected count not correct...');
  5643. uroExpectedCommentCount = cachedCommentCount;
  5644. }
  5645. }
  5646. else
  5647. {
  5648. uroAddLog('first comment on this UR not received yet, reverting to pending mode...');
  5649. uroPendingCommentDataRefresh = true;
  5650. }
  5651. }
  5652.  
  5653. }
  5654. else
  5655. {
  5656. // if the WME session is loaded with a UR already selected, such that WME has opened the UR dialog as part
  5657. // of the session startup process, adding new comments to the UR cause the cached data to be updated immediately.
  5658. // This prevents URO+ from switching into waiting mode in the above block of code, so we have to instead do
  5659. // it here by comparing the cached count against the expected count following the Send click event.
  5660. if(cachedCommentCount >= uroExpectedCommentCount)
  5661. {
  5662. uroPendingCommentDataRefresh = false;
  5663. uroWaitingCommentDataRefresh = true;
  5664. uroExpectedCommentCount = null;
  5665. }
  5666.  
  5667. // once the cached data has been updated, refilter the URs so that the new comment count is taken into account
  5668. // immediately for filtering and display purposes
  5669. if(uroWaitingCommentDataRefresh === true)
  5670. {
  5671. uroWaitingCommentDataRefresh = false;
  5672. uroFilterURs();
  5673. uroAddLog('refresh complete');
  5674. }
  5675. }
  5676. }
  5677. }
  5678.  
  5679. function uroAddedComment()
  5680. {
  5681. // when the user clicks the Send button to submit a new UR comment, this event handler fires before the new comment is
  5682. // posted to the server and thus also before the comment list gets updated in the UR dialog. So we take the current
  5683. // comment count and, if the new comment edit box isn't empty, increment it by 1 to get the expected count. Then we
  5684. // set the pending flag true to initiate a session refresh on the next 100ms tick
  5685. uroExpectedCommentCount = W.map.panelRegion.currentView.conversationView.conversation.comments.length;
  5686. if(document.getElementsByClassName('new-comment-text')[0].value !== '')
  5687. {
  5688. uroExpectedCommentCount++;
  5689. uroAddLog('new comment added to UR '+uroSelectedURID+', cache refresh required...');
  5690. uroPendingCommentDataRefresh = true;
  5691. }
  5692. else
  5693. {
  5694. uroPendingCommentDataRefresh = false;
  5695. }
  5696. }
  5697.  
  5698. function uroTenthSecondTick()
  5699. {
  5700. if(uroSetupListeners)
  5701. {
  5702. if((loginManager.isLoggedIn()) || (uroPracticeMode === true))
  5703. {
  5704. uroSetupListeners = false;
  5705.  
  5706. if(uroPracticeMode === true)
  5707. {
  5708. document.getElementsByClassName("sandbox")[0].style.display = "none";
  5709. }
  5710.  
  5711. // filter markers when the marker objects are modified (this happens whenever WME needs to load fresh marker data
  5712. // due to having panned/zoomed the map beyond the extents of the previously loaded data)
  5713. W.model.mapUpdateRequests.events.register("objectschanged", null, uroFilterURs_onObjectsChanged);
  5714. W.model.mapUpdateRequests.events.register("objectsadded", null, uroFilterURs_onObjectsAdded);
  5715. W.model.mapUpdateRequests.events.register("objectsremoved", null, uroFilterURs_onObjectsRemoved);
  5716.  
  5717. W.model.updateRequestSessions.events.register("objectschanged", null, uroUREvent_onObjectsChanged);
  5718. W.model.updateRequestSessions.events.register("objectsadded", null, uroUREvent_onObjectsAdded);
  5719. W.model.updateRequestSessions.events.register("objectsremoved", null, uroUREvent_onObjectsRemoved);
  5720.  
  5721. W.model.cameras.events.register("objectschanged", null, uroFilterCameras);
  5722. W.model.cameras.events.register("objectsadded", null, uroFilterCameras);
  5723. W.model.cameras.events.register("objectsremoved", null, uroFilterCameras);
  5724. W.model.problems.events.register("objectschanged", null, uroFilterProblems);
  5725. W.model.problems.events.register("objectsadded", null, uroFilterProblems);
  5726. W.model.problems.events.register("objectsremoved", null, uroFilterProblems);
  5727. W.model.venues.events.register("objectschanged", null, uroFilterPlaces);
  5728. W.model.venues.events.register("objectsadded", null, uroFilterPlaces);
  5729. W.model.venues.events.register("objectsremoved", null, uroFilterPlaces);
  5730.  
  5731. var userTabs = document.getElementById(uroUserTabId);
  5732. var tabContent = null;
  5733. if(uroPracticeMode === false)
  5734. {
  5735. var navTabs = uroTimbonesGetElementsByClassName('nav-tabs', userTabs)[0];
  5736. tabContent = uroTimbonesGetElementsByClassName('tab-content', userTabs)[0];
  5737. var newtabUR = document.createElement('li');
  5738. newtabUR.innerHTML = '<a href="#sidepanel-uroverview" data-toggle="tab">URO+</a>';
  5739. navTabs.appendChild(newtabUR);
  5740. }
  5741. uroControls.id = "sidepanel-uroverview";
  5742. uroControls.className = "tab-pane";
  5743. if(uroPracticeMode === false)
  5744. {
  5745. tabContent.appendChild(uroControls);
  5746. }
  5747. else
  5748. {
  5749. userTabs.appendChild(uroControls);
  5750. }
  5751.  
  5752. uroAddEventListener('_btnUndoLastHide',"click", uroRemoveLastAddedIgnore, true);
  5753. uroAddEventListener('_btnClearSessionHides',"click", uroRemoveAllIgnores, true);
  5754. uroEnableIgnoreListControls();
  5755.  
  5756. uroAddEventListener('_btnClearCamWatchList',"click", uroClearCamWatchList, true);
  5757. uroAddEventListener('_btnSettingsToText',"click", uroSettingsToText, true);
  5758. uroAddEventListener('_btnTextToSettings',"click", uroTextToSettings, true);
  5759. uroAddEventListener('_btnResetSettings',"click", uroDefaultSettings, true);
  5760. uroAddEventListener('_btnClearSettingsText',"click", uroClearSettingsText, true);
  5761. uroAddEventListener('_cbMasterEnable',"click", uroFilterItems_MasterEnableClick, true);
  5762.  
  5763. uroSetOnClick("_linkSelectUserRequests",uroShowURTab);
  5764. uroSetOnClick("_linkSelectMapProblems",uroShowMPTab);
  5765. uroSetOnClick("_linkSelectPlaces",uroShowPlacesTab);
  5766. uroSetOnClick("_linkSelectCameras",uroShowCameraTab);
  5767. uroSetOnClick("_linkSelectMisc",uroShowMiscTab);
  5768. uroSetOnClick("_linkSelectOWL",uroShowOWLTab);
  5769.  
  5770. for(var idx=0;idx<W.Config.venues.categories.length;idx++)
  5771. {
  5772. uroSetOnClick('_uroPlacesGroupState-'+idx,uroPlacesGroupCollapseExpand);
  5773. }
  5774.  
  5775. // add exclusiveCB click handlers to all checkboxes with a pairedWith attribute
  5776. var cbList = document.getElementsByTagName('input');
  5777. for (var optIdx=0;optIdx<cbList.length;optIdx++)
  5778. {
  5779. if((cbList[optIdx].id.indexOf('_cb') === 0) && (cbList[optIdx].attributes.pairedWith !== undefined))
  5780. {
  5781. uroSetOnClick(cbList[optIdx].id,uroExclusiveCB);
  5782. }
  5783. }
  5784.  
  5785. var dbgMode = "none";
  5786. if(uroShowDebugOutput)
  5787. {
  5788. dbgMode = "inline";
  5789. }
  5790. document.getElementById('_uroDebugMode').style.display = dbgMode;
  5791. uroAddEventListener('_uroVersion',"click", uroToggleDebug, true);
  5792.  
  5793. uroAddLog('finalise onload');
  5794. uroLoadSettings();
  5795. uroNewLookCheckDetailsRequest();
  5796.  
  5797. if(uroGetCBChecked('_cbEnableDTE'))
  5798. {
  5799. if(dteControlsIdx != -1)
  5800. {
  5801. dteSetNewTabLength();
  5802. }
  5803. else
  5804. {
  5805. uroAddLog('ERROR - archive panel not found!');
  5806. uroSetStyleDisplay(uroUserTabId,'');
  5807. }
  5808. }
  5809.  
  5810. if(uroBetaEditor === false)
  5811. {
  5812. if(uroGetCBChecked('_cbEnableSRS'))
  5813. {
  5814. selectionManager.events.register("selectionchanged", null, srsCheckSidePanel);
  5815. uroAddLog('added SRS event handler');
  5816. }
  5817. }
  5818.  
  5819. // filter markers as and when the map is moved
  5820. W.map.events.register("moveend", null, uroFilterItems);
  5821. W.map.events.register("mousemove", null, uroGetAMs);
  5822. W.map.events.register("mousemove", null, uroNewLookHighlightedItemsCheck);
  5823. W.map.events.registerPriority("mousedown", null, uroMouseDown);
  5824.  
  5825. // trap mousedown on Streetview marker drag
  5826. document.getElementsByClassName('street-view-control')[0].onmousedown = uroMouseDown;
  5827.  
  5828. W.map.events.register("mouseup", null, uroMouseUp);
  5829.  
  5830. uroSetStyles(uroCtrlURs);
  5831. uroSetStyles(uroCtrlMPs);
  5832. uroSetStyles(uroCtrlPlaces);
  5833. uroSetStyles(uroCtrlCameras);
  5834. uroSetStyles(uroCtrlMisc);
  5835. uroSetStyles(uroOWL);
  5836.  
  5837. uroShowURTab();
  5838. uroRestyleWMETabs();
  5839. uroUserID = loginManager.getLoggedInUser().id;
  5840. uroFilterItems();
  5841. }
  5842. }
  5843. else
  5844. {
  5845. var mousePos = document.getElementsByClassName('mouse-position')[0].innerHTML;
  5846.  
  5847. if(document.getElementsByClassName('panel')[0] === undefined)
  5848. {
  5849. uroHidePopupOnPanelOpen = true;
  5850. }
  5851.  
  5852. if(uroPopupShown === true)
  5853. {
  5854. var hidePopup = false;
  5855. if((mousePos == '00.00000, 00.00000') && (uroMouseInPopup === false))
  5856. {
  5857. hidePopup = true;
  5858. }
  5859. if(document.getElementsByClassName('panel')[0] !== undefined)
  5860. {
  5861. if(uroHidePopupOnPanelOpen === true)
  5862. {
  5863. hidePopup = true;
  5864. uroHidePopupOnPanelOpen = false;
  5865. }
  5866. }
  5867.  
  5868. if(hidePopup === true)
  5869. {
  5870. uroHidePopup();
  5871. }
  5872. }
  5873.  
  5874. if((uroAreaNameHoverObj !== null) && (uroAreaNameHoverTime != -1) && (uroAreaNameOverlayShown === false))
  5875. {
  5876. if(++uroAreaNameHoverTime > 5)
  5877. {
  5878. uroAreaNameOverlaySetup();
  5879. }
  5880. }
  5881. uroReplaceAreaNames(false);
  5882.  
  5883. if(uroPopupTimer > 0)
  5884. {
  5885. if(uroMouseInPopup === false)
  5886. {
  5887. uroPopupTimer--;
  5888. }
  5889. }
  5890. if(uroPopupTimer === 0)
  5891. {
  5892. uroHidePopup();
  5893. }
  5894.  
  5895. if(uroPopupDwellTimer > 0)
  5896. {
  5897. uroPopupDwellTimer--;
  5898. if(uroPopupDwellTimer === 0)
  5899. {
  5900. uroNewLookHighlightedItemsCheck('dwellTimeout');
  5901. }
  5902. }
  5903.  
  5904. if(document.getElementsByClassName("archive-panel")[0] === undefined)
  5905. {
  5906. if(dteClearHighlightsOnPanelClose)
  5907. {
  5908. dteClearListHighlight();
  5909. dteClearHighlightsOnPanelClose = false;
  5910. }
  5911. }
  5912. else
  5913. {
  5914. if(dteArmClearHighlightsOnPanelClose)
  5915. {
  5916. dteArmClearHighlightsOnPanelClose = false;
  5917. dteClearHighlightsOnPanelClose = true;
  5918. }
  5919. }
  5920.  
  5921. // test for the opening or closing of the UR editing dialog
  5922. var URDialogIsOpen = (document.getElementsByClassName('new-comment-form').length == 1);
  5923. if(URDialogIsOpen)
  5924. {
  5925. var thisSelectedURID = W.map.panelRegion.currentView.conversationView.conversation.getID();
  5926. if(thisSelectedURID != uroSelectedURID)
  5927. {
  5928. // if the user selects a new UR whilst the editing dialog is still open, treat it in the
  5929. // same way as if the user had selected that UR with the dialog closed
  5930. uroURDialogIsOpen = false;
  5931. }
  5932. if(uroURDialogIsOpen === false)
  5933. {
  5934. // user is editing a new UR
  5935. uroSelectedURID = thisSelectedURID;
  5936. document.getElementsByClassName('new-comment-form')[0].getElementsByClassName('btn')[0].addEventListener("click", uroAddedComment, false);
  5937. uroAddLog('user is editing UR '+uroSelectedURID);
  5938. uroExpectedCommentCount = W.model.updateRequestSessions.objects[uroSelectedURID].comments.length;
  5939. }
  5940. }
  5941. else if(uroURDialogIsOpen === true)
  5942. {
  5943. // dialog was open and has now been closed
  5944. uroSelectedURID = null;
  5945. }
  5946. uroURDialogIsOpen = URDialogIsOpen;
  5947.  
  5948. if(((uroPendingCommentDataRefresh === true) || (uroWaitingCommentDataRefresh === true)) && (uroSelectedURID !== null))
  5949. {
  5950. uroAddLog('check completion of comment data refresh for UR '+uroSelectedURID+' ('+uroPendingCommentDataRefresh+','+uroWaitingCommentDataRefresh+')');
  5951. uroGetSelectedURCommentCount();
  5952. }
  5953.  
  5954. var selectedTotal = W.selectionManager.selectedItems.length;
  5955. if((selectedTotal > 0) && (document.getElementById('_uroDivOWLBtns') === null))
  5956. {
  5957. var selectedClass = W.selectionManager.selectedItems[0].model.CLASS_NAME;
  5958. var displayAddToOWLBtn = false;
  5959. var displayUpdateOWLBtn = false;
  5960. var displayRemoveFromOWLBtn = false;
  5961. var selectedSegments = false;
  5962. var selectedLandmarks = false;
  5963. var fid;
  5964. var loop;
  5965.  
  5966. // WME only seems to allow multi-object selections for segments, so testing the class of the first object in the
  5967. // selection list tells us the class of any other objects in the list too...
  5968. if(selectedClass == "Waze.Feature.Vector.Segment")
  5969. {
  5970. selectedSegments = true;
  5971. for(loop=0; loop<selectedTotal; loop++)
  5972. {
  5973. fid = W.selectionManager.selectedItems[loop].model.attributes.id;
  5974. var segIdx = uroIsSegOnWatchList(fid);
  5975. if(segIdx == -1)
  5976. {
  5977. displayAddToOWLBtn = true;
  5978. }
  5979. else
  5980. {
  5981. if(uroSegDataChanged(segIdx))
  5982. {
  5983. displayUpdateOWLBtn = true;
  5984. }
  5985. displayRemoveFromOWLBtn = true;
  5986. }
  5987. }
  5988. }
  5989.  
  5990. else if(selectedClass == "Waze.Feature.Vector.Landmark")
  5991. {
  5992. selectedLandmarks = true;
  5993. for(loop=0; loop<selectedTotal; loop++)
  5994. {
  5995. fid = W.selectionManager.selectedItems[loop].model.attributes.id;
  5996. var placeIdx = uroIsPlaceOnWatchList(fid);
  5997. if(placeIdx == -1)
  5998. {
  5999. displayAddToOWLBtn = true;
  6000. }
  6001. else
  6002. {
  6003. if(uroPlaceDataChanged(placeIdx))
  6004. {
  6005. displayUpdateOWLBtn = true;
  6006. }
  6007. displayRemoveFromOWLBtn = true;
  6008. }
  6009. }
  6010. }
  6011.  
  6012. var btnHTML = '<div id="_uroDivOWLBtns">';
  6013. if((displayAddToOWLBtn === true) && (displayUpdateOWLBtn === false))
  6014. {
  6015. btnHTML += '<button class="btn btn-default" id="_btnAddUpdateOWL">Add to OWL</button>';
  6016. }
  6017. else if((displayUpdateOWLBtn === true) && (displayAddToOWLBtn === false))
  6018. {
  6019. btnHTML += '<button class="btn btn-default" id="_btnAddUpdateOWL">Update OWL</button>';
  6020. }
  6021. else if((displayAddToOWLBtn === true) && (displayUpdateOWLBtn === true))
  6022. {
  6023. btnHTML += '<button class="btn btn-default" id="_btnAddUpdateOWL">Add to & Update OWL</button>';
  6024. }
  6025.  
  6026. if(displayRemoveFromOWLBtn === true)
  6027. {
  6028. btnHTML += '<button class="btn btn-default" id="_btnRemoveOWL">Remove from OWL</button>';
  6029. }
  6030. btnHTML += '</div>';
  6031. /*
  6032. // once we get around to enabling these again, remember that altering the inner HTML of the
  6033. // segment-edit-general panel when the selected segment is part of a roundabout then disables
  6034. // the onclick handler for the select roundabout button...
  6035. //
  6036. // also remember that the current WME beta has yet another different side panel arrangement
  6037. if(selectedSegments === true)
  6038. {
  6039. document.getElementById("segment-edit-general").innerHTML += btnHTML;
  6040. }
  6041. else if(selectedLandmarks === true)
  6042. {
  6043. document.getElementById("landmark-edit-general").innerHTML += btnHTML;
  6044. }
  6045.  
  6046. if((displayAddToOWLBtn === true)||(displayUpdateOWLBtn === true))
  6047. {
  6048. if(selectedSegments === true)
  6049. {
  6050. uroAddEventListener('_btnAddUpdateOWL','click', uroAddUpdateSegWatchList, true);
  6051. }
  6052. else
  6053. {
  6054. uroAddEventListener('_btnAddUpdateOWL','click', uroAddUpdatePlaceWatchList, true);
  6055. }
  6056. }
  6057.  
  6058. if(displayRemoveFromOWLBtn === true)
  6059. {
  6060. if(selectedSegments === true)
  6061. {
  6062. uroAddEventListener('_btnRemoveOWL','click', uroRemoveSegFromWatchList, true);
  6063. }
  6064. else
  6065. {
  6066. uroAddEventListener('_btnRemoveOWL','click', uroRemovePlaceFromWatchList, true);
  6067. }
  6068. }
  6069. */
  6070. }
  6071. }
  6072. }
  6073.  
  6074. function uroToggleURCtrls()
  6075. {
  6076. uroCtrlsHidden = !uroCtrlsHidden;
  6077. if (!uroCtrlsHidden)
  6078. {
  6079. document.getElementById('_hideUCCtrl').innerHTML = "hide";
  6080. if(uroCurrentTab == 1) uroShowURTab();
  6081. else if(uroCurrentTab == 2) uroShowMPTab();
  6082. else if(uroCurrentTab == 3) uroShowPlacesTab();
  6083. else if(uroCurrentTab == 4) uroShowCameraTab();
  6084. else if(uroCurrentTab == 5) uroShowOWLTab();
  6085. else if(uroCurrentTab == 6) uroShowMiscTab();
  6086. }
  6087. else
  6088. {
  6089. document.getElementById('_hideUCCtrl').innerHTML = "show";
  6090. uroSetStyleDisplay('uroCtrlURs','none');
  6091. uroSetStyleDisplay('uroCtrlMPs','none');
  6092. uroSetStyleDisplay('uroCtrlCameras','none');
  6093. uroSetStyleDisplay('uroCtrlMisc','none');
  6094. uroSetStyleDisplay('uroOWL','none');
  6095. }
  6096.  
  6097. return false;
  6098. }
  6099.  
  6100. function uroActiveTab(_id)
  6101. {
  6102. var e = document.getElementById(_id);
  6103. e.style.backgroundColor = "aliceblue";
  6104. e.style.borderTop = "1px solid";
  6105. e.style.borderLeft = "1px solid";
  6106. e.style.borderRight = "1px solid";
  6107. e.style.borderBottom = "0px solid";
  6108. }
  6109.  
  6110. function uroInactiveTab(_id)
  6111. {
  6112. var e = document.getElementById(_id);
  6113. e.style.backgroundColor = "white";
  6114. e.style.borderTop = "0px solid";
  6115. e.style.borderLeft = "0px solid";
  6116. e.style.borderRight = "0px solid";
  6117. e.style.borderBottom = "1px solid";
  6118. }
  6119.  
  6120.  
  6121. function uroInactiveAllTabs()
  6122. {
  6123. uroInactiveTab("_tabSelectCameras");
  6124. uroInactiveTab("_tabSelectMapProblems");
  6125. uroInactiveTab("_tabSelectMisc");
  6126. uroInactiveTab("_tabSelectUserRequests");
  6127. uroInactiveTab("_tabSelectCWL");
  6128. uroInactiveTab("_tabSelectPlaces");
  6129.  
  6130. if(!uroCtrlsHidden)
  6131. {
  6132. uroSetStyleDisplay('uroCtrlURs','none');
  6133. uroSetStyleDisplay('uroCtrlMPs','none');
  6134. uroSetStyleDisplay('uroCtrlCameras','none');
  6135. uroSetStyleDisplay('uroCtrlMisc','none');
  6136. uroSetStyleDisplay('uroOWL','none');
  6137. uroSetStyleDisplay('uroCtrlPlaces','none');
  6138. }
  6139. }
  6140.  
  6141.  
  6142. function uroShowURTab()
  6143. {
  6144. uroInactiveAllTabs();
  6145. uroActiveTab("_tabSelectUserRequests");
  6146. uroCurrentTab = 1;
  6147. if(!uroCtrlsHidden) uroSetStyleDisplay('uroCtrlURs','block');
  6148. return false;
  6149. }
  6150.  
  6151.  
  6152. function uroShowMPTab()
  6153. {
  6154. uroInactiveAllTabs();
  6155. uroActiveTab("_tabSelectMapProblems");
  6156. uroCurrentTab = 2;
  6157. if(!uroCtrlsHidden) uroSetStyleDisplay('uroCtrlMPs','block');
  6158. return false;
  6159. }
  6160.  
  6161. function uroShowPlacesTab()
  6162. {
  6163. uroInactiveAllTabs();
  6164. uroActiveTab("_tabSelectPlaces");
  6165. uroCurrentTab = 3;
  6166. if(!uroCtrlsHidden) uroSetStyleDisplay('uroCtrlPlaces','block');
  6167. for(var idx=0;idx<uroPlacesGroupsCollapsed.length;idx++)
  6168. {
  6169. uroPlacesGroupCEHandler(idx);
  6170. }
  6171. return false;
  6172. }
  6173.  
  6174. function uroShowCameraTab()
  6175. {
  6176. uroInactiveAllTabs();
  6177. uroActiveTab("_tabSelectCameras");
  6178. uroCurrentTab = 4;
  6179. if(!uroCtrlsHidden) uroSetStyleDisplay('uroCtrlCameras','block');
  6180. return false;
  6181. }
  6182.  
  6183. function uroShowOWLTab()
  6184. {
  6185. uroInactiveAllTabs();
  6186. uroActiveTab("_tabSelectCWL");
  6187. uroCurrentTab = 5;
  6188. if(!uroCtrlsHidden) uroSetStyleDisplay('uroOWL','block');
  6189. uroOWLUpdateHTML();
  6190. return false;
  6191. }
  6192.  
  6193. function uroShowMiscTab()
  6194. {
  6195. uroInactiveAllTabs();
  6196. uroActiveTab("_tabSelectMisc");
  6197. uroCurrentTab = 6;
  6198. if(!uroCtrlsHidden) uroSetStyleDisplay('uroCtrlMisc','block');
  6199. return false;
  6200. }
  6201.  
  6202.  
  6203.  
  6204. function uroTimbonesGetElementsByClassName(classname, node)
  6205. {
  6206. if(!node) node = document.getElementsByTagName("body")[0];
  6207. var a = [];
  6208. var re = new RegExp('\\b' + classname + '\\b');
  6209. var els = node.getElementsByTagName("*");
  6210. for (var i=0,j=els.length; i<j; i++)
  6211. {
  6212. if (re.test(els[i].className)) a.push(els[i]);
  6213. }
  6214. return a;
  6215. }
  6216.  
  6217. function uroNewLookCheckDetailsRequest()
  6218. {
  6219. var thisurl = document.location.href;
  6220. var doRetry = true;
  6221. var urID;
  6222. var endmarkerpos = thisurl.indexOf('&endshow');
  6223. var showmarkerpos = thisurl.indexOf('&showturn=');
  6224. if((endmarkerpos != -1) && (showmarkerpos != -1))
  6225. {
  6226. showmarkerpos += 10;
  6227. uroAddLog('showturn tab opened');
  6228. urID = thisurl.substr(showmarkerpos,endmarkerpos-showmarkerpos);
  6229. uroAddLog(' turn problem ID = '+urID);
  6230.  
  6231. try
  6232. {
  6233. W.map.problemLayer.markers[urID].icon.imageDiv.click();
  6234. doRetry = false;
  6235. }
  6236. catch(err)
  6237. {
  6238. uroAddLog('problems not fully loaded, retrying...');
  6239. }
  6240.  
  6241. if(doRetry) setTimeout(uroNewLookCheckDetailsRequest,500);
  6242. }
  6243. else
  6244. {
  6245. showmarkerpos = thisurl.indexOf('&showpur=');
  6246. if((endmarkerpos != -1) && (showmarkerpos != -1))
  6247. {
  6248. showmarkerpos += 9;
  6249. uroAddLog('showPUR tab opened');
  6250. urID = thisurl.substr(showmarkerpos,endmarkerpos-showmarkerpos);
  6251. uroAddLog(' PUR ID = '+urID);
  6252.  
  6253. try
  6254. {
  6255. W.map.placeUpdatesLayer.markers[urID].icon.imageDiv.click();
  6256. doRetry = false;
  6257. }
  6258. catch(err)
  6259. {
  6260. uroAddLog('PURs not fully loaded, retrying...');
  6261. }
  6262.  
  6263. if(doRetry) setTimeout(uroNewLookCheckDetailsRequest,500);
  6264. }
  6265. }
  6266.  
  6267. }
  6268.  
  6269.  
  6270. function uroUpdateMPSolverList()
  6271. {
  6272. if(Object.keys(W.model.problems.objects).length === 0)
  6273. {
  6274. return;
  6275. }
  6276.  
  6277. var resolverList = [];
  6278. var selector = document.getElementById('_selectMPUserID');
  6279. var selectedUser = null;
  6280. if(selector.selectedOptions[0] !== undefined)
  6281. {
  6282. selectedUser = parseInt(selector.selectedOptions[0].value);
  6283. }
  6284. while(selector.options.length > 0)
  6285. {
  6286. selector.options.remove(0);
  6287. }
  6288. var selectedIdx = 0;
  6289. var idx = 0;
  6290.  
  6291. for (var mpobj in W.model.problems.objects)
  6292. {
  6293. if(W.model.problem.objects.hasOwnProperty(mpobj))
  6294. {
  6295. var prob = W.model.problems.objects[mpobj];
  6296. if(prob.attributes.resolvedBy !== null)
  6297. {
  6298. var userID = prob.attributes.resolvedBy;
  6299. var userName = W.model.users.objects[userID].userName;
  6300. if(resolverList.indexOf(userName) == -1)
  6301. {
  6302. resolverList.push(userName);
  6303. selector.options.add(new Option(userName, userID));
  6304. if(userID == selectedUser)
  6305. {
  6306. selectedIdx = idx;
  6307. }
  6308. idx++;
  6309. }
  6310. }
  6311. }
  6312. }
  6313.  
  6314. if(selectedIdx !== null)
  6315. {
  6316. selector.selectedIndex = selectedIdx;
  6317. }
  6318. }
  6319.  
  6320.  
  6321. function uroUpdateResolverList()
  6322. {
  6323. if(Object.keys(W.model.mapUpdateRequests.objects).length === 0)
  6324. {
  6325. return;
  6326. }
  6327.  
  6328. var resolverList = [];
  6329. var selector = document.getElementById('_selectURResolverID');
  6330. var selectedUser = null;
  6331. if(selector.selectedOptions[0] !== undefined)
  6332. {
  6333. selectedUser = parseInt(selector.selectedOptions[0].value);
  6334. }
  6335. while(selector.options.length > 0)
  6336. {
  6337. selector.options.remove(0);
  6338. }
  6339. var selectedIdx = 0;
  6340. var idx = 0;
  6341.  
  6342. for (var urobj in W.model.mapUpdateRequests.objects)
  6343. {
  6344. if(W.model.mapUpdateRequests.objects.hasOwnProperty(urobj))
  6345. {
  6346. var ureq = W.model.mapUpdateRequests.objects[urobj];
  6347. if(ureq.attributes.resolvedBy !== null)
  6348. {
  6349. var userID = ureq.attributes.resolvedBy;
  6350. var userName = W.model.users.objects[userID].userName;
  6351. if(resolverList.indexOf(userName) == -1)
  6352. {
  6353. resolverList.push(userName);
  6354. selector.options.add(new Option(userName, userID));
  6355. if(userID == selectedUser)
  6356. {
  6357. selectedIdx = idx;
  6358. }
  6359. idx++;
  6360. }
  6361. }
  6362. }
  6363. }
  6364. if(selectedIdx !== null)
  6365. {
  6366. selector.selectedIndex = selectedIdx;
  6367. }
  6368. }
  6369.  
  6370. function uroUpdateUserList()
  6371. {
  6372. if(Object.keys(W.model.updateRequestSessions.objects).length === 0) return;
  6373.  
  6374. var selector = document.getElementById('_selectURUserID');
  6375.  
  6376. var selectedUser = null;
  6377. if(selector.selectedOptions[0] !== undefined)
  6378. {
  6379. selectedUser = parseInt(selector.selectedOptions[0].value);
  6380. }
  6381.  
  6382. while(selector.options.length > 0)
  6383. {
  6384. selector.options.remove(0);
  6385. }
  6386.  
  6387. var selectedIdx = null;
  6388.  
  6389. var listedIDs = [];
  6390. for(var ursIdx in W.model.updateRequestSessions.objects)
  6391. {
  6392. if(W.model.updateRequestSessions.objects.hasOwnProperty(ursIdx))
  6393. {
  6394. var ursObj = W.model.updateRequestSessions.objects[ursIdx];
  6395. if(ursObj.comments.length > 0)
  6396. {
  6397. for(var cidx=0; cidx < ursObj.comments.length; cidx++)
  6398. {
  6399. var userID = ursObj.comments[cidx].userID;
  6400. if((listedIDs.indexOf(userID) == -1) && (userID != -1))
  6401. {
  6402. listedIDs.push(userID);
  6403. }
  6404. }
  6405. }
  6406. }
  6407. }
  6408.  
  6409. if(listedIDs.length > 0)
  6410. {
  6411. var users = W.model.users.getByIds(listedIDs);
  6412. for(var idx=0; idx<listedIDs.length; idx++)
  6413. {
  6414. selector.options.add(new Option(users[idx].userName, listedIDs[idx]));
  6415. if(listedIDs[idx] == selectedUser)
  6416. {
  6417. selectedIdx = idx;
  6418. }
  6419. }
  6420. }
  6421.  
  6422.  
  6423. if(selectedIdx !== null)
  6424. {
  6425. selector.selectedIndex = selectedIdx;
  6426. }
  6427. }
  6428.  
  6429.  
  6430. function uroSetStyles(obj)
  6431. {
  6432. obj.style.fontSize = '12px';
  6433. obj.style.lineHeight = '100%';
  6434. obj.style.overflow = 'auto';
  6435. obj.style.height = (window.innerHeight * 0.55) + 'px';
  6436. }
  6437.  
  6438. function uroPlacesGroupCEHandler(groupidx)
  6439. {
  6440. if(uroPlacesGroupsCollapsed[groupidx] === false)
  6441. {
  6442. document.getElementById('_uroPlacesGroup-'+groupidx).style.display = "block";
  6443. document.getElementById('_uroPlacesGroupState-'+groupidx).src = uroIcons[0][0];
  6444. }
  6445. else
  6446. {
  6447. document.getElementById('_uroPlacesGroup-'+groupidx).style.display = "none";
  6448. document.getElementById('_uroPlacesGroupState-'+groupidx).src = uroIcons[0][1];
  6449. }
  6450. }
  6451. function uroPlacesGroupCollapseExpand()
  6452. {
  6453. var groupidx = this.id.substr(21);
  6454. if(uroPlacesGroupsCollapsed[groupidx] === true) uroPlacesGroupsCollapsed[groupidx] = false;
  6455. else uroPlacesGroupsCollapsed[groupidx] = true;
  6456. uroPlacesGroupCEHandler(groupidx);
  6457. return false;
  6458. }
  6459. function uroPopulatePlacesTab()
  6460. {
  6461. var tHTML = '';
  6462. tHTML += '<b>Filter PURs by category/status:</b><br>';
  6463. tHTML += '<input type="checkbox" id="_cbFilterUneditablePlaceUpdates">Ones I can\'t edit</input><br>';
  6464. tHTML += '<input type="checkbox" id="_cbFilterLockRankedPlaceUpdates">Ones with non-zero lockRanks</input><br>';
  6465. tHTML += '<input type="checkbox" id="_cbFilterNewPlacePUR">Ones for new places</input><br>';
  6466. tHTML += '<input type="checkbox" id="_cbFilterUpdatedDetailsPUR">Ones for updated place details</input><br>';
  6467. tHTML += '<input type="checkbox" id="_cbFilterNewPhotoPUR">Ones for new photos</input><br>';
  6468. tHTML += '<input type="checkbox" id="_cbFilterFlaggedPUR">Ones flagged for attention</input><br>';
  6469. tHTML += '<br><input type="checkbox" id="_cbLeavePURGeos">Don\'t hide place polygons/points</input><br>';
  6470. tHTML += '<br><input type="checkbox" id="_cbInvertPURFilters">Invert PUR filters</input><br>';
  6471.  
  6472. tHTML += '<br><b>Filter PURs by severity:</b><br>';
  6473. tHTML += '<input type="checkbox" id="_cbPURFilterLowSeverity">Low</input>&nbsp;&nbsp;';
  6474. tHTML += '<input type="checkbox" id="_cbPURFilterMediumSeverity">Medium</input>&nbsp;&nbsp;';
  6475. tHTML += '<input type="checkbox" id="_cbPURFilterHighSeverity">High</input>';
  6476.  
  6477. tHTML += '<br><b>Filter PURs by age of submission:</b><br>';
  6478. tHTML += '<input type="checkbox" id="_cbEnablePURMinAgeFilter">Hide PURs less than </input>';
  6479. tHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputPURFilterMinDays"> days old<br>';
  6480. tHTML += '<input type="checkbox" id="_cbEnablePURMaxAgeFilter">Hide PURs more than </input>';
  6481. tHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputPURFilterMaxDays"> days old<br>';
  6482.  
  6483. tHTML += '<hr>';
  6484.  
  6485. tHTML += '<br><b>Filter Places by state:</b><br>';
  6486. tHTML += 'Hide if last edited<br>';
  6487. tHTML += '<input type="checkbox" id="_cbPlaceFilterEditedLessThan"> less than </input>';
  6488. tHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterPlaceEditMinDays"> days ago<br>';
  6489. tHTML += '<input type="checkbox" id="_cbPlaceFilterEditedMoreThan"> more than </input>';
  6490. tHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterPlaceEditMaxDays"> days ago<br>';
  6491.  
  6492. tHTML += '<br>Hide if locked at level:<br>';
  6493. tHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHidePlacesL0">1</input>';
  6494. tHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHidePlacesL1">2</input>';
  6495. tHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHidePlacesL2">3</input>';
  6496. tHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHidePlacesL3">4</input>';
  6497. tHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHidePlacesL4">5</input>';
  6498. tHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHidePlacesL5">6</input>';
  6499.  
  6500. tHTML += '<br><br><input type="checkbox" id="_cbHidePhotoPlaces" pairedWith="_cbHideNoPhotoPlaces">Hide or </input>';
  6501. tHTML += '<input type="checkbox" id="_cbHideNoPhotoPlaces" pairedWith="_cbHidePhotoPlaces">show ones with photos</input><br>';
  6502.  
  6503. tHTML += '<br><br><b>Filter Places by category:</b><br>';
  6504.  
  6505. var nCategories = W.Config.venues.categories.length;
  6506. var i;
  6507. if(uroPlacesGroupsCollapsed.length != nCategories)
  6508. {
  6509. for(i=0; i<nCategories; i++)
  6510. {
  6511. uroPlacesGroupsCollapsed.push(false);
  6512. }
  6513. }
  6514.  
  6515. for(i=0; i<nCategories; i++)
  6516. {
  6517. var parentCategory = W.Config.venues.categories[i];
  6518. var localisedName = I18n.lookup("venues.categories")[parentCategory];
  6519.  
  6520. if(uroPlacesGroupsCollapsed[i] === true)
  6521. {
  6522. tHTML += '<img src="'+uroIcons[0][1]+'" id="_uroPlacesGroupState-'+i+'">';
  6523. }
  6524. else
  6525. {
  6526. tHTML += '<img src="'+uroIcons[0][0]+'" id="_uroPlacesGroupState-'+i+'">';
  6527. }
  6528.  
  6529. tHTML += '&nbsp;&nbsp;<input type="checkbox" id="_cbPlacesFilter-'+parentCategory+'"><b>'+localisedName+'</b></input><br>';
  6530. tHTML += '<div id="_uroPlacesGroup-'+i+'" style="padding:3px;border-width:2px;border-style:solid;border-color:#FFFFFF">';
  6531.  
  6532. for(var ii=0; ii<W.Config.venues.subcategories[parentCategory].length; ii++)
  6533. {
  6534. var subCategory = W.Config.venues.subcategories[parentCategory][ii];
  6535. localisedName = I18n.lookup("venues.categories")[subCategory];
  6536. tHTML += '&nbsp;&nbsp;<input type="checkbox" id="_cbPlacesFilter-'+subCategory+'">'+localisedName+'</input><br>';
  6537. }
  6538. tHTML += '</div>';
  6539. }
  6540. tHTML += '<input type="checkbox" id="_cbFilterPrivatePlaces"><b>Residential Places</b></input><br>';
  6541. tHTML += '<br><input type="checkbox" id="_cbInvertPlacesFilter">Invert Place filters?</input>';
  6542.  
  6543. uroCtrlPlaces.innerHTML = tHTML;
  6544. }
  6545.  
  6546. function uroWazeBits()
  6547. {
  6548. // "fake" uroWazeBits() function which only performs layer scan, to stop the uroWazeBits() call in WMETB from
  6549. // messing around with other stuff in the actual uroWazeBits() function (now renamed uroRealWazeBits...) that
  6550. // really only ought to be called once.
  6551. var i;
  6552. for(i=0;i<W.map.layers.length;i++)
  6553. {
  6554. if(W.map.layers[i].name == 'Spotlight') uroMaskLayer = i;
  6555. if(W.map.layers[i].name.indexOf('Waze.Control.SelectHighlightFeature') != -1) uroRootContainer = W.map.layers[i].div.id;
  6556. if(W.map.layers[i].name == 'Node Connections') uroTurnsLayerIdx = i;
  6557. }
  6558. uroPlacesRoot = W.map.landmarkLayer.id + '_vroot';
  6559.  
  6560. for(i=0;i<W.map.controls.length;i++)
  6561. {
  6562. if(W.map.controls[i].CLASS_NAME == 'Waze.View.ArchivePanel') dteControlsIdx = i;
  6563. else if(W.map.controls[i].CLASS_NAME == 'Waze.Control.Archive') dteControlsIdx = i;
  6564.  
  6565. if(W.map.controls[i].id !== null)
  6566. {
  6567. if(W.map.controls[i].id.indexOf('UpdateRequests') != -1) uroURControlsIdx = i;
  6568. if(W.map.controls[i].id.indexOf('MapProblems') != -1) uroProblemControlsIdx = i;
  6569. }
  6570. }
  6571. uroAddLog('uroMaskLayer at idx '+uroMaskLayer);
  6572. uroAddLog('Turns layer at idx '+uroTurnsLayerIdx);
  6573. uroAddLog('uroRootContainer = '+uroRootContainer);
  6574. uroAddLog('Places root layer = '+uroPlacesRoot);
  6575. }
  6576.  
  6577.  
  6578. function uroRealWazeBits()
  6579. {
  6580. if(document.getElementsByClassName("sandbox").length > 0)
  6581. {
  6582. uroPracticeMode = true;
  6583. }
  6584. else
  6585. {
  6586. uroPracticeMode = false;
  6587. }
  6588.  
  6589. uroAddLog('adding WazeBits...'+uroToHex(uroWazeBitsPresent,4));
  6590. if((uroWazeBitsPresent & 0x0001) === 0)
  6591. {
  6592. if(typeof unsafeWindow.W != "undefined")
  6593. {
  6594. if(typeof unsafeWindow.W.controller != "undefined")
  6595. {
  6596. if(typeof unsafeWindow.W.controller.map != "undefined")
  6597. {
  6598. uroAddLog(' W.map OK');
  6599. W.map = unsafeWindow.W.controller.map;
  6600. uroWazeBitsPresent |= 0x0001;
  6601. }
  6602. }
  6603. }
  6604. }
  6605. if((uroWazeBitsPresent & 0x0002) === 0)
  6606. {
  6607. if(typeof unsafeWindow.W != "undefined")
  6608. {
  6609. if(typeof unsafeWindow.W.controller != "undefined")
  6610. {
  6611. if(typeof unsafeWindow.W.controller.model != "undefined")
  6612. {
  6613. uroAddLog(' W.model OK');
  6614. W.model = unsafeWindow.W.controller.model;
  6615. uroWazeBitsPresent |= 0x0002;
  6616. }
  6617. }
  6618. }
  6619. }
  6620. if((uroWazeBitsPresent & 0x0004) === 0)
  6621. {
  6622. if(typeof unsafeWindow.W != "undefined")
  6623. {
  6624. if(typeof unsafeWindow.W.app != "undefined")
  6625. {
  6626. if(typeof unsafeWindow.W.app.loginManager != "undefined")
  6627. {
  6628. uroAddLog(' loginManager OK');
  6629. loginManager = unsafeWindow.W.app.loginManager;
  6630. uroWazeBitsPresent |= 0x0004;
  6631. }
  6632. }
  6633. }
  6634. }
  6635. if((uroWazeBitsPresent & 0x0008) === 0)
  6636. {
  6637. if(typeof unsafeWindow.W != "undefined")
  6638. {
  6639. if(typeof unsafeWindow.W.geometryEditing != "undefined")
  6640. {
  6641. if(typeof unsafeWindow.W.geometryEditing.selectionManager != "undefined")
  6642. {
  6643. uroAddLog(' selectionManager OK');
  6644. selectionManager = unsafeWindow.W.geometryEditing.selectionManager;
  6645. uroWazeBitsPresent |= 0x0008;
  6646. }
  6647. }
  6648. }
  6649. }
  6650. if((uroWazeBitsPresent & 0x0010) === 0)
  6651. {
  6652. if(typeof unsafeWindow.OpenLayers != "undefined")
  6653. {
  6654. uroAddLog(' OpenLayers OK');
  6655. OpenLayers = unsafeWindow.OpenLayers;
  6656. uroWazeBitsPresent |= 0x0010;
  6657. }
  6658. }
  6659. if((uroWazeBitsPresent & 0x0020) === 0)
  6660. {
  6661. if(typeof unsafeWindow.Waze != "undefined")
  6662. {
  6663. uroAddLog(' Waze OK');
  6664. Waze = unsafeWindow.Waze;
  6665. uroWazeBitsPresent |= 0x0020;
  6666. }
  6667. }
  6668. if((uroWazeBitsPresent & 0x0040) === 0)
  6669. {
  6670. if(document.getElementById('user-tabs') !== null)
  6671. {
  6672. uroUserTabId = 'user-tabs';
  6673. uroAddLog(' user-tabs OK');
  6674. uroWazeBitsPresent |= 0x0040;
  6675. }
  6676. else if(document.getElementById('user-info') !== null)
  6677. {
  6678. uroUserTabId = 'user-info';
  6679. uroAddLog(' user-info OK');
  6680. uroWazeBitsPresent |= 0x0040;
  6681. }
  6682. }
  6683. if((uroWazeBitsPresent & 0x0080) === 0)
  6684. {
  6685. if(uroPracticeMode === true)
  6686. {
  6687. uroAddLog(' sidepanel-drives ignored in practice mode');
  6688. uroWazeBitsPresent |= 0x0080;
  6689. }
  6690. else
  6691. {
  6692. if(document.getElementById('sidepanel-drives') !== null)
  6693. {
  6694. uroAddLog(' sidepanel-drives OK');
  6695. uroWazeBitsPresent |= 0x0080;
  6696. }
  6697. }
  6698. }
  6699. if((uroWazeBitsPresent & 0x0100) === 0)
  6700. {
  6701. if(typeof unsafeWindow.I18n != "undefined")
  6702. {
  6703. uroAddLog(' I18n OK');
  6704. uroWazeBitsPresent |= 0x0100;
  6705. }
  6706. }
  6707.  
  6708. if(uroWazeBitsPresent !== 0x01FF) setTimeout(uroRealWazeBits,250);
  6709. else if((loginManager.isLoggedIn() === false) && (uroPracticeMode === false))
  6710. {
  6711. uroAddLog('Waiting for user log-in...');
  6712. setTimeout(uroRealWazeBits,1000);
  6713. }
  6714. else
  6715. {
  6716. uroAddLog('All WazeBits present and correct...');
  6717.  
  6718. uroDOMHasTurnProblems = (W.model.turnProblems !== undefined);
  6719.  
  6720. uroPopulatePlacesTab();
  6721.  
  6722. uroControls.appendChild(uroCtrlURs);
  6723. uroControls.appendChild(uroCtrlMPs);
  6724. uroControls.appendChild(uroCtrlPlaces);
  6725. uroControls.appendChild(uroCtrlCameras);
  6726. uroControls.appendChild(uroOWL);
  6727. uroControls.appendChild(uroCtrlMisc);
  6728. uroControls.appendChild(uroCtrlHides);
  6729. uroControls.appendChild(uroAMList);
  6730.  
  6731. uroCtrlURs.onclick = uroFilterItems_URTabClick;
  6732. uroCtrlMPs.onclick = uroFilterItems_MPTabClick;
  6733. uroCtrlPlaces.onclick = uroFilterItems_PlacesTabClick;
  6734. uroCtrlCameras.onclick = uroFilterItems_CamerasTabClick;
  6735. uroCtrlMisc.onclick = uroFilterItems_MiscTabClick;
  6736.  
  6737. uroWazeBits();
  6738.  
  6739. uroDiv.addEventListener("mouseover", uroEnterPopup, false);
  6740. uroDiv.addEventListener("mouseout", uroExitPopup, false);
  6741.  
  6742. if(sessionStorage.UROverview_FID_IgnoreList === undefined) sessionStorage.UROverview_FID_IgnoreList = '';
  6743. if(sessionStorage.UROverview_FID_WatchList === undefined) sessionStorage.UROverview_FID_WatchList = '';
  6744.  
  6745. if(uroConfirmIntercepted === false) uroAddInterceptor();
  6746.  
  6747. setInterval(uroTenthSecondTick,100);
  6748. uroShowDebugOutput = uroPersistentDebugOutput;
  6749. }
  6750. }
  6751.  
  6752.  
  6753. function uroAddInterceptor()
  6754. {
  6755. uroAddLog('Adding interceptor function...');
  6756. // add interceptor function for confirm(), so that we can auto-select the "OK" option when solving URs
  6757. // which have pending question...
  6758.  
  6759. var _confirm = unsafeWindow.confirm;
  6760. unsafeWindow.confirm = function(msg)
  6761. {
  6762. if((I18n.lookup("update_requests.panel.confirm") == msg) && (uroGetCBChecked('_cbDisablePendingQuestions') === true))
  6763. {
  6764. uroAddLog('Intercepted pending comments confirmation...');
  6765. return true;
  6766. }
  6767. else if(typeof(msg) == 'undefined')
  6768. {
  6769. uroAddLog('Intercepted blank confirmation...');
  6770. return true;
  6771. }
  6772. else
  6773. {
  6774. return _confirm(msg);
  6775. }
  6776. };
  6777.  
  6778. uroConfirmIntercepted = true;
  6779. }
  6780.  
  6781.  
  6782. function uroEnterPopup()
  6783. {
  6784. uroMouseInPopup = true;
  6785. }
  6786.  
  6787. function uroExitPopup()
  6788. {
  6789. uroMouseInPopup = false;
  6790. }
  6791.  
  6792. function uroToggleDebug()
  6793. {
  6794. uroShowDebugOutput = !uroShowDebugOutput;
  6795. var dbgMode = "none";
  6796. if(uroShowDebugOutput)
  6797. {
  6798. dbgMode = "inline";
  6799. }
  6800. document.getElementById('_uroDebugMode').style.display = dbgMode;
  6801. }
  6802.  
  6803. function uroInitialise()
  6804. {
  6805. if(document.URL.indexOf('editor-beta') != -1) uroBetaEditor = true;
  6806.  
  6807. // create a new div to display the UR details floaty-box
  6808. uroDiv = document.createElement('div');
  6809. uroDiv.id = "uroDiv";
  6810. uroDiv.style.position = 'absolute';
  6811. uroDiv.style.visibility = 'hidden';
  6812. uroDiv.style.top = '0';
  6813. uroDiv.style.left = '0';
  6814. uroDiv.style.zIndex = 100;
  6815. uroDiv.style.backgroundColor = 'aliceblue';
  6816. uroDiv.style.borderWidth = '3px';
  6817. uroDiv.style.borderStyle = 'solid';
  6818. uroDiv.style.borderRadius = '10px';
  6819. uroDiv.style.boxShadow = '5px 5px 10px Silver';
  6820. uroDiv.style.padding = '4px';
  6821. document.body.appendChild(uroDiv);
  6822.  
  6823.  
  6824. uroControls = document.createElement('section');
  6825. uroControls.style.fontSize = '12px';
  6826. uroControls.id = 'uroControls';
  6827. var updateURL;
  6828. if(navigator.userAgent.indexOf('Chrome') == -1)
  6829. {
  6830. updateURL = 'https://greasyfork.org/scripts/1952-uroverview-plus-uro';
  6831. }
  6832. else
  6833. {
  6834. updateURL = 'https://chrome.google.com/webstore/detail/uroverview/amdamgkgchnbaopmphhjapmjcdghdphi';
  6835. }
  6836. var tabbyHTML = '<b><a href="'+updateURL+'" target="_blank">UROverview Plus</a></b> <label id="_uroVersion">'+uroVersion+'</label>';
  6837. tabbyHTML += '<label id="_uroDebugMode">(dbg)</label>';
  6838. tabbyHTML += '&nbsp;<input type="checkbox" id="_cbMasterEnable" checked>Enabled</input>';
  6839. tabbyHTML += '<p><table border=0 width="100%"><tr>';
  6840. tabbyHTML += '<td valign="center" align="center" id="_tabSelectUserRequests"><a href="#" id="_linkSelectUserRequests" style="text-decoration:none;font-size:12px">URs</a></td>';
  6841. tabbyHTML += '<td valign="center" align="center" id="_tabSelectMapProblems"><a href="#" id="_linkSelectMapProblems" style="text-decoration:none;font-size:12px">MPs</a></td>';
  6842. tabbyHTML += '<td valign="center" align="center" id="_tabSelectPlaces"><a href="#" id="_linkSelectPlaces" style="text-decoration:none;font-size:12px">Places</a></td>';
  6843. tabbyHTML += '<td valign="center" align="center" id="_tabSelectCameras"><a href="#" id="_linkSelectCameras" style="text-decoration:none;font-size:12px">Cams</a></td>';
  6844. tabbyHTML += '<td valign="center" align="center" id="_tabSelectCWL"><a href="#" id="_linkSelectOWL" style="text-decoration:none;font-size:12px">OWL</a></td>';
  6845. tabbyHTML += '<td valign="center" align="center" id="_tabSelectMisc"><a href="#" id="_linkSelectMisc" style="text-decoration:none;font-size:12px">Misc</a></td>';
  6846. tabbyHTML += '</tr></table>';
  6847. uroControls.innerHTML = tabbyHTML;
  6848.  
  6849.  
  6850. uroCtrlURs = document.createElement('p');
  6851. uroCtrlMPs = document.createElement('p');
  6852. uroCtrlCameras = document.createElement('p');
  6853. uroOWL = document.createElement('p');
  6854. uroCtrlMisc = document.createElement('p');
  6855. uroAMList = document.createElement('div');
  6856. uroCtrlHides = document.createElement('div');
  6857. uroCtrlPlaces = document.createElement('p');
  6858.  
  6859. // UR controls tab
  6860. uroCtrlURs.id = "uroCtrlURs";
  6861. uroCtrlURs.innerHTML = '<br>';
  6862.  
  6863. uroCtrlURs.innerHTML += '<b>Filter by type:</b><br>';
  6864. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterWazeAuto">Waze Automatic</input><br>';
  6865. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterIncorrectTurn">Incorrect turn</input><br>';
  6866. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterIncorrectAddress">Incorrect address</input><br>';
  6867. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterIncorrectRoute">Incorrect route</input><br>';
  6868. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterMissingRoundabout">Missing roundabout</input><br>';
  6869. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterGeneralError">General error</input><br>';
  6870. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterTurnNotAllowed">Turn not allowed</input><br>';
  6871. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterIncorrectJunction">Incorrect junction</input><br>';
  6872. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterMissingBridgeOverpass">Missing bridge overpass</input><br>';
  6873. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterWrongDrivingDirection">Wrong driving direction</input><br>';
  6874. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterMissingExit">Missing exit</input><br>';
  6875. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterMissingRoad">Missing road</input><br>';
  6876. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterBlockedRoad">Blocked road</input><br>';
  6877. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterMissingLandmark">Missing Landmark</input><br>';
  6878. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterUndefined">Undefined</input><br>';
  6879.  
  6880. uroCtrlURs.innerHTML += '&nbsp;&nbsp;<i>Specially tagged types</i><br>';
  6881. uroCtrlURs.innerHTML += '&nbsp;&nbsp;<input type="checkbox" id="_cbFilterRoadworks">[ROADWORKS]</input><br>';
  6882. uroCtrlURs.innerHTML += '&nbsp;&nbsp;<input type="checkbox" id="_cbFilterConstruction">[CONSTRUCTION]</input><br>';
  6883. uroCtrlURs.innerHTML += '&nbsp;&nbsp;<input type="checkbox" id="_cbFilterClosure">[CLOSURE]</input><br>';
  6884. uroCtrlURs.innerHTML += '&nbsp;&nbsp;<input type="checkbox" id="_cbFilterEvent">[EVENT]</input><br>';
  6885. uroCtrlURs.innerHTML += '&nbsp;&nbsp;<input type="checkbox" id="_cbFilterNote">[NOTE]</input><br><br>';
  6886. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbInvertURFilter">Invert operation of type filters?</input><br>';
  6887.  
  6888. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbURFilterOutsideArea">Hide URs outside my editable area</input><br>';
  6889.  
  6890. uroCtrlURs.innerHTML += '<hr>';
  6891.  
  6892. uroCtrlURs.innerHTML += '<br><b>Hide by state:</b><br>';
  6893. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterOpenUR">Open</input><br>';
  6894. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterClosedUR">Closed</input><br>';
  6895. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterSolved">Solved</input><br>';
  6896. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterUnidentified">Not identified</input><br><br>';
  6897.  
  6898.  
  6899. uroCtrlURs.innerHTML += '<br><b>Filter by age of submission:</b><br>';
  6900. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableMinAgeFilter">Hide URs less than </input>';
  6901. 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>';
  6902. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableMaxAgeFilter">Hide URs more than </input>';
  6903. 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>';
  6904.  
  6905. uroCtrlURs.innerHTML += '<br><b>Filter by description/comments/following:</b><br>';
  6906. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbURDescriptionMustBePresent" pairedWith="_cbURDescriptionMustBeAbsent">Hide</input> or ';
  6907. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbURDescriptionMustBeAbsent" pairedWith="_cbURDescriptionMustBePresent">show</input> URs with no description<br>';
  6908. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableKeywordMustBePresent">Hide URs not including </input>';
  6909. uroCtrlURs.innerHTML += '<input type="text" style="font-size:14px; line-height:16px; height:22px; margin-bottom:4px;" id="_textKeywordPresent"><br>';
  6910. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableKeywordMustBeAbsent">Hide URs including </input>';
  6911. uroCtrlURs.innerHTML += '<input type="text" style="font-size:14px; line-height:16px; height:22px; margin-bottom:4px;" id="_textKeywordAbsent"><br>';
  6912. uroCtrlURs.innerHTML += '&nbsp;&nbsp;<input type="checkbox" id="_cbCaseInsensitive"><i>Case-insensitive matches?</i></input><br><br>';
  6913.  
  6914. uroCtrlURs.innerHTML += 'With comments from me?<br>';
  6915. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideMyComments" pairedWith="_cbHideAnyComments">Yes </input>';
  6916. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideAnyComments" pairedWith="_cbHideMyComments">No</input><br>';
  6917.  
  6918. uroCtrlURs.innerHTML += 'If last comment made by me?<br>';
  6919. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideIfLastCommenter" pairedWith="_cbHideIfNotLastCommenter">Yes </input>';
  6920. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideIfNotLastCommenter" pairedWith="_cbHideIfLastCommenter">No </input><br>';
  6921.  
  6922. uroCtrlURs.innerHTML += 'If last comment made by UR reporter?<br>';
  6923. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideIfReporterLastCommenter" pairedWith="_cbHideIfReporterNotLastCommenter">Yes </input>';
  6924. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideIfReporterNotLastCommenter" pairedWith="_cbHideIfReporterLastCommenter">No</input><br>';
  6925.  
  6926. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableMinCommentsFilter">With less than </input>';
  6927. uroCtrlURs.innerHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterMinComments"> comments<br>';
  6928. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableMaxCommentsFilter">With more than </input>';
  6929. uroCtrlURs.innerHTML += '<input type="number" min="0" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterMaxComments"> comments<br>';
  6930.  
  6931. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideMyFollowed" pairedWith="_cbHideMyUnfollowed">Ones I am or </input>';
  6932. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideMyUnfollowed" pairedWith="_cbHideMyFollowed">am not following</input><br>';
  6933.  
  6934. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableCommentAgeFilter2">Last comment less than </input>';
  6935. 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>';
  6936. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableCommentAgeFilter">Last comment more than </input>';
  6937. 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>';
  6938.  
  6939. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbURUserIDFilter">Without comments from user</input>';
  6940. uroCtrlURs.innerHTML += '<select id="_selectURUserID" style="width:80%; height:22px;"></select><br>';
  6941. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbURResolverIDFilter">Not resolved by user</input>';
  6942. uroCtrlURs.innerHTML += '<select id="_selectURResolverID" style="width:80%; height:22px;"></select>';
  6943.  
  6944. uroCtrlURs.innerHTML += '<br><br><input type="checkbox" id="_cbNoFilterForTaggedURs"><b>Don\'t apply state/age filters to tagged URs</b></input><br>';
  6945.  
  6946.  
  6947. // Map problems controls tab
  6948. uroCtrlMPs.id = "uroCtrlMPs";
  6949. uroCtrlMPs.innerHTML = '<br>';
  6950.  
  6951. uroCtrlMPs.innerHTML += '<b>Filter MPs by type:</b><br>';
  6952. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterMissingJunction">Missing junction</input><br>';
  6953. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterMissingRoad">Missing road</input><br>';
  6954. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterCrossroadsJunctionMissing">Missing crossroads</input><br>';
  6955. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterDrivingDirectionMismatch">Driving direction mismatch</input><br>';
  6956. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterRoadTypeMismatch">Road type mismatch</input><br>';
  6957. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterRestrictedTurn">Restricted turn might be allowed</input><br>';
  6958. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterRoadClosureProblem">Road closure</input><br>';
  6959. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterUnknownProblem">Unknown problem type</input><br><br>';
  6960. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterTurnProblem">Turn Problems</input><br><br>';
  6961.  
  6962. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterReopenedProblem">Reopened Problems</input><br><br>';
  6963.  
  6964. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbInvertMPFilter">Invert operation of type filters?</input><br>';
  6965.  
  6966. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterOutsideArea">Hide MPs outside my editable area</input><br>';
  6967.  
  6968. uroCtrlMPs.innerHTML += '<br><b>Hide closed/solved/unidentified Problems:</b><br>';
  6969. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterClosed">Closed</input><br>';
  6970. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterSolved">Solved</input><br>';
  6971. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterUnidentified">Not identified</input><br><br>';
  6972.  
  6973. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPClosedUserIDFilter" pairedWith="_cbMPNotClosedUserIDFilter">Closed</input> or ';
  6974. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPNotClosedUserIDFilter" pairedWith="_cbMPClosedUserIDFilter">Not Closed</input> by user';
  6975. uroCtrlMPs.innerHTML += '<select id="_selectMPUserID" style="width:80%; height:22px;"></select><br>';
  6976.  
  6977. uroCtrlMPs.innerHTML += '<br><b>Hide problems (not turn) by severity:</b><br>';
  6978. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterLowSeverity">Low</input>&nbsp;&nbsp;';
  6979. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterMediumSeverity">Medium</input>&nbsp;&nbsp;';
  6980. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterHighSeverity">High</input><br>';
  6981.  
  6982.  
  6983. // Places filtering tab
  6984. uroCtrlPlaces.id = "uroCtrlPlaces";
  6985. uroCtrlPlaces.innerHTML = 'Places filter list being populated, please wait...';
  6986.  
  6987.  
  6988. // Camera controls tab
  6989. uroCtrlCameras.id = "uroCtrlCameras";
  6990. uroCtrlCameras.innerHTML = '<br><b>Show Cameras by creator:</b><br>';
  6991. uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowWorldCams" checked>world_* users</input><br>';
  6992. uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowUSACams" checked>usa_* users</input><br>';
  6993. uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowNonWorldCams" checked>other users</input><br>';
  6994. uroCtrlCameras.innerHTML += '<br><input type="checkbox" id="_cbShowOnlyMyCams">Show ONLY cameras created/edited by me</input><br>';
  6995.  
  6996.  
  6997. uroCtrlCameras.innerHTML += '<br><b>Show Cameras by approval status:</b><br>';
  6998. uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowApprovedCams" checked>approved</input><br>';
  6999. uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowNonApprovedCams" checked>non-approved</input><br>';
  7000. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbShowOlderCreatedNonApproved"> if created more than </input>';
  7001. 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>';
  7002. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbShowOlderUpdatedNonApproved"> if updated more than </input>';
  7003. 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>';
  7004.  
  7005. uroCtrlCameras.innerHTML += '<br><b>Show Cameras by type:</b><br>';
  7006. uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowSpeedCams" checked>Speed</input><br>';
  7007. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbShowIfSpeedSet" checked> with speed data</input><br>';
  7008. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbShowIfNoSpeedSet" checked> with no speed data</input><br>';
  7009. uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowRedLightCams" checked>Red Light</input><br>';
  7010. uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowDummyCams" checked>Dummy</input><br>';
  7011.  
  7012. uroCtrlCameras.innerHTML += '<br><b>Hide Cameras by creator:</b><br>';
  7013. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideCreatedByMe">me</input>';
  7014. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideCreatedByRank0">L1</input>';
  7015. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideCreatedByRank1">L2</input>';
  7016. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideCreatedByRank2">L3</input>';
  7017. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideCreatedByRank3">L4</input>';
  7018. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideCreatedByRank4">L5</input>';
  7019. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideCreatedByRank5">L6</input>';
  7020.  
  7021. uroCtrlCameras.innerHTML += '<br><b>Hide Cameras by updater:</b><br>';
  7022. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideUpdatedByMe">me</input>';
  7023. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideUpdatedByRank0">L1</input>';
  7024. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideUpdatedByRank1">L2</input>';
  7025. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideUpdatedByRank2">L3</input>';
  7026. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideUpdatedByRank3">L4</input>';
  7027. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideUpdatedByRank4">L5</input>';
  7028. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideUpdatedByRank5">L6</input>';
  7029.  
  7030. uroCtrlCameras.innerHTML += '<br><br><b><input type="checkbox" id="_cbHideCWLCams">Hide cameras on watchlist</input></b><br>';
  7031.  
  7032.  
  7033. // Object watchlist tab
  7034. uroOWL.id = "uroOWL";
  7035. uroOWLUpdateHTML();
  7036.  
  7037.  
  7038. // Misc controls tab
  7039. uroCtrlMisc.id = "uroCtrlMisc";
  7040. uroCtrlMisc.innerHTML = '<br><b>Use default conversation markers:</b><br>';
  7041. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbNativeConvoMarkers" checked>in public WME</input><br>';
  7042. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbNativeBetaConvoMarkers" checked>in beta WME</input><br>';
  7043.  
  7044. uroCtrlMisc.innerHTML += '<br><br><b><input type="checkbox" id="_cbCommentCount">Show comment count on UR markers</input></b><br>';
  7045.  
  7046. uroCtrlMisc.innerHTML += '<br><br><b><input type="checkbox" id="_cbURBackfill">Backfill UR data</input></b><br>';
  7047.  
  7048. uroCtrlMisc.innerHTML += '<br><br><b>Marker Unstacking:</b><br>';
  7049. 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>';
  7050. 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>';
  7051.  
  7052. uroCtrlMisc.innerHTML += '<br><br><b>Use custom marker for URs tagged as:</b><br>';
  7053. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomRoadworksMarkers">[ROADWORKS]</input><br>';
  7054. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomConstructionMarkers">[CONSTRUCTION]</input><br>';
  7055. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomClosuresMarkers">[CLOSURE]</input><br>';
  7056. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomEventsMarkers">[EVENT]</input><br>';
  7057. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomNotesMarkers">[NOTE]</input><br>';
  7058.  
  7059. uroCtrlMisc.innerHTML += '<br><br><b>Use custom marker for MPs tagged as:</b><br>';
  7060. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomElginMarkers">[Elgin]</input><br>';
  7061. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomTrafficMasterMarkers">[TM]</input><br>';
  7062. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomTrafficCastMarkers">[TrafficCast]</input><br>';
  7063.  
  7064. uroCtrlMisc.innerHTML += '<br><br><b>Popup mouse behaviour:</b><br>';
  7065. 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>';
  7066. 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>';
  7067. 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>';
  7068.  
  7069. uroCtrlMisc.innerHTML += '<br><br><b>Disable popup for:</b><br>';
  7070. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitURPopup">URs</input><br>';
  7071. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitMPPopup">MPs</input><br>';
  7072. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitCamPopup">Cameras</input><br>';
  7073. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitSegPopup">Segments</input><br>';
  7074. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitTurnsPopup">Restricted Turns</input><br>';
  7075. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitLandmarkPopup">Places</input><br>';
  7076. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitPUPopup">Place Updates</input><br>';
  7077.  
  7078. uroCtrlMisc.innerHTML += '<br><br><b>Date/Time formatting for popups:</b><br>';
  7079. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbDateFmtDDMMYY" pairedWith="_cbDateFmtMMDDYY,_cbDateFmtYYMMDD" checked>day/month/year</input><br>';
  7080. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbDateFmtMMDDYY" pairedWith="_cbDateFmtDDMMYY,_cbDateFmtYYMMDD">month/day/year</input><br>';
  7081. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbDateFmtYYMMDD" pairedWith="_cbDateFmtMMDDYY,_cbDateFmtDDMMYY">year/month/day</input><br><br>';
  7082. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbTimeFmt24H" pairedWith="_cbTimeFmt12H" checked>24 hour</input><br>';
  7083. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbTimeFmt12H" pairedWith="_cbTimeFmt24H">12 hour</input><br><br>';
  7084. uroCtrlMisc.innerHTML += '<i>Unticked uses browser default setting</i>';
  7085.  
  7086. uroCtrlMisc.innerHTML += '<br><br><b><input type="checkbox" id="_cbWhiteBackground">Use custom background colour</input></b><br>';
  7087. 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">';
  7088. 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">';
  7089. 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>';
  7090.  
  7091. uroCtrlMisc.innerHTML += '<br><br><b><input type="checkbox" id="_cbHideAMLayer">Hide Area Manager polygons</input></b><br>';
  7092.  
  7093. uroCtrlMisc.innerHTML += '<br><br><b><input type="checkbox" id="_cbDisablePlacesFiltering">Disable Places filtering</input></b><br>';
  7094.  
  7095. uroCtrlMisc.innerHTML += '<br><br><b><input type="checkbox" id="_cbDisablePendingQuestions">Disable UR Pending Questions confirmation</input></b><br>';
  7096.  
  7097. uroCtrlMisc.innerHTML += '<br><b>Enable integrated scripts:</b><br>';
  7098. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbEnableDTE">Drive Tab Enhancement (DTE)</input><br>';
  7099. if(uroBetaEditor === false)
  7100. {
  7101. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbEnableSRS">Select Roundabout Segments (SRS)</input><br>';
  7102. }
  7103.  
  7104. uroCtrlMisc.innerHTML += '<br><br><b>Settings backup/restore/reset:</b><br>';
  7105. uroCtrlMisc.innerHTML += '<input type="button" id="_btnSettingsToText" value="Backup">&nbsp;&nbsp;&nbsp;';
  7106. uroCtrlMisc.innerHTML += '<input type="button" id="_btnTextToSettings" value="Restore">&nbsp;&nbsp;|&nbsp;&nbsp;';
  7107. uroCtrlMisc.innerHTML += '<input type="button" id="_btnResetSettings" value="Reset"><br><br>';
  7108.  
  7109. uroCtrlMisc.innerHTML += '<textarea id="_txtSettings" value="" /><br>';
  7110. uroCtrlMisc.innerHTML += '<input type="button" id="_btnClearSettingsText" value="Clear"><br>';
  7111.  
  7112. // footer for tabs container
  7113. uroCtrlHides.id = 'uroCtrlHides';
  7114. uroCtrlHides.innerHTML = '<input type="button" id="_btnUndoLastHide" value="Undo last hide">&nbsp;&nbsp;&nbsp;';
  7115. uroCtrlHides.innerHTML += '<input type="button" id="_btnClearSessionHides" value="Undo all hides"><p>';
  7116.  
  7117. // footer for AM list
  7118. uroAMList.id = 'uroAMList';
  7119. window.addEventListener("beforeunload", uroSaveSettings, false);
  7120.  
  7121. uroRealWazeBits();
  7122. }
  7123.  
  7124.  
  7125. function dteAddHeader()
  7126. {
  7127. var rlcObj = document.getElementsByClassName("result-list-container");
  7128. if(typeof rlcObj == "undefined") return;
  7129. if(typeof rlcObj[0].children[0] == "undefined") return;
  7130. if(typeof rlcObj[0].children[0].innerHTML == "undefined") return;
  7131.  
  7132. var thtml = rlcObj[0].children[0].innerHTML;
  7133. if(thtml.indexOf('Full drive history') == -1)
  7134. {
  7135. thtml += '<br><br><i><small>Full drive history goes back to '+dteOldestFullDrive.toDateString()+'</small></i>';
  7136. rlcObj[0].children[0].innerHTML = thtml;
  7137. }
  7138. }
  7139.  
  7140.  
  7141. function dteSetNewTabLength()
  7142. {
  7143. uroAddLog('altering ResultsPerPage parameter...');
  7144.  
  7145. var t = document.getElementById('sidepanel-drives');
  7146. t.style.overflow = 'auto';
  7147. t.style.height = (window.innerHeight * 0.6) + 'px';
  7148.  
  7149. var baseloc = 'https://'+window.location.hostname+Waze.Config.api_base+'/Archive/MyList?minDistance=1000';
  7150.  
  7151. var a = new XMLHttpRequest();
  7152. var fullDrives = 0;
  7153. var foundMissingDrive = false;
  7154.  
  7155. while(!foundMissingDrive)
  7156. {
  7157. uroSetStyleDisplay(uroUserTabId,'none');
  7158. var loc = baseloc+'&offset='+fullDrives+'&count=5';
  7159. uroAddLog('requesting '+loc);
  7160. var retries = 0;
  7161. while(retries < 3)
  7162. {
  7163. a.open('GET',loc,false);
  7164. a.send();
  7165. if(a.responseText !== "")
  7166. {
  7167. break;
  7168. }
  7169. retries++;
  7170. }
  7171. if(a.responseText !== "")
  7172. {
  7173. var b = JSON.parse(a.responseText);
  7174. var loadedDrives = b.archives.objects.length;
  7175. uroAddLog('received '+loadedDrives+' drives');
  7176. if(loadedDrives != 5) foundMissingDrive = true;
  7177.  
  7178. for(var loop=0; loop < loadedDrives; loop++)
  7179. {
  7180. if(b.archives.objects[loop].hasFullSession === false)
  7181. {
  7182. foundMissingDrive = true;
  7183. }
  7184. else
  7185. {
  7186. fullDrives++;
  7187. dteOldestFullDrive = new Date(b.archives.objects[loop].startTime);
  7188. }
  7189. }
  7190. }
  7191. else
  7192. {
  7193. foundMissingDrive = true;
  7194. }
  7195. }
  7196.  
  7197. uroAddLog(fullDrives+' full drives in history');
  7198. uroAddLog('oldest drives are on '+dteOldestFullDrive.toDateString());
  7199. if(fullDrives < 5)
  7200. {
  7201. fullDrives = 5;
  7202. uroAddLog('insufficient full drives, using standard drives tab');
  7203. }
  7204. else if(fullDrives > 50)
  7205. {
  7206. uroAddLog('too many full drives for a single tab page, splitting over multiple pages...');
  7207. fullDrives = Math.ceil(fullDrives/Math.ceil(fullDrives/50));
  7208. }
  7209. uroSetStyleDisplay(uroUserTabId,'');
  7210. if((dteOldestFullDrive - dteEpoch) > 0)
  7211. {
  7212. uroAddLog('updating drives tab...');
  7213. W.map.controls[dteControlsIdx].sidePanelView.ResultsPerPage = fullDrives;
  7214. setInterval(dteAddHeader,250);
  7215. setInterval(dteCheckDriveListChanges,250);
  7216. }
  7217. }
  7218.  
  7219. function dteListClick()
  7220. {
  7221. dteClearListHighlight();
  7222. this.style.backgroundColor = "lightgreen";
  7223. dteArmClearHighlightsOnPanelClose = true;
  7224. }
  7225.  
  7226. function dteClearListHighlight()
  7227. {
  7228. var drivesShown = document.getElementById('sidepanel-drives').getElementsByClassName('result session').length;
  7229. if(drivesShown > 0)
  7230. {
  7231. for(var loop = 0;loop < drivesShown; loop++)
  7232. {
  7233. var listEntry = document.getElementById('sidepanel-drives').getElementsByClassName('result session')[loop];
  7234. listEntry.style.backgroundColor = "";
  7235. }
  7236. }
  7237. }
  7238.  
  7239. function dteCheckDriveListChanges()
  7240. {
  7241. var drivesShown = document.getElementById('sidepanel-drives').getElementsByClassName('result session').length;
  7242. if(drivesShown > 0)
  7243. {
  7244. var topID = document.getElementById('sidepanel-drives').getElementsByClassName('result session')[0].getAttribute('data-id');
  7245. if(topID != dteTopID)
  7246. {
  7247. dteTopID = topID;
  7248. for(var loop = 0;loop < drivesShown; loop++)
  7249. {
  7250. var listEntry = document.getElementById('sidepanel-drives').getElementsByClassName('result session')[loop];
  7251. var driveID = listEntry.getAttribute('data-id');
  7252. var driveObj = W.model.archives.objects[driveID];
  7253. var driveSecs = Math.floor((driveObj.endTime - driveObj.startTime) / 1000);
  7254. var driveHours = Math.floor(driveSecs / 3600);
  7255. driveSecs -= (driveHours * 3600);
  7256. var driveMins = Math.floor(driveSecs / 60);
  7257. driveSecs -= (driveMins * 60);
  7258. var trueTime = (driveHours+':'+("0"+driveMins).slice(-2)+'.'+("0"+driveSecs).slice(-2));
  7259. listEntry.getElementsByTagName('span')[1].innerHTML = trueTime;
  7260. listEntry.addEventListener("click", dteListClick, false);
  7261. }
  7262. }
  7263. }
  7264. }
  7265.  
  7266. function srsSelect()
  7267. {
  7268. var rbtID = selectionManager.selectedItems[0].model.attributes.junctionID;
  7269. uroAddLog('selecting roundabout ID '+rbtID);
  7270. selectionManager.selectControl.unselectAll();
  7271. var segID;
  7272. var junctionID;
  7273.  
  7274. for(var slIdx=0; slIdx < W.map.segmentLayer.features.length; slIdx++)
  7275. {
  7276. if(W.map.segmentLayer.features[slIdx].fid === null)
  7277. {
  7278. junctionID = W.map.segmentLayer.features[slIdx].model.attributes.junctionID;
  7279. segID = W.map.segmentLayer.features[slIdx].model.attributes.id;
  7280. }
  7281. else
  7282. {
  7283. junctionID = W.map.segmentLayer.features[slIdx].attributes.junctionID;
  7284. segID = W.map.segmentLayer.features[slIdx].fid;
  7285. }
  7286.  
  7287. if(junctionID == rbtID)
  7288. {
  7289. uroAddLog('...adding segment '+segID);
  7290. selectionManager.selectControl.select(W.map.segmentLayer.features[slIdx]);
  7291. }
  7292. }
  7293. }
  7294.  
  7295.  
  7296. function srsCheckSidePanel()
  7297. {
  7298. if(selectionManager.selectedItems.length === 0) return;
  7299. if(document.getElementById('srsCtrl') !== null) return;
  7300. var junctionID = selectionManager.selectedItems[0].model.attributes.junctionID;
  7301. if(junctionID === undefined) return;
  7302. srsCtrl = document.createElement('section');
  7303. srsCtrl.id = 'srsCtrl';
  7304. srsCtrl.innerHTML = '<button id="srsButton" class="btn btn-default">Select roundabout</button>';
  7305. document.getElementById('segment-edit-general').appendChild(srsCtrl);
  7306. uroSetOnClick('srsButton',srsSelect);
  7307. }
  7308.  
  7309.  
  7310. function uroBootstrap()
  7311. {
  7312. var bGreasemonkeyServiceDefined = false;
  7313. try {
  7314. bGreasemonkeyServiceDefined = (typeof Components.interfaces.gmIGreasemonkeyService === "object");
  7315. }
  7316. catch (err) { /* Ignore */ }
  7317. if (typeof unsafeWindow === "undefined" || ! bGreasemonkeyServiceDefined) {
  7318. unsafeWindow = ( function () {
  7319. var dummyElem = document.createElement('p');
  7320. dummyElem.setAttribute('onclick', 'return window;');
  7321. return dummyElem.onclick();
  7322. }) ();
  7323. }
  7324. /* begin running the code! */
  7325. uroInitialise();
  7326. }
  7327.  
  7328. uroBootstrap();
  7329.