UROverview Plus (URO+)

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

当前为 2015-12-02 提交的版本,查看 最新版本

  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.62
  9. // ==/UserScript==
  10.  
  11. /*
  12.  
  13. TO-DO ITEMS
  14. =======================================================================================================================
  15. Bug fixes - MUST BE CLEARED BEFORE RELEASE
  16. =======================================================================================================================
  17.  
  18.  
  19.  
  20. =======================================================================================================================
  21. Things to be checked
  22. =======================================================================================================================
  23.  
  24.  
  25. =======================================================================================================================
  26. Proposed functionality
  27. =======================================================================================================================
  28.  
  29. Use a completely new custom marker for any UR which matches a description keyword - i.e. combine the existing custom
  30. marker idea with the existing keyword filter
  31.  
  32. Fix for crosshairs icon in UR/MP/PUR details panel
  33.  
  34. Option to shuffle the UI elements around to restore sanity
  35. - Street/City/County/Country fields in the segment edit panel
  36.  
  37. Flush settings to localStorage whenever a change is made, or at least before opening a new tab via a popup
  38.  
  39. User-defined setting presets
  40.  
  41. Extend unstacking to cameras
  42.  
  43. Place filtering
  44. - by last user to edit
  45.  
  46. Localisation
  47.  
  48. First-run information
  49. - show quickstart guide to URO features if no existing settings are present (i.e. new installation)
  50.  
  51. =======================================================================================================================
  52. New functionality in progress
  53. =======================================================================================================================
  54.  
  55. Addition of segment and place watchlist functionality
  56. */
  57.  
  58. /* JSHint Directives */
  59. /* globals $: */
  60. /* globals W: true */
  61. /* globals I18n: */
  62. /* globals OL: true */
  63. /* globals OpenLayers: true */
  64. /* globals Waze: true */
  65. /* globals require: */
  66. /* jshint bitwise: false */
  67.  
  68. var uroVersion = "3.62";
  69. var uroReleaseDate = "20151202";
  70.  
  71. // list of changes affecting all users
  72. var uroChanges =
  73. [
  74. 'MPs without descriptions are handled correctly again'
  75. ];
  76. // list of changes affecting only WME Beta users (at least until the next production release including these parts of the beta code...)
  77. var uroBetaChanges =
  78. [
  79.  
  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. var uroURIDInURL = null;
  134.  
  135. var uroDOMHasTurnProblems = false;
  136. var uroBetaEditor = 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.  
  150. var uroCWLGroups = [];
  151. var uroCamWatchObjects = [];
  152. var uroSegWatchObjects = [];
  153. var uroPlaceWatchObjects = [];
  154.  
  155. var uroFriendlyAreaNames = [];
  156. var uroAreaNameHoverTime = -1;
  157. var uroAreaNameHoverObj = null;
  158. var uroAreaNameOverlayShown = false;
  159. var uroANEditHovered = false;
  160. var uroANEditBox = null;
  161.  
  162. var uroPrevMouseX = -1;
  163. var uroPrevMouseY = -1;
  164.  
  165. var dteControlsIdx = -1;
  166. var dteOldestFullDrive = new Date(0);
  167. var dteEpoch = new Date(0);
  168. var dteTopID = '';
  169. var dteClearHighlightsOnPanelClose = false;
  170. var dteArmClearHighlightsOnPanelClose = false;
  171.  
  172. var uroUserTabId = '';
  173.  
  174. var uroTBRObj = null;
  175.  
  176. var uroUnstackedMasterID = null;
  177. var uroStackList = [];
  178. var uroStackType = null;
  179.  
  180. var uroIcons =
  181. [
  182. // stuff used within the URO tabbed UI
  183. // 0 = group collapse/group expand
  184. [
  185. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94CAhYRIqo78SIAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAADtJREFUKM9j/P//PwNJgCQN////ZyFeGyMjIwMDAxMDiWAQamDB9Bb+kKTMBmICdxgFK64AxZKiSE3eAAOXFRnJRfN6AAAAAElFTkSuQmCC",
  186. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94CAhYRDHbt/O0AAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAAE5JREFUKM+9UkEKACAMcmP//7IdgghqMQvytoOKTiMJCRKBZNRpZgbAIcIzsa5XJcgOB8Qaaz3nSt4chlLX3nb9OXRlL7cO2V83I1Dn3QDKfhshMqWScAAAAABJRU5ErkJggg=="
  187. ],
  188. // 1 = addtogroup active/addtogroup idle
  189. [
  190. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94BGhYVKhKBubQAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAAEZJREFUOMtjYBjygBHB/P8fjzJGIszCZQA+gxkYWIjTABPDdAkL8U7G7hIcYcDISEGYwDQSFyZM5AQckYA4F7CQZ8goQAYAMCsd/TxbqrwAAAAASUVORK5CYII=",
  191. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94DAw0tDee2t8AAAABPSURBVDjL7ZAxCgAgDAMT6cP6dH+mUwfBaugmeFMpbTgCPA9j6H2M7MidvCZlAadgADDlIXY7E1OVM5NtB+5kuZN4VDtpleIkVAOrhHxWJoJkNv2QAd51AAAAAElFTkSuQmCC"
  192. ],
  193. // 2 = goto active/goto idle
  194. [
  195. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94BGhYfLAEN9AsAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAAGdJREFUOMutk+EKACEIg7fD93/l3Y+uP5kmeYMgkH0NTUpCRw+acgBynHaCKsgBlpaIhDJQtQchaAtIBuNAlAQSV7OUwPYYGX2kL6Zi37hYYk6NU1ZPui/Y4XWeVsWSDpdkt8bftvEFOy0jJkeygWMAAAAASUVORK5CYII=",
  196. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94DAw0tFm3TfiwAAABySURBVDjLrZNRDsAgCEPp4r306HKy7sMsMRMckZH4ZfqoYEFSMnVJshYAME7aQRS0AOaR9C5UFe5AoRnsQCbAW4wFAklRlaNd1ipIrxHeRwKGZeuuNcEjK554J5x7lohNS+g+4d39Kyqug2jGyqnwtzTengM2Gxwa0GsAAAAASUVORK5CYII="
  197. ],
  198.  
  199. // replacements for native UR/problem markers
  200. // 3 = normal/selected open roadworks UR
  201. [
  202. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAoCAYAAABw65OnAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94GCAc3MvOL7YEAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAACsJJREFUWMOlmHtsHVV+x7/nMWdm7r1zH45zvXnYuQFCQ0ikJC6JTEC9RbRg+AOpqf9KJdqKBFb9gy1/rlYrFgmhVuIhVSgbpF0WqyAoEivEsqtNUDMtCaAUV9k0BkKcteXYvbGv7VzfudczZ2bOOf0Dm80mfm33SPPPzJlzPuec3+P7OwR/eKMASLVaJUEQkKWXnucZ3/cNAANA/yEDknX2IdVqlY6NjfFKpcLTNLXCMGS2bdNms0ny+byRUmrXdRXnPBkbG0srlUrq+75ehDKrTcDWmJz29vZyrbWTz+eznuflwzAsaq1LADo45yUhRIlSmldKeUqpjJTSKRaLQinFkiQhO3fuNLVa7f+1E6RarTIppQXAZYzltNb5AwcOdB85cuQvenp6/jSXy93uOE4npVRoreMoimZardaV8fHxz998881T586du0opbSqlWgBC27YT3/fVcruyHATp7e3ljuM4URTlLMsqPvroo3/y+OOPP7lly5YHKaV8pRWFcRuuyEJrnU5OTn70xhtvnPjwww8vJUnScBynFUVRNDQ0lN4MQpYD4Jy7tm0X4jje+NJLL/3NgQMHvksocSih6zY2bTSMNtG5c+eOP/PMM/8qhKhLKefTNA1vBiE3H0GSJC4hpJTJZDadOHHih5VK5RH8kW1sbOyXTz755HMLCws1Y8x1y7LCG4/mRsNkYRg6xWKxQAj5zuuvv/6jtQDS8UugM6PA7AS0Bkg2v2y/YrG44/7779/y3nvvndNaJ5cvX07b7fYtEKS/v9/KZDKelLL88ssv/92ePXuOrLXCK4/dgQ1Xfgn86qeYuDyGwgN/tWLfYrG4Y+fOnfKDDz74qlwux7t3705GRkb0UuBBtVpl09PTjjEm39/ff/fBgwePrQUw88VvoK7OA44HMBvz/i/WPJaDBw8e6+/vv9sYk5+ennaq1Sr7Nvr5vs+iKHJt2y4ePXr0CcaYvdaAs5+dRIcHgBFACHitebTra8QDSuyjR48+Ydt2MYoi1/d9BoBQAPTQoUPCcZzs/v37t2/btu2B9Rjb/Ke/Ro4umjYnKDLg+mcfrR7vCUV3d/ef7d+/f7vjONlDhw4JAJRWq1WSJInIZDLZw4cPP7heizdTV8HKBSC/EejoglUuQo5+uXbioZQdPnz4wUwmk02SRFSrVcJ932e9vb1CSpnt6enZtx6ASEp0fe+fYHeVgUIBUCmcIAAP185bC7KFnp6efVLKrFJK+L7PeF9fHyWECMuynGKxWFkPxEy9jo57/hzwCr+XWrNzdcRxDCHEiv9m7Bx0ERXXdZ0kSURfXx+lnudRKSWP41hkMpnieiBm52bg3ADw7QQdG9CYm13z/0wmU4zjWEgpued5lMdxTDjn1BhDKaXWeiDmnv1bTEfT2HTH7SB33QmkCrh4EfMT19B67CmUj/1gLbuwjDGUc07jOCYcAFzXNVEUQSmVMMZWBTHGAKMXkJEGTM0AbggkEhgZhjVt0D7nA2tAKKWSpXkBgAohTJqmWgih2u323NpuYeBEBpziGwGVSEApgFBYCkguX1hziHa7PSeEUIvzGh4EgWaMpVrreHZ2dsx2rS7bclfNjuUn/hHW3DhgQmBzJ2A0ULgDjiig3LMXjWYTxfzyeUQmIebm5ka11jGANAgCzT/99FPd29ubWJYVXrp06fz27dsPrraKMIzQ8fffh1vqvOWbDSA/P4f563MrQtiWi6+++uo3aZqGSZIkQ0NDmlarVSWEkISQhcHBwTNKKbkaxNT/XgWnK0tGphXC+ZU9JE1TOTg4eIYQsiCEkNVqVVHf97Vt2zFjrD0xMVG7ePGiv+JRqBS1wVcQfXISqF0BrteAoP7NM1cDxobR/mAQ82++siLE8PCwPzExUWOMtW3bjn3f12Qx+ovdu3cXc7ncljvvvHPva6+99opt297NXjF69iNcOfKX2JEAmzsAcXsB2NYNKAOM/RZ6NMTkPDDak8POf/sfbNy6DYT8TjdJKYNjx4597+uvvz7farUmL1682AAQfytqduzYAcYYazQacF13Yc+ePQcJIURrjWvXruEnPxvEr3/4D6gEITYVgGIBIBYBBAGSCGgtgJgUCwa4NBXjxJlPULp9F7q7t4IQAmOMefvtt3986tSpzxhjU7Ztz1+9elUC0EuiVZ89ezbu7e1tUkqnjh8/fmrDhg2VkZGRx1544QUsSfa/BmCXv/XUbzbRGMAsbqgBCAO4BP7z9H/hJ6fvR6VSwfPPP49yufzz48ePn0qSZFpr3RwaGoqXiqQb5Z3ZvHmzyeVyOooic/bs2dFHHnnE+vzzz3ddu3YNAGAB2KSB77jARhegGQvIut8AhAvQCykuzwP/MQP8uwYiAI1GA+fPn58+efLkCUrp17lcbjqO41atVouX5N0tQheAI6UsACgD2DIwMPDAhQsXvvvWW285cRyjC8ABAHfngZ4ikM1zGBgETYXxBvDfTeATACGAzs5Ofc899/xqbm7uBKV0AsC0bdvzAKIbhS5ZrugB4ARB4AkhOhljXfl8fttdd931xDvvvHNgYmJiVd1PCEEulzMPP/zwcLPZ/Jd2u/1bpdRUHMcznucFNwOsWPxUq1UWBIHIZDLZIAiKjuN0MMa6OOfdmUzmmY8//vi2Vqu1LMRDDz0032w2n+Wcj8VxfE1KOet5XmNhYaHteV68XBW23KqM7/tqaGhIMsYCAHVjzKTWelQpdanRaDz/1FNP1bLZ7OLKgV27duH999/H7Oxso1Qq/cgYcymKojGt9SSAOmMsGBoakiuVgXy1+jQIAuW6rozj2DiOo7XWRmtNJycn/7lWqz2by+UKWuulWKBffPHF1ycmJkaUUjVK6YyUsuW6rqzX6/qmsc1qVTkZGBigX3zxhdXV1SU6OjoEIcTmnAulFE+ShNu2bTUaDdput+fvvffe3mZ4nbh2FqdPnz716quvfgRghjEWUEqTMAzBOWednZ1s06ZNfOvWrbRQKJB6vb4iBKlWq2xqasru7u7Olkolj1JaMMbkOecFSmnetm2PEJJVSmW+/PJLWalU3F07d1fGx8fHnn766XeVUi1KaUwIoQBs13XdNE0zcRy7AOwgCLjjONi7d69ZLHxuKQOXLkEylmUV0zQtCSFKjLFSkiQlQkgxSZICpTRvjNmqlCqfOXMm2LdvX9dzzz13pl6vLyVSMMa4MSZrjMkByDLGXEqpEEIwIYSWUqpyuaxrtdotLsr6+voEIcQjhJTSNC1ZlpUD4CZJIoQQFiGExXFsGWN6AOTTNHU551wppY0xkhDS4pxPU0qvG2NSxlhKCEmSJJFCiHYYhk3Lsq4LIeaDIGgvVefkJk+x7rvvvgwAT0rpWZaVIYQ4xhhLKcUJIYxSSgkhTCnFOeeMEMKSJNHGGMUYS40xyhijCCGac54CSKWUsTEmTJKknaZp0xjTHh4ejgAoAOZG7zADAwNpvV4PgyDQUkrpuq5oNBrccRyLUsqUUlQpBc455ZxTKSUxxhBCiLFt2xBCjFJKp2lqHMcxUspUKaVs204JIQkhRCZJIgEs5Y3lI+biRQmbnZ1lGzZsoJ7n0SAImOd5JE1TopQii2L1lkDHGDO/U2ChZowZx3H0yMiIvu2223Sz2VQbN27U64mYN74ni26Ler3+e1eGa7WlK8WBgQG8++675ob4cEuw+j+lA177aXrCYwAAAABJRU5ErkJggg==",
  203. "data:image/png;base64,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"
  204. ],
  205. // 4 = normal/selected closed roadworks UR
  206. [
  207. "data:image/png;base64,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",
  208. "data:image/png;base64,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"
  209. ],
  210.  
  211. // 5 = normal/selected open closure UR
  212. [
  213. "data:image/png;base64,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",
  214. "data:image/png;base64,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"
  215. ],
  216. // 6 = normal/selected closed closure UR
  217. [
  218. "data:image/png;base64,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",
  219. "data:image/png;base64,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"
  220. ],
  221.  
  222. // 7 = normal/selected open event UR
  223. [
  224. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAoCAYAAABw65OnAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94ICBQjDyQd1Y0AAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAADRJJREFUWMOdWGuMXOV5fr7Luc7O7Myud3zD62XBxmmAGpu4rE3KqJCkNkKVsNympQktP2ijBqlQpYQikTa4qSqUVX4QESjEwRQJgVAoN7dxRKfF4GJuDmGJVzbJ1Lf17uzsZW7nfOe7vP2xa8fYJiQ9Pz+dc97ne6/P8zL85g8HwCqVCmu1Wuz0YT6fp2q1SgAIgPtNfsh+zXdYpVLhtVpNDg0NSWOMlySJCIKAN5tNVigUSCnloiiyUkpdq9XM0NCQqVarbhEU/SoD4hOM840bN0rnXFgoFHL5fL6QJEnROVcC0CelLPm+X+KcF6y1eWttrJQKi8Wib60VWmu2bt06mpiY+H95glUqFaGU8gBEQoge51xh06ZNq2655ZbPDQ4OXt3T03NJGIZLOOe+cy5L03S63W5/ePTo0beefPLJvQcOHDjGOW9aa9sAkiAIdLVatRfyyoVAsI0bN8owDMM0TXs8zyveeOONl916661/sXLlyhs45/LjbpRkHUR+Ds45c+LEiR8//vjjD7/00kvjWuu5MAzbaZqmb7/9tjkXCLsQACllFARBb5ZlA6Ojo3+6adOmrzDOQs74r51sjhzIUXrgwIGH7rrrrn/1fb+ulJo3xiTnAmHnhkBrHTHGSnEcL3/44YfvGxoa2vaJFolAjMHNHoI78jzY9E8h1Dxsbikw+HnUvKtf/quv/OU3u93uBBHNep6XnB2asxNTJEkSFovFXsbYsl27dv3D6tWrtzHGFl79FXXkGAN9+ALYTx+FzDpgzIARB1cN8BP/hfxsdc3mPxtd+dxzzx9wzunDhw+bTqdzHgi2detWL47jvFKqPDo6+udXXnnlLYwxqCyDa87Apho8Cs/DQkRwp96E+PB58KAf8EMw5gGMA8yBnIFI5tDbPLBm3R98Q734wguHyuVydvnll+sjR464040HlUpFTE1NhURU2Lp166evueaa23WmMPsvj6F+3e9icus2nNiyBb8YXoXWW2/BOQdyDsY6OGiIsR+AgjwoKsL5JZDXA5IRiHlgMgRxCVl/HxsHZm/funXrp4moMDU1FVYqFXHaE6xWq3l9fX35QqFQvv/++++OZbCmceuXgONHIXp7IfwITHrQBCSP7sIPSsP4+kwB3z48gyfG67hUzmNFDEi/AC4kYDIwl4FZBegUzKQgp0C6Kdd+4W9KL7744r5ms5m8+eabCoDjAPiWLVv8MAxzGzZsuHjF6tW/17rnbkQDZQTlMsJyGV5/CbK3iObgEP7uif3Yt2YERd/DijAAyRC3d7bimhPXg1EXZBUYWZAzADmALMAMGBxE4ydYtWrVdRs2bLg4DMPcli1bfACcVyoVprX24zjObd++/QZVrUKaDF7/EoTl5fD6+sELBbieCN/5+qPoy+ewPAww4AsUPYGC7yEnBaZcAZ86PAKWNgDdBrMJnFUgZ0DGAY4Ao8A5F9u3b78hjuOc1tqvVCqMV6tVYa31lVK5wcHBq7J9r4KHEUQuhtfXB0QBBPfwzdt2YkkQYCAKsTTyUfI5ejyJWEqEQiDkHP9rCxidWY3MzINUE1x3wWwK2GQhi+MyuqqNwcHBq5RSOWutX61WBR8ZGeFBEPhRFIXFYnHIHT4MpzUoUchmZ0CJgnEWWa6IWEj0BxKlIEBOBggZh2QckjNwziEY4VutTfCSeSBrAVkb0B3AqYUSX7oJcdCDYrE4FEVRGASBPzIywmU+n+eNRkMSkR/HcbHdbAOMg/M6WCsAaYWDxVUgEAwcUmchiGCI4AhwYCACHBEIDAk4WHoKsA5kE7CsAwYsJObwQt+L47iYZZmfZZns7+/nMssyJqXkRMQ55x5yMUxjDlAKTHCQMTjZtxZda9DUHCACiKFlMrSMQWItFDloa2HJgcBASQOAWAgFGMCArLAS3srrFggJ5x4RcSklz7KMSQCIoojSNIW1Vst1l3npnj0w3RBCcFhj0C/fQ0ttB5xDIj0QEVLr0LIa7cyhY4CuM7AO8JgFsxlAfJGJEMhm4JXv4vTksdbq03YBgPu+T8YY5/u+7XQ6M8H1NyA9fhx6ahrqVB3Z1BTWHKhiJlWYTjUm0wSTKsOUUmhkDnPaoGkMEiMAxpCDgjlrPhIR3GfuBev/7TOnnU5nxvd9u2iXZKvVckII45zLGo1GbdnV65fy8jJkR2tgnINZB5cpzHYVOj7BFxwEICMgBdDWGm1tocmBIPAl+58Qp+9MBDtyH9jaP4bkCw1f6QQzMzO/cM5lAEyr1XJ8//79LkkSbYxJxsfHD0ZehPKux5BN1aEbMzBz87CdLu76zt+inmWYTBWmUoVpo1FPFWYyi9Q6gDEEAvj2F7+K9PNP40h4Hbp/+DrYmi9CcAmihckdeBEOHTr0E2NMkiSJ3r9/v+OVSsX6vq8YY93du3fvM8aonsuvwMonngC0hlvkrJ994z+Qzc+jnmrUjUMjs+hoC+ccGGNwRLhzTQGWRxBRBO/SGxH4eQixkEOMLXjCGKN27969jzHW9X1fVSoVy6vVqguCIBNCdI4fPz4xNjZWBYDCLX+CFc8+C6sNYAzIaOx97Gtw0oNzAOyCcTCAHOGKkoedVy6D4AJ+aS1MYRjCCz4CAADGxsaqx48fnxBCdIIgyKrVquMAqFqt6rm5uY7WenZ0dPTpNE1bknGUbr4Zn9IaPXd8FerLf4QNr7+KN65fCY8xGCz0CGOBzw5EePdzlwDil8zPabWQmmcBUEq1RkdHn9Zaz87NzXWq1aoGQGdIzZo1ayCEEHNzc4iiqHvFFVf8DmOMkbMIohjJ2mH0X7oOy3Ih7v2tEiJukE5P45+vXo4HPnMRGOcf4Ri5fBHS888+o6eeeup7e/fu/R8hxGQQBPPHjh1TANwZEMeOHcPAwACstXjnnXdmVqxY0bNnz551IyOb4V18MXiphDDOgTMOMI6852NFeTlWZVNYvWTJWSxn8facg3MOIsJ7772H999//4cPPPDAs1rrE1rrmTfeeCMBFqqZ//JTaADdXC7X0Fqf2Llz567Vq1c/u23bQqvtLS0DOXeGn15ZCvHlwQDriuFHmRYjHP1wDJxxWGtxzz334Oabb56644479iilTuZyuQaA7qK98zgmLrvsMgLgiMgCMK+99trPb7rppslHHnnkqlOTE3LN2mGEYQ5nhRndVhNxvndhPhCBAZiaPIVHHv0+brvtNmetfZlz/o04jseFEFNSylYQBKpWq7kLKrBarUZDQ0NOSmmTJNFCCD0+Pj5hjHldCFF++cXnV37h97cxIcQZ97W7bfTkegDGwBhDqlJ8//En6OC7B8d6enrua7fbewCcyLJsKo7jJoD0XBF0ngw8DSTLMhMEQdZut5XWunXy5Ml3Z2bnXxsfP7R+8+bNec/zAAA6TRDl8iAizMzM4N67v9ap/verd3e73R92Op0PkySZiKJoWmvdCoJAXUiFXVCL1mo1mpiYcMPDwyZN00wIoQCkjLH0yJHD77TbnZFisZgrl8tIuy2EcQ/SNIXOss5z//b838/Mzv5Ma32ciCadc7NxHHf379+fLYaALiTzP1YatlotG0WRMsa0OOcN59wpxvjxgwcP/tPQ0FATAKxzICIEQeAeeui7j9SOHh231k5wzqe11q0oilS9XndnK/xPUuVsx44d/IMPPvCWLl3q9/X1+YyxQErpW2ul1lqGYeQ1GtM8SdL5zZs3b5yaOcn6igN45ZVX9j744IM/FkJMCyFanHOdJAmklGLJkiVi+fLl8qKLLuK9vb2sXq9/bDhYpVIRk5OTwapVq3KlUinPOe8looKUspdzXgiCIM8Yy2lt4kOHfqaGhi6O1l6ydujEsaO1v77zzmcY423OecYY4wCCKIoiY0ycZVkEIGi1WjIMQ6xfv54Whc95JXp6CRJ7nlc0xpR83y8JIUpa6xJjrKi17uWcFxhjF+lMlV97/fXW+qvWL935j9/ad2piAkLIAACEEJKIckTUAyAnhIg4577v+8L3faeUsuVy2U1MTJwPYmRkRDLGIgA5IspzznMAYmttKKUMpZS+1tonoiXOuUgbLX/07z/6eb0+pQjMMcYc51wDMEQkhBBCSimstdzzPMqyzHLOM9/3syzL9MTEhDtXlXMA3rXXXhsDyCul8p7nxYyxkIg8a61kjAnOOWeMCWutZIDgQgiVpk5IaYUQhogsEVnGmJNSGgBGKZURUaK17hhjmkTUGRsbSwFYAHT2woN27Nhh6vV60mq1nFJKRVHkz83NyTAMPc65sNZyay2klFxKybudzkKHIkehFxFjjKy1zhhDYRiSUspYa20QBIYxphljSmutAGSLyzW64JJkcVEiGo2G6O/v5/l8nrdaLZHP55kxhllr2SJZZUQO1lgwxiCkhBDiTNYnSeKEEBSGoTty5IgbHh52zWbTDgwMuHMbFvuEXRZbLFvU6/WPrAxPPzpTkJ7/Ed5w9kpxx44deOaZZ+isQXles/o/KhD5gMjJ8lsAAAAASUVORK5CYII=",
  225. "data:image/png;base64,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"
  226. ],
  227. // 8 = normal/selected closed event UR
  228. [
  229. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAoCAYAAABw65OnAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94IDhUwB2+AKcYAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAADEVJREFUWMOdWGuMXdV5Xd9+nHPu3IfvnRnP9cCAr9887ALhoRCDggpplKoRP6JRpSatmgqlilQpaqWmDyFaUVKJVCAq9UVD6I9UrRpaIFIVt4IUt2Vog12MCXYDNvjaM3jiuTN37tzXOfvsx9cfc8cdP0hJ98+ts8+39vdcaxN+8iUAUONgg0zf0MZmXIq5OddkAAwg/CQ/pI/4DTUONkTnXEdVrqsodqxtZqWMpch7OUXliL3xQSfakyLbne+66vVV15xrhhEo/nEG5P9hXEzfMq04cBKVoqIu6YpNbTWEUGPwOEmqCS1qIFRCCOUQwpgzLom3xFHwQQYbaHLPJPcv9P9fnqDGwYZ0xmkGFyBQYubK5K2T11UfrH6qXW/fsRQt7VqVq5NW2EgHndd8bXkqn3pv/ML40c53Oi8tv7k8T0RdBPQJlKpY2eZc01/NK1cDQdO3TCsZy8RlrkSaqjP3z+zzD/pfPb7l+ANeePWhV7IANCCDdLes3fKy/I58euF7C++w5Y5KVN8bny0eX3SXA6GrASBJBRnJLdbarbsf3v2FI3uOfNmQST5SBm0sBmKOsztP3fnnpx87/dda65bP/Rp7Ti8HQleEwLoCg2uyIKcnH5t85I2JN372oxgEAegCuXgctPwDSLMGX6xD22dwW+lj3115ZPlRn/pFAq0qrdLNodkMQha3FpMt27dUQZiuP1l/9Nj4sc+ANhn5cWse8PzLELIADgNQbgDXA8wabKGGuyrzh5a+2noEjMW1s2udQWuQAfCbq4N2379bq4IqO+Omdj6884tHrj/yedAozn0AOYD4Q7ywDAT6CkQ8AUQJiDRAAqAADg4y7eAhXL/nxYPaLL+8/MPiZDGv31i37TPtcNETjYMNlfWyoojE1qlPTN158ksn/yr3edz+/jMYPPsNcPBwvSE462LX4wvATZsACCCc/zJ4bAIUVcAMUN4F8i6QLYPyLjjtgIYXEF9zxtx0aP8Xl15bOhLy0ErKyaA513QCADXnmtIZVxCRqIbZ8FCe5vH5P/gc3L9+D1Gjgah+DaKpOkJlHO995Vo88Z/P497z87hx/n3c+f5JvIJ9yPUYoEsQ0RggIpBQIKEBpvWISoUefSEOs+EhEYmqM67QnGtKAKQAiJm7ZiKb2WLtQG3HWxNv/XTrT38NaquHSCLAB7huFyCJbqWMrz/xj8i1RpUJkRJYM8CXBp9Bqd/Bm41/BwcCsQcHB+IAsAfIgRAgV47j7Zm3P3nzgZt3LP3H0urMXTODhdcXnGgcbFCwIVIFVSx+uvgAXgeUy6EnJpFMTUOPT0BUKgilAp767WcwXi5iOomxNZKoaolKpFFUEkuhghtP3Q3KVgDbB/kUwRtwcGAXgMCAMwgiyOKniw+ogioGG6LGwQaJ5lxTBh8iZ1xxtb5628r8oxBJAbI4Bj0+DhRiSKHx6K88hsk4xtZCgnohQi0SKGmFMaWQSIlECJz1FTzZ3o7crYFNF8IOQT4DfLqeQ2NTQA6s1ldvc8YVgw9Rc64pxcwdM0LGMpIFmbQKrUY4dQrBWnBqkK+2wamBCx55sYoxqTARK9TiGEUVIyEBRQJKEIQQkMT4w95d0OkakPeAvA/YARDMegnU7wIioFVoNWRBJjKW0cwdM0LFpVj0232FgKgbdauu2wdIQIgWqBeDrcGb1evAYDgEZMFDMsMxIzAQQGAGAjMYhBQClP0I8AHsU1A+WE/MYKD81wEA3ahb1bmOYKFK4yWhbG5JKCECB+GE09PuBSyuPAgYA5IC7BzOj+/F0Dt0rQCYASb0XI6ec0i9h+EA6z08BzAInK4AkOuhAAEE5JVrgfpZAIATToMhhBLC5pYUAKhEcZ7lUF5Zt9Npd3QJbphASgHvHCbUW+iZzwEhIFUazIzMB/S8RT8PGDhgGBx8ADR5kM8BFiMmwmCfI7nmtYv9TXllN+wCgNKR5myYBRlJX82r7eWPL9ezFxcgK1U4IoRgsWdhAe1fMDBeI1IODAHjPYYB6FqHrnNInQSIUYSBA6BGo4k5QEycBar/22SrebUtI+mDCyEZS1iZvgkQcBw4n+hNNJf3L9f3VObxw6UMJATIB4TcYHVoMIgYkRRgADkDGYC+tehbD8sBDIlf9K9AQow6KkNMnQYaI1IIAA6Y7E+eWQtrOYGc6ZsgFo4uBJ95y47T8rnym1AAvgbkSy3YlTZcZw1+MMRvPPVVtPIcFzKDpcxg2Vm0MoN27pH5ABAhlsCTt/4OxI53cTr5JOiWU8D2EYCNwa2A0tnScXac+szbhaMLQTQONryMpCFBw/bz7VejEBnsAX7qcQDWIow4673f/2fka2toZRYtF7CSewysRwgBRITAjKG6eT0PEmCP+gagRyNy0xSOQmTaz7dfJUFDGUnTONjwojnXDDKSuRBikC6mi/vO7TsMAPg5YP8fA/utA5wDO4uXvvmbCEojBAB+3TgI4MA4UNPA3tGtKwCKo8S4jAbsO7fvcLqYLgohBjKSeXOuGQQAPvfaOZt38wE7Xh0+O/x2MS/2QAA+BeAHwM2fB8wv/Txu/+arsNfdCE0Eh/Ue4Txw79YCjs/su5Q2uytpU9EWe8Nnh99mx6t5Nx+ce+2cxXodgQG4uBIPpZSd4fywuffw3mfBm3jgA8DHPv5362qiBgwP3AQu7sdB0QUm9uOVmV2XAmAA113BO3jvK3ufHZ4dnpFSduJKPBxB5YtHux90UZwoAgHov91vb792e6l1uHUDbgUwM3JxsqFC1gntWf3MOtmpXYXq0aaEfBc4cO7ACxf+8sI/wOEDttw+/8b5dMNfl+AvbytzVIyCM46H/zU807i/oVtfa92EzwKINukvjFhWeUTQxi6jzvMj0AHAU4D4E7GUvZo9LYV8Ny7GS8GGfv9CP9+omUvEz+TuSWZwAMMTyA2ODt5v/EzjQvtv27fxMis0RmA2883BKAmxqQxXAPw9gIcRqlz9blmWfy8ei9+RUi4JKXo61qYz3wlXVWCd+Q7Xrq8FkuR96q1QwqbvpYsVrrwWqWhq+C/Da3Ev6JJTGYDCphDkAF4El94pnZgsTz6iUnVIkPiAc17SBd0VJLLLRdAVMnADiLfeyUjmbuAMO+6JJXFsrDc2x+/zrfZWW8aGBDIjEAxgDVBPqMH4sfHfSkzyAg/5vZCFRZ3oZfbc07E2V1NhV9WinfkO9y/0w3hj3LnM5UIJQ0SZIJGJeXqDBnS3LdsiJgCko4Q1wJgbG0z/27bf92vhv+GwICAuIGA1HouHC0cW8lEI+KMI4o2IU2G8ABUrDjZ4qaUDw8MzbwnVd/xn/SdynccbIEhS2PU3O/+sf2JwFA4fCCGW61zvT5WmDK9xaLVa/FFVOc3OzoqTJ0/qer0ebZ/cHlVVNR6Px6Myl9VqtqpUorRpG7HNb1tbObByO9ZAqAA3HLvhpda3ll+WQi5LKXs74h02TVMopeTk5KScnp5WMzMzYsuWLXQ5oEtk4H333Sd7vV4kpSwQUUEIkTCz1lprZtZCiBhAKU3TiTP+/Xrt18cfPLXv1H3b1rY13e+6vyBPP5JStnZFu3rMnAkhcmOMIyIrhMh7vV6WJEk6NTWVHTp0yG48pmz2hGg2m6rRaIxpravOuVoURTUpZc1aWyOiqrV2ixCiQkQzZV+c+uD1873SzaU6nsar+ZIBJMW7o92QUipmLjJzCUBRSlkQQkRRFMkoioIxxk9NTYXFxUXGRe4x8sTdd98tiEiNbp0wcwFAgZkjIYSO41jmea7X90nt4B2s/kj+k7V54Iikkipm5qL3PmdmLaV0UkprrZVaa07T1AohdBRFMsuyq4ZDAND33HPPGICyMaastR4jooSZtfdeEZEUQggikt57RYAUUkqTZUEq5aWUjpk9M3siCkopB8AZY3JmTq21A+dcl5kHJ06c2BDEvNkTPDs761qtVtrr9YIxxhQKhajT6agkSbQQQnrvhfceSimhlBLDwYBARODAiS4wEbH3PjjnOEkSNsY4772P49gRkSUiY601o5YWrvY0cPGR7Pbbb5crKytyYmJClMtl0ev1ZLlcJuccee8JALz3xBzgnQcRQSoFKeXFrE/TNEgpOUmScPr06bBz587Q7Xb91q1bw+HDh/2HPZJctVeMyhatVot6vd4V39vcQOloneBsWuVymQ8fPsyzs7N47rnneNN0uaJf/A82dYTLDshwfwAAAABJRU5ErkJggg==",
  230. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAoCAYAAABw65OnAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94IDhUyEjBrr68AAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAADEVJREFUWMOdWFuMG9d5/s5lzsyQnF1y75JW1lp2LVmSoctWdWQpCKM6CBTXsB+6RdP2xUCbom2A9KFJW0N12qRXpGiDFg3iPNhNntoKdZECSWDYqInA0gJWZEW2ZFuxIlGyDGqX2huHS86c298HcqWVLDVKzwvJwZnzf/y///L9h+HnXxwAq1arLE1TtvYwSRKq1WoEgAD4n+dAdo97WLVa5fV6XU5NTUlrbdDtdkUYhrzVarGBgQHK89zHceyklKZer9upqSlbq9V8HxT9XwbEzzDOp6enpfc+GhgYKCZJMtDtdsve+wqAISllRSlV4ZwPOOcS51whz/OoXC4r55wwxrDt27dTo9H4f3mCVatVked5ACAWQpS89wPtne3N5afKn1ocX/zFeTX/wJJYGjHcqMAHuuIq18f02E+H5oZ+tO/Vfa+88cYbH3DOW865NoBuGIamVqu5O3nlTiDY9PS0nBNzkc1siQWsPPnLk9vcU+53zwyeedxxJ+/6lwyAABBe2N0ru18V3xXPix+K88aY5SiK2lmWZadOnbK3A7mdDrZh9wbZZu2YS1728OMPHn3wmdOHT//t1fjqduLEcQ/kEiPeiBoPLuxeeHrzw5v95R9evjQajnoichMTE77RaNDdPMGq1aowxsSMscoVcWXDyF+OPPfm8JufuecwbwON0mvIVq6BbA6hitjSnsFese/7C1++/pX73H0NIloKgqC7npr1IERxtBgNbhksg2HD+D+Mf+X00Okj95Q/BGAeuFz4d3Cu4L0GWQfvMjiTgwUhftX90w/mvzT/3Ba5pXHx4sXlubm5DIBbTwc7cuRIUC6Wk8hEYyPPjjxz8r6TvwkGwAJY2y7vAmAFuFr8bwSqAC4lGBNgjAEgkHcgk+PX1Sd+4bW9P83z1/L3xsbG9K5du8yFCxf8DU9Uq1WZpmlRKTV6+PDh/V/77Nde1F6HeBs4Of+PICJYrUFZFwc//hfAeP9N3/v8oPtfEGEMEYQgMHiTwZsMVnfgrYbLu7BZG7vjZ/Md3935THwyPqm1biZJslqr1SzrH6d27txZGR0dnVz86uLfvVV86/DbZ14EDyTgPJwxsJlGdzUFWi0sfvxxXFIJOlpDwuPQYBubBwIoVQADweYdeJvB5KtweRdOd2FNB2FlEk+bv/qfoT8b+uNms3n13LlzSwA0B8APHjyooigq7tu37/63ht46fP7SfyIqlRCVSgiTBKpQgIxCUJLgwpFfQzMZRiFUGIgiQEi8vFDEi5cYiAy8twB5eGf7dHmAeYA89EoDZytnP7Fv3777oygqHjx4UAHgvFqtMmOMKhQKxROHTjyOKwD3HqpUQjwwiLBYhIwicBXgynQVxUKMgThCSSnEKkAsA4RSoE0K//yegctX4a0GeQfvLIgcvO21Eu8sPPfixKETjxcKhaIxRlWrVcZrtZpwzqk8z4tL40t7L/GXwaWEVAqqUABTATgXOPvgHhTDEKUowkAUIQ4EwiCACiRCIRBxoEkxTi0z5KYLZ3OQM73A7CUBZFgCNLA0vrQ3z/Oic07VajXBDxw4wMMwVHEcR824OZVdvw7vPZyx0J0OvLFw5EFBCCUliipAMQoRBiECISC4AOMMHIAA4ZXFIpjN+8Gp4Z0GOQMAKAzfByigGTen4jiOwjBUBw4c4DJJEr6wsCCJSLVUq2zyvJezjMFqCW8t5kmCgeCIYL0H8wRPHkQEAgHUSxQCg2Ycppv23a/htQY4QN5hsv0ZYAhoqVZZa6201nJ4eJhLrTWTUnIi4pbbgEsJ3emCnANjDN57tKJB5M5BGAMGAhFDZjW6xsBYB0selgDLAfIcVnfAuOh5oF/oWZQAld53y21ARFxKybXWTAJAHMeUZRmkkyYeHw+W3n0XVgfggsM7C5FbZHoLQB7GBr264T0yo5EZB+08VsHgPIPsZwK5m7qGvMOO0h/cqM/SSbNmFwC4UoqstV4p5cq6vPgA+zSyxUXkaYpspYWs1UZhvoFOptHONNKsizTP0c4ydLRFZjRWHSH3vbiIyML7dQCIsEP+CVC6WWTLuryolHJ9uyTTNPVCCOu918PpcP36+PVxOTAANzcHLwQYEXieYzXPkTsHyXv+td7DgdB2QOoZNDjAgP18HpzfbLY71JeACdygBRYYaY9c8t5rADZNU89nZ2d9t9s11tpuciX5MQLgY/v/CGJuDmJhAWJpCbzdxrY3XseScVg2FsvGYsURmpZhwQtkfQuKPH5rywweLn8RebgJD098sQdArFMQEihdLp2x1na73a6ZnZ31vFqtOqVUzhjrLL60+LryKsco8LFf+Q641kDftZsbF9HWHnNOoOkFFrxAm3ivfRDBE3BkS6XHuwT2ZL8BBOsA9ONBeZUvvrT4OmOso5TKq9Wq47VazYdhqIUQq5sWNjW2XdlW6/kRePTpbwNagzkH5hxm6j/qZQz1uGZEfRHDsC1yeFI+3HN7CUD8UQAAsO3Ktlq30W0IIVbDMNS1Ws3faGC7du0ql0qlTc3J5p5rR699fVWtJkCvhZ977xhW2it47NHfBpaB32+eQJcJCBAMMexPGD4/9ks3eQeADwFsurXrF00xnfjqxB+OXh39cbvd/vDs2bPLaw2MANjBwcGOlHJ549zG+jff/uYLvSrUWzuLMxjdvbu3swx844HH8NmtFexgHXw7fhSfn7gNAAEY/YjuoIdee+iFzuXOJSnl8uDgYKevVoitk3lqeno64ZyPB0EwdfTo0d95//33n/rCp77Q25ECKK6L8haATl/sbLqD2HHr6PgJ8MjqIy8l30heMMbUvfdzp06dSgFoALRe6NLGjRupVCr5LMvo+PHjl5544olg5a9Xdlz49IVekNE6EGGfewIQ3QagCaDQFz1fB7Y+v3WeHWfPc85/UiqV5rXW7Uajoddy5ha1vW3bNgLgicgBsMePH7/45JNPzm14acPez9nPye+Nfw9QtxnM14FYC8IWgH8DcBS+TOXvO+a+vDHZeF4IMS+lTMMwzOv1ur+j5K/X6zQ1NeWllK7b7RohhDl//nzDWntCCDE2+/LsJjwGdstbGj1gayGuAfwHqHS+dO6TI598rpJXflAW5Q+11vOFQqEFILt9CGJ3m77SNFWFQqGYpmn5Gr82BIFxz/3m9q72s53f62xEfFPmI7kpeOW/yNX9F/cflVLWtdbX8jxfSJJkudPprCZJou80hd1xFq3X69RoNPzWrVttlmV6WA3nQ2Ioa/lWJj4Qb2IVB0xiihhe54kcKPjC6szJmT9fXFx81xhzlYjmvPdLhUKhMzs7q/sU0J3G/LuOhmmaujiOc2ttyjlfuF/ef42DXx29MPo3pclSqycaescyxfyzr/7pt+r1+nnnXINzft0Yk8ZxnDebTb9+wv9ZUzmbmZnh77zzTjA+Pq6GhoYUYyyUUirnnDTGyIniRFBoFXiow5WFRxamkYKhBGw/vf2Vi/966VXO+XUhRMo5N91uF1JKMTIyIjZs2CAnJyf54OAgazabd6WDVatVMTc3F27evLlYqVQSzvkgEQ1IKQc55wNhGCaMsaK1thDX4zzeHMeLk4tTE82J+uTfTx4D0Oaca8YYBxDGcRxbawta6xhAmKapjKIIe/bsof7g85EUXbsEKQRBULbWVpRSFSFExRhTYYyVjTGDnPMBAJPGmLHymXLaeagzXv1O9fW5a9fAhQgBQAghiahIRCUARSFEzDlXSimhlPJ5nruxsbEbg/EtIA4cOCAZYzGAIhElnPMigIJzLpJSRlJKZYxRRDRC5GNjrByeHb7YbDZzEHkw5jnnBoAlIiGEEFJK4ZzjQRCQ1tpxzrVSSmutTaPR8LenKAcQHDp0qAAgyfM8CYKgwBiLiChwzknGmOCcc8aYWPdb5HnuhRBOCGGJyBGRY4x5KaUFYPM810TUNcasWmtbRLR67ty5tQmX1o+4NDMzY5vNZjdNU5/neR7HsVpeXpZRFAWcc+Gc4845SCm5lJJ3Op21aKcoiogxRs45b62lKIooz3PrnHNhGFrGmGGM5caYvJ/Y/k5XAzdSaHp6WiwsLIjh4WGeJAlP01QkScKstcw5xwDAOceICK6vyoUQEELciPput+uFEBRFkb9w4YLfunWrb7VabnR01N9LxVz/nPXTFs1m85Yrw7VlrYEQsn8VcHOtXSnOzMzg2LFjtK67fKRY/S+/aHnarDBImQAAAABJRU5ErkJggg=="
  231. ],
  232.  
  233. // 9 = normal/selected open note UR
  234. [
  235. "data:image/png;base64,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",
  236. "data:image/png;base64,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"
  237. ],
  238. // 10 = normal/selected closed note UR
  239. [
  240. "data:image/png;base64,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",
  241. "data:image/png;base64,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"
  242. ],
  243.  
  244. // 11 = normal/selected open Elgin MP
  245. [
  246. "data:image/png;base64,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",
  247. "data:image/png;base64,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"
  248. ],
  249. // 12 - normal/selected closed Elgin MP
  250. [
  251. "data:image/png;base64,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",
  252. "data:image/png;base64,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"
  253. ],
  254.  
  255. // 13 - normal/selected open TrafficCast MP
  256. [
  257. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAoCAYAAABw65OnAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3wcGFToTAw15qgAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAABmJLR0QAAAAAAAD5Q7t/AAALL0lEQVRYw61YB1RUWRKVRnRAAZVVBkWFHXRWYVzHiCBBQMAMqAgGxIA5rXEMa04wStJB1zCG0TVgXkVEDCiSwbwzjp5VjGAD3UA3NJ1qb327GQyoeOZx3mn+7//q3Vd161b9rlev7kOEaeju7l6/a9euRvrJ13xf9/2fPgzYMG+CaRIcHGw+cuRIy8GDB7ccNGhQq759+1oHBAS08vPzazls2LDmo0aNMvfy8jLRgTL4UwD079/fyMnJySwkJMRq7ty59suWLXNfvnz50MWLF4csXLhwHO6NW7RoUSiuR+K+H6Ybru2nTp1qZWdnZwIvGX4xGJzE0Nvb2yQ0NNRqzpw5nVesWOG/c+fOlZcvX7525coV8dmzZ5UnTpzQHjt2jM6cOaO9ePFiVXp6+uvU1JTU3bt3LZs/f77vlClTOvj7+1v06tWrQVhYWN3CBPT1Bw4caA4AdgsWLPA5fPhw+NWrV++kpd0QV1ZWKrRaLfFQaaoo+8Uh+uXWBNqe609bM/tRZIY35T2Pr8y5mZV56NChRfCWO0JljdA1hl3R5wIwHDJkSJOZM2c6LFmyJPjChQvJOLlEKpXIKioq1EpVJanUVfSbOJl+yuxPm270psg0V4pKc6fodC+KTfehm69OUXlFSSnW/J6WlnYAXvQbN25ce3CmyaRJkww/FQIROGAKNzqsX79+Ija/l5iYWCmTyZQqlZLU2FyqeE7nHqyk9aldKDzNiWIyPOjIvVmU8iSOHhQn02vZA5Iri0ipVRLWyCQSyRPYubRq1aqQyZMndwJxzbBPrRwxsLS0NAbTbefNmxd47dq1m0lJSRVyuVyr0WhIo1WTRPGMDtwKo83pvSn8hjMdvjuD8qU5pNTIST9KpWVUUVFJvIZHVVWVoqioqGDfvn254NaYsWPHtuvRo0fDDwLo16+fEaYVssADITgH9Ox+jQAAfyqNgg7fmQn3u9KmDHdKehghAOORn59PIB6ZmZmRSCSimJgYqjlgR/nq1SvJhg0briIs/QIDA/+CvUTvhQFcMBs6dOh3W7duXZGSkiIpKytTqdXqakOXH0fR+uvd6ccbLpTyeLtwr6hITEhRgonqaWFhQciit0AwkREWxY4dO6QRERHLoTN/8/DweM8bRvb29pZjxozxQhZkZ2RkSMEDrd5Ifmk2bb7hDgDOlPhwI6m1KgAoIhcXl+rNcTo6evQoYS29fv2a3h2wp8Ga0qysrJvwmjvWmtXUDwNnZ2fj3r17261Zs2Ym2Py8sLBQgVEN4iiIF5nmRrtyAkks/59wDylXDSA5OZn0aVvbYK9KpVJlTk6OGKSfjPVfQ4dE+lAYgChmkOGuMHYqNze3EKHQsFH+E1f8Ttty/IUUvPgoUjB48OBBYXNjY2Ph5HqXf2zw9+Xl5RqAKILgHRgxYsQ3AwYMMKouSOBDMyibBww+hstkSqVSo198vygR2eABDehDr8ruC/esra0FEJDwzwKgH8gUTXFxseTevXsZSNVuCIlx27ZtDepBUg1RGyyROgHICHhMqtGnF4/rz3aAC660JcNHuAZpycjIiJDOdPv2barLQEi08LIM634FL3xQ6Jphf1E9xMUQ4WgFECFIzVKwWFPzZImP1kITetHBW1OF69jYWDI0NKSOHTtSXQfbLS0trcrLy3s8ceLEUciQ1ti/AXOiPkjZGnViwvnz50veBfGfB8vox1RHOnZ/gXAN5RO0AN77IhDMN5D/FTwR5uvr+y23B0K1hHBY494UeKKopKTkrXCce7gSIJzoyP1ZwjUERwDRuXPnLwLBqZqdnS3BfpNQ2Dpg/8YcDhFAtETBCgNrn4I4VTVBXHoSBU70pu05AcI1l27mhK2t7Qf14HNAIEMk06dPD0Watsf+jZiYIlTN5qzrAPEb5LUMGlGNIrcgXpDqqAwvqlAVU3FxCTVu3JhMTEzoyJEjdQLB2oNwy0HMRyiSwxEOW+xvLIgV3NJ01qxZg0+dOnUlMzOzmDPkjU5oKL8sm2Kz+lNkuiflvYgXjI0fP15I0Z49exIKHNX03Cf4oIViSlAYEyDdnq6urq1g5418A4TJtGnTnDdu3LgFglXw8uXLKoWiEstUqJAy2nMzhDZBrA7dnUYKXKOxIVNTUwEIqu5neQFFjMOnghaVoL9YijrVFV5oqutF69ULCgoyAoj26IJmnDt37g6jlUhKVFpS409JGc/2vGle0t3pbmFCtV5w1WQgTFKcjgoKCqhm0dMP9hTUUov2oJxrByrpUKilLQAYDx8+/I10t2jRwgAy2nTGjBl9w8PD49AvPn36NF8ml8s0GjQnWq2GdueNoAhkyU9ZA6lQ9lAwjmwiKysrAQhrB4OBccJB3gLBnoMSK6APRT9ggJDdunTp0lT3ivDHgHg0ROfTbvbs2ePRGyYiLEUFhQUqSK0Aolj+FEXMHdXUhWIyvauBMCfQBAkg9AUtKiqKJbo6DMg4FbwgjY+PP4qTD/D09GyNotngg40N4mQ+YcIEJ6Tr3OPHj2cDjBwk1aK3QwNTRf8VJ1F0hqfQU3IvebcggRSq0jdNr1IleAD9AkGMhM0ZIEKkSUhIkONQN0aPHj0GUu2AWmVa60uSj49PA3RWrfBwH3BkHvqDnJMnT5aLxWIViCow/F7heYoFkAhI+eY0F/SXMyjvZTwVVzz5gwPwnExeRrzu0qVLZXv27HmNArkYoXKEJlnyG9tHG13kbiMssOE2b+XKlf/Yv3//RXREJSjf6jephl6z8hntvzWRIq47AogbRad5CO3+v7L90f6HCZ24XF6uPnDggBxakrF06dIwhMEJwtSGZZr3+egbF8s4UpZbPRvUCZd169ZNjouL2wYgzxFT2rVrV/WJbxYcp925o6Ejvug33AS+bMJMSjpCaGzFW7Zs2YSMCwQROR1bskRzSiJFP/lGxkDqu7m5NYKAtcSb1Pd4tRuIz9mrV6/ehlGKQoe0UwtuV6IBfirNpazn/6aEhM3088+rFHv37v0FNWY22kVvkLAD+obmCMHnvZ/icAY1XoL5zfsruNACsm6LzHECqGCk8VKkcTEkWI06QOUytPiVcoEv6MoqoqOjI8CpIIiYIwDYIG2bsB22Bw+I6vIWLoBgArG2I52agCNtIGpd0ND6IXvWohJK8Q6qAvPp9OnTWsi9NjIyci9eHwNx8i6QdGsGwOvRRDeo8bPBp0MBAvHDDdE5NYIhMxhpht6hBRvF/x1BXA9sNBEnPgbmVwCEBuqpwgtyOrw2BQA88bwDZlsHBwdLNEwWSEtzHMS0BqBawRjofvgw4YW6Te0cHR05pp3Q+HRFwXHq06ePLzqiULh7Dcr6r3fu3KHU1FQxGuU12Gg8Zn9MF4DojjV/7969uz3stYcdGwD4GvbNkaYNa9MJvtmQT47Ff8XiztjcmU8GA/1geDCADcV3I3HvBwCOQt7vgzC9QFcWj+9j8P0/sX4Cvh8GEEMwB+CeN+65MSg+EJ5ryV7RacV73jBkd7Hr8dC3WOyIDb0wB/HmMBwET4yCoVBcr8CzmwE0Dp878LkdRqO7deu2Ft/Pgo0xuB+MtcOxzo8PgbWufDAOEw7QpDYQgiewsClmG3Yjo9e51oNPxMb4dOwV/B+g2yQI/wcyUD49Nh/Iz+HTh72I6YZw9GIAGO2YJwhLY+z1wXQVSMnpxHHjhwG+dadOnWx1Me3AwHhig+908e6M03/Pn3zN3GFS8jP4vyOvg61v+PQcBuYaA6hBztp/JGNX2djYfKUTGP6FxZxdyF5izvBkg+9O/Xc8OT15HcefM02fGXX5QU2vFcLPhToPvfWT4aem/idFXcqLPpaW/wcHON2y+MnQaAAAAABJRU5ErkJggg==",
  258. "data:image/png;base64,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"
  259. ],
  260. // 14 - normal/selected closed TrafficCast MP
  261. [
  262. "data:image/png;base64,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",
  263. "data:image/png;base64,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"
  264. ],
  265.  
  266. // 15 - normal/selected open TrafficMaster MP
  267. [
  268. "data:image/png;base64,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",
  269. "data:image/png;base64,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"
  270. ],
  271. // 16 - normal/selected closed TrafficMaster MP
  272. [
  273. "data:image/png;base64,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",
  274. "data:image/png;base64,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"
  275. ]
  276. ];
  277.  
  278. var uroMarkers =
  279. [
  280. // 0 = comment count circle
  281. ["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=="],
  282. // 1 = green comment marker
  283. ["data:image/png;base64,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"],
  284. // 2 = yellow (own) comment marker
  285. ["data:image/png;base64,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"]
  286. ];
  287.  
  288.  
  289. function uroAddLog(logtext)
  290. {
  291. if(uroShowDebugOutput) console.log('URO+: '+logtext);
  292. }
  293.  
  294. function uroGetCBChecked(cbID)
  295. {
  296. return(document.getElementById(cbID).checked);
  297. }
  298.  
  299. function uroSetCBChecked(cbID, state)
  300. {
  301. document.getElementById(cbID).checked = state;
  302. }
  303.  
  304. function uroGetElmValue(elmID)
  305. {
  306. return(document.getElementById(elmID).value);
  307. }
  308.  
  309. function uroSetStyleDisplay(elm,style)
  310. {
  311. document.getElementById(elm).style.display = style;
  312. }
  313.  
  314. function uroSetOnClick(elm,fn)
  315. {
  316. document.getElementById(elm).onclick = fn;
  317. }
  318.  
  319. function uroAddEventListener(elm,eventType,eventFn,eventBool)
  320. {
  321. document.getElementById(elm).addEventListener(eventType, eventFn, eventBool);
  322. }
  323.  
  324.  
  325. function uroFirstTimerWelcomePack()
  326. {
  327. uroAddLog('welcome new users to Club URO...');
  328.  
  329. // to be completed...
  330. }
  331.  
  332. function uroShowUpdateNotes()
  333. {
  334. uroAddLog('let existing users know what\'s new in this release');
  335.  
  336. var alertMsg = 'URO+ Update Notes...\n\n';
  337. alertMsg += 'Thanks for upgrading to URO+ '+uroVersion+' ('+uroReleaseDate+'). What\'s changed?\n\n';
  338.  
  339. var loop;
  340. if(uroChanges.length > 0)
  341. {
  342. for(loop=0; loop < uroChanges.length; loop++)
  343. {
  344. alertMsg += '* '+uroChanges[loop]+'\n';
  345. }
  346. }
  347. if((uroBetaEditor) && (uroBetaChanges.length > 0))
  348. {
  349. alertMsg += '\nFor WME Beta:\n';
  350. for(loop=0; loop < uroBetaChanges.length; loop++)
  351. {
  352. alertMsg += '* '+uroBetaChanges[loop]+'\n';
  353. }
  354. }
  355.  
  356. alert(alertMsg);
  357. }
  358.  
  359. function uroAdvertiseCustomIcons()
  360. {
  361. uroAddLog('advertise the benefits of custom UR icons...');
  362.  
  363. var confirmMsg = 'URO+ Installation/Upgrade Processing...\n\n';
  364. 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';
  365. confirmMsg += 'Markers are defined for [ROADWORKS], [CONSTRUCTION], [CLOSURE], [EVENT] and [NOTE] tags in URs, and [Elgin], [TM] and [TrafficCast] in MPs.\n\n';
  366. confirmMsg += 'Would you like me to automatically enable these custom markers?\n\n';
  367. confirmMsg += 'If you change your mind later on, they can be enabled/disabled via the Misc tab within the URO+ settings';
  368.  
  369. if(confirm(confirmMsg) === true)
  370. {
  371. uroSetCBChecked('_cbCustomRoadworksMarkers', true);
  372. uroSetCBChecked('_cbCustomConstructionMarkers', true);
  373. uroSetCBChecked('_cbCustomClosuresMarkers', true);
  374. uroSetCBChecked('_cbCustomEventsMarkers', true);
  375. uroSetCBChecked('_cbCustomNotesMarkers', true);
  376. uroSetCBChecked('_cbCustomElginMarkers', true);
  377. uroSetCBChecked('_cbCustomTrafficMasterMarkers', true);
  378. uroSetCBChecked('_cbCustomTrafficCastMarkers', true);
  379. }
  380. }
  381.  
  382.  
  383. function uroGatherSettings(container)
  384. {
  385. var options = '';
  386. var urOptions = document.getElementById(container).getElementsByTagName('input');
  387. for (var optIdx=0;optIdx<urOptions.length;optIdx++)
  388. {
  389. var id = urOptions[optIdx].id;
  390. if((id.indexOf('_cb') === 0)||(id.indexOf('_text') === 0)||(id.indexOf('_input') === 0))
  391. {
  392. options += ':' + id;
  393. if(urOptions[optIdx].type == 'checkbox') options += ',' + urOptions[optIdx].checked.toString();
  394. else if((urOptions[optIdx].type == 'text')||(urOptions[optIdx].type == 'number')) options += ',' + urOptions[optIdx].value.toString();
  395. }
  396. }
  397. return options;
  398. }
  399.  
  400.  
  401. function uroGatherCamWatchList()
  402. {
  403. var liststr = '';
  404. for(var loop=0;loop<uroCamWatchObjects.length;loop++)
  405. {
  406. var camObj = uroCamWatchObjects[loop];
  407. if((camObj.fid !== undefined) && (camObj.persistent === true))
  408. {
  409. if(loop > 0) liststr += ':';
  410.  
  411. liststr += camObj.fid+',';
  412. liststr += camObj.watch.lon+',';
  413. liststr += camObj.watch.lat+',';
  414. liststr += camObj.watch.type+',';
  415. liststr += camObj.watch.azymuth+',';
  416. liststr += camObj.watch.speed+',';
  417. liststr += camObj.watch.validated+',';
  418. liststr += camObj.groupID+',';
  419. liststr += camObj.server;
  420. }
  421. }
  422. return liststr;
  423. }
  424. function uroGatherSegWatchList()
  425. {
  426. var liststr = '';
  427. for(var loop=0;loop<uroSegWatchObjects.length;loop++)
  428. {
  429. var segObj = uroSegWatchObjects[loop];
  430. if((segObj.fid !== undefined) && (segObj.persistent === true))
  431. {
  432. if(loop > 0) liststr += ':';
  433.  
  434. liststr += segObj.fid+',';
  435. liststr += segObj.watch.left+',';
  436. liststr += segObj.watch.right+',';
  437. liststr += segObj.watch.bottom+',';
  438. liststr += segObj.watch.top+',';
  439. liststr += segObj.watch.fromNode+',';
  440. liststr += segObj.watch.toNode+',';
  441. liststr += segObj.watch.fwdDir+',';
  442. liststr += segObj.watch.revDir+',';
  443. liststr += segObj.watch.length+',';
  444. liststr += segObj.watch.level+',';
  445. liststr += segObj.watch.rank+',';
  446. liststr += segObj.watch.roadType+',';
  447. liststr += segObj.watch.updatedOn+',';
  448. liststr += segObj.groupID+',';
  449. liststr += segObj.server;
  450. }
  451. }
  452. return liststr;
  453. }
  454. function uroGatherPlaceWatchList()
  455. {
  456. var liststr = '';
  457. for(var loop=0;loop<uroPlaceWatchObjects.length;loop++)
  458. {
  459. var placeObj = uroPlaceWatchObjects[loop];
  460. if((placeObj.fid !== undefined) && (placeObj.persistent === true))
  461. {
  462. if(loop > 0) liststr += ':';
  463.  
  464. liststr += placeObj.fid+',';
  465. liststr += placeObj.watch.left+',';
  466. liststr += placeObj.watch.right+',';
  467. liststr += placeObj.watch.bottom+',';
  468. liststr += placeObj.watch.top+',';
  469. liststr += placeObj.watch.name+',';
  470. liststr += placeObj.watch.imageCount+',';
  471. liststr += placeObj.watch.residential+',';
  472. liststr += placeObj.watch.updatedOn+',';
  473. liststr += placeObj.groupID+',';
  474. liststr += placeObj.server;
  475. }
  476. }
  477. return liststr;
  478. }
  479. function uroGatherCWLGroups()
  480. {
  481. var liststr = '';
  482. for(var loop=0;loop<uroCWLGroups.length;loop++)
  483. {
  484. var groupObj = uroCWLGroups[loop];
  485. if(groupObj.groupID != -1)
  486. {
  487. if(loop > 0) liststr += ':';
  488.  
  489. liststr += groupObj.groupID+',';
  490. liststr += groupObj.groupName+',';
  491. liststr += groupObj.groupCollapsed;
  492. }
  493. }
  494. return liststr;
  495. }
  496. function uroGatherPlacesGroups()
  497. {
  498. var liststr = '';
  499. for(var loop=0;loop<uroPlacesGroupsCollapsed.length;loop++)
  500. {
  501. if(loop > 0) liststr += ':';
  502. liststr += uroPlacesGroupsCollapsed[loop];
  503. }
  504. return liststr;
  505. }
  506. function uroGatherFriendlyAreaNames()
  507. {
  508. var liststr = '';
  509. for(var loop=0;loop<uroFriendlyAreaNames.length;loop++)
  510. {
  511. var fnObj = uroFriendlyAreaNames[loop];
  512. if(loop > 0) liststr += ':';
  513.  
  514. liststr += fnObj.fName+',';
  515. liststr += fnObj.area+',';
  516. liststr += fnObj.server;
  517. }
  518. return liststr;
  519. }
  520.  
  521. function uroSaveSettings()
  522. {
  523. if(uroInhibitSave)
  524. {
  525. uroAddLog('save inhibited');
  526. return;
  527. }
  528.  
  529. if (localStorage)
  530. {
  531. localStorage.UROverviewUROptions = uroGatherSettings('uroCtrlURs');
  532. localStorage.UROverviewMPOptions = uroGatherSettings('uroCtrlMPs');
  533. localStorage.UROverviewCameraOptions = uroGatherSettings('uroCtrlCameras');
  534. localStorage.UROverviewMiscOptions = uroGatherSettings('uroCtrlMisc');
  535. localStorage.UROverviewPlacesOptions = uroGatherSettings('uroCtrlPlaces');
  536. localStorage.UROverviewCamWatchList = uroGatherCamWatchList();
  537. localStorage.UROverviewSegWatchList = uroGatherSegWatchList();
  538. localStorage.UROverviewPlaceWatchList = uroGatherPlaceWatchList();
  539. localStorage.UROverviewCWLGroups = uroGatherCWLGroups();
  540. localStorage.UROverviewFriendlyAreaNames = uroGatherFriendlyAreaNames();
  541. localStorage.UROverviewPlacesGroups = uroGatherPlacesGroups();
  542.  
  543. localStorage.UROverviewMasterEnable = uroGetCBChecked('_cbMasterEnable');
  544. localStorage.UROverviewCurrentVersion = uroVersion;
  545.  
  546. uroAddLog('save complete');
  547. }
  548. else
  549. {
  550. uroAddLog('no localStorage, save blocked');
  551. }
  552. }
  553.  
  554. function uroApplySettings(settings)
  555. {
  556. var options = settings.split(':');
  557. for(var optIdx=0;optIdx<options.length;optIdx++)
  558. {
  559. var fields = options[optIdx].split(',');
  560. if(fields[0].indexOf('_cb') === 0)
  561. {
  562. if(document.getElementById(fields[0]) !== null)
  563. {
  564. uroSetCBChecked(fields[0], (fields[1] == 'true'));
  565. }
  566. }
  567. else if((fields[0].indexOf('_input') === 0)||(fields[0].indexOf('_text') === 0))
  568. {
  569. if(document.getElementById(fields[0]) !== null) document.getElementById(fields[0]).value = fields[1];
  570. }
  571. }
  572. }
  573.  
  574.  
  575. function uroApplyCamWatchList()
  576. {
  577. var objects = localStorage.UROverviewCamWatchList.split(':');
  578. uroCamWatchObjects = [];
  579. if(objects.length > 0)
  580. {
  581. for(var objIdx=0;objIdx<objects.length;objIdx++)
  582. {
  583. var fields = objects[objIdx].split(',');
  584. if(fields.length >= 7)
  585. {
  586. // following two bits of code add in blank fields if the user has updated their copy of URO+ from an
  587. // older version which didn't include support for either of these field types
  588.  
  589. // add default groupID field
  590. if(fields.length == 7)
  591. {
  592. fields.push(0);
  593. }
  594. // set default groupID value to 0 (no group)
  595. if(fields[7] == -1)
  596. {
  597. fields[7] = 0;
  598. }
  599.  
  600. // add default server field
  601. if(fields.length == 8)
  602. {
  603. fields.push('??');
  604. }
  605. // set default server value to unknown
  606. if(fields[8] === 0)
  607. {
  608. fields[8] = '??';
  609. }
  610.  
  611. uroCamWatchObjects.push(new uroCamWatchObj(true,fields[0],fields[1],fields[2],fields[3],fields[4],fields[5],fields[6],fields[7],fields[8]));
  612. }
  613. }
  614. }
  615. }
  616. function uroApplySegWatchList()
  617. {
  618. var objects = localStorage.UROverviewSegWatchList.split(':');
  619. uroSegWatchObjects = [];
  620.  
  621. for(var objIdx=0;objIdx<objects.length;objIdx++)
  622. {
  623. var fields = objects[objIdx].split(',');
  624. 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]));
  625. }
  626. }
  627. function uroApplyPlaceWatchList()
  628. {
  629. var objects = localStorage.UROverviewPlaceWatchList.split(':');
  630. uroPlaceWatchObjects = [];
  631.  
  632. for(var objIdx=0;objIdx<objects.length;objIdx++)
  633. {
  634. var fields = objects[objIdx].split(',');
  635. 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]));
  636. }
  637. }
  638.  
  639. function uroApplyCWLGroups()
  640. {
  641. var objects = localStorage.UROverviewCWLGroups.split(':');
  642. uroCWLGroups = [];
  643.  
  644. for(var objIdx=0;objIdx<objects.length;objIdx++)
  645. {
  646. var fields = objects[objIdx].split(',');
  647. if(fields.length < 2)
  648. {
  649. fields.push(false);
  650. }
  651. uroCWLGroups.push(new uroOWLGroupObj(fields[0],fields[1],(fields[2] == 'true')));
  652. }
  653. }
  654.  
  655. function uroApplyPlacesGroups()
  656. {
  657. var t = localStorage.UROverviewPlacesGroups.split(':');
  658. for(var i=0;i<t.length;i++)
  659. {
  660. uroPlacesGroupsCollapsed[i] = (t[i] == "true");
  661. }
  662. }
  663.  
  664.  
  665. function uroApplyFriendlyAreaNames()
  666. {
  667. var objects = localStorage.UROverviewFriendlyAreaNames.split(':');
  668. uroFriendlyAreaNames = [];
  669.  
  670. for(var objIdx=0;objIdx<objects.length;objIdx++)
  671. {
  672. var fields = objects[objIdx].split(',');
  673. uroFriendlyAreaNames.push(new uroAFNObj(fields[0],parseFloat(fields[1]),fields[2]));
  674. }
  675.  
  676. uroReplaceAreaNames(true);
  677. }
  678.  
  679. function uroLoadSettings()
  680. {
  681. var isNewInstall = true;
  682. var isUpgradeInstall = true;
  683. var notifyAboutCustomIcons = true;
  684.  
  685. uroAddLog('loadSettings()');
  686. if (localStorage.UROverviewUROptions !== undefined)
  687. {
  688. uroAddLog('recover UR tab settings');
  689. uroApplySettings(localStorage.UROverviewUROptions);
  690. isNewInstall = false;
  691. }
  692.  
  693. if (localStorage.UROverviewCameraOptions !== undefined)
  694. {
  695. uroAddLog('recover camera tab settings');
  696. uroApplySettings(localStorage.UROverviewCameraOptions);
  697. isNewInstall = false;
  698. }
  699.  
  700. if (localStorage.UROverviewMPOptions !== undefined)
  701. {
  702. uroAddLog('recover MP tab settings');
  703. uroApplySettings(localStorage.UROverviewMPOptions);
  704. isNewInstall = false;
  705. }
  706.  
  707. if (localStorage.UROverviewPlacesOptions !== undefined)
  708. {
  709. uroAddLog('recover Places tab settings');
  710. uroApplySettings(localStorage.UROverviewPlacesOptions);
  711. isNewInstall = false;
  712. }
  713.  
  714. if (localStorage.UROverviewMiscOptions !== undefined)
  715. {
  716. uroAddLog('recover misc tab settings');
  717. uroApplySettings(localStorage.UROverviewMiscOptions);
  718. isNewInstall = false;
  719.  
  720. if(localStorage.UROverviewCurrentVersion !== undefined)
  721. {
  722. notifyAboutCustomIcons = false;
  723. }
  724. else
  725. {
  726. if(uroGetCBChecked('_cbCustomRoadworksMarkers') === true) notifyAboutCustomIcons = false;
  727. if(uroGetCBChecked('_cbCustomConstructionMarkers')=== true) notifyAboutCustomIcons = false;
  728. if(uroGetCBChecked('_cbCustomClosuresMarkers') === true) notifyAboutCustomIcons = false;
  729. if(uroGetCBChecked('_cbCustomEventsMarkers') === true) notifyAboutCustomIcons = false;
  730. if(uroGetCBChecked('_cbCustomNotesMarkers') === true) notifyAboutCustomIcons = false;
  731. }
  732. }
  733.  
  734. if(localStorage.UROverviewCWLGroups !== undefined)
  735. {
  736. uroAddLog('recover CWL groups');
  737. uroApplyCWLGroups();
  738. isNewInstall = false;
  739. }
  740. else
  741. {
  742. uroAddLog('set default CWL group');
  743. uroCWLGroups.push(new uroOWLGroupObj(0,'No group',false));
  744. }
  745.  
  746. if(localStorage.UROverviewCamWatchList !== undefined)
  747. {
  748. uroAddLog('recover camera watchlist');
  749. uroApplyCamWatchList();
  750. uroGetCurrentCamWatchListObjects();
  751. isNewInstall = false;
  752. }
  753.  
  754. if(localStorage.UROverviewSegWatchList !== undefined)
  755. {
  756. uroAddLog('recover segment watchlist');
  757. uroApplySegWatchList();
  758. uroGetCurrentSegWatchListObjects();
  759. isNewInstall = false;
  760. }
  761.  
  762. if(localStorage.UROverviewPlaceWatchList !== undefined)
  763. {
  764. uroAddLog('recover places watchlist');
  765. uroApplyPlaceWatchList();
  766. //uroGetCurrentPlaceWatchListObjects();
  767. isNewInstall = false;
  768. }
  769.  
  770. if(localStorage.UROverviewPlacesGroups !== undefined)
  771. {
  772. uroAddLog('recover places groups');
  773. uroApplyPlacesGroups();
  774. isNewInstall = false;
  775. }
  776.  
  777. if(localStorage.UROverviewCurrentVersion !== undefined)
  778. {
  779. uroAddLog('comparing install versions');
  780. if(localStorage.UROverviewCurrentVersion == uroVersion)
  781. {
  782. isUpgradeInstall = false;
  783. }
  784. }
  785.  
  786. if(localStorage.UROverviewFriendlyAreaNames !== undefined)
  787. {
  788. uroAddLog('recover friendly area names');
  789. uroApplyFriendlyAreaNames();
  790. isNewInstall = false;
  791. }
  792.  
  793. if(localStorage.UROverviewMasterEnable !== undefined)
  794. {
  795. uroAddLog('recover master enable state');
  796. document.getElementById('_cbMasterEnable').checked = (localStorage.UROverviewMasterEnable == "true");
  797. }
  798.  
  799. if(isNewInstall)
  800. {
  801. uroFirstTimerWelcomePack();
  802. }
  803. else if(isUpgradeInstall)
  804. {
  805. uroShowUpdateNotes();
  806. }
  807.  
  808. if(notifyAboutCustomIcons)
  809. {
  810. uroAdvertiseCustomIcons();
  811. }
  812.  
  813. uroInhibitSave = false;
  814. }
  815.  
  816. function uroDefaultSettings()
  817. {
  818. if(confirm('Resetting URO+ settings cannot be undone\nAre you sure you want to do this?') === true)
  819. {
  820. var defaultSettings = '';
  821. 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]';
  822. defaultSettings += '[UROverviewPlacesGroups][len=59]false:false:false:false:false:false:false:false:false:false[END]';
  823. defaultSettings += '[UROverviewCamWatchList][len=0][END]';
  824. defaultSettings += '[UROverviewFriendlyAreaNames][len=0][END]';
  825. defaultSettings += '[UROverviewMiscOptions][len=1141]:_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,false:_cbTimeFmt12H,false:_cbWhiteBackground,false:_inputCustomBackgroundRed,255:_inputCustomBackgroundGreen,255:_inputCustomBackgroundBlue,255:_cbHideAMLayer,false:_cbDisablePlacesFiltering,false:_cbInhibitNURButton,false:_cbInhibitNMPButton,false:_cbInhibitNPURButton,false:_cbInhibitURCentering,false:_cbInhibitMPCentering,false:_cbInhibitPURCentering,false:_cbHideEditorInfo,false:_cbEnableDTE,false[END]';
  826. defaultSettings += '[UROverviewSegWatchList][len=0][END]';
  827. 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]';
  828. defaultSettings += '[UROverviewUROptions][len=1601]:_cbURFilterOutsideArea,false:_cbNoFilterForURInURL,false:_cbFilterWazeAuto,false:_cbFilterIncorrectTurn,false:_cbFilterIncorrectAddress,false:_cbFilterIncorrectRoute,false:_cbFilterMissingRoundabout,false:_cbFilterGeneralError,false:_cbFilterTurnNotAllowed,false:_cbFilterIncorrectJunction,false:_cbFilterMissingBridgeOverpass,false:_cbFilterWrongDrivingDirection,false:_cbFilterMissingExit,false:_cbFilterMissingRoad,false:_cbFilterBlockedRoad,false:_cbFilterMissingLandmark,false:_cbFilterUndefined,false:_cbFilterRoadworks,false:_cbFilterConstruction,false:_cbFilterClosure,false:_cbFilterEvent,false:_cbFilterNote,false:_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]';
  829. 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]';
  830. defaultSettings += '[UROverviewMasterEnable][len=4]true[END]';
  831. defaultSettings += '[UROverviewPlaceWatchList][len=0][END]';
  832. defaultSettings += '[UROverviewCurrentVersion][len=0][END]';
  833. defaultSettings += '[UROverviewCWLGroups][len=16]0,No group,false[END]';
  834. document.getElementById('_txtSettings').value = defaultSettings;
  835. uroTextToSettings();
  836. document.getElementById('_txtSettings').value = '';
  837. }
  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 < 50) && (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 '+idList.length+' updateRequestSessions, 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. if(uroGetCBChecked('_cbMasterEnable') === true)
  2357. {
  2358. if(customType === 0) useCustomMarker = (uroGetCBChecked('_cbCustomRoadworksMarkers'));
  2359. else if(customType === 1) useCustomMarker = (uroGetCBChecked('_cbCustomConstructionMarkers'));
  2360. else if(customType === 2) useCustomMarker = (uroGetCBChecked('_cbCustomClosuresMarkers'));
  2361. else if(customType === 3) useCustomMarker = (uroGetCBChecked('_cbCustomEventsMarkers'));
  2362. else if(customType === 4) useCustomMarker = (uroGetCBChecked('_cbCustomNotesMarkers'));
  2363. else if(customType === 100) useCustomMarker = (uroGetCBChecked('_cbCustomElginMarkers'));
  2364. else if(customType === 101) useCustomMarker = (uroGetCBChecked('_cbCustomTrafficCastMarkers'));
  2365. else if(customType === 102) useCustomMarker = (uroGetCBChecked('_cbCustomTrafficMasterMarkers'));
  2366. }
  2367. if(!useCustomMarker) customType = -1;
  2368. uroCustomMarkerList.push(new uroACMObj(urID, customType, hasMyComments, nComments));
  2369. }
  2370.  
  2371. function uroRenderCustomMarkers(markerType)
  2372. {
  2373. var urID;
  2374. var elmID;
  2375. var newSpan;
  2376. var divElem;
  2377. var objIdx;
  2378. var customType;
  2379. var customMarker;
  2380.  
  2381. if(markerType == 'ur')
  2382. {
  2383. var useDefaultConvoMarker = false;
  2384. var addCommentCount = false;
  2385.  
  2386. if(uroGetCBChecked('_cbMasterEnable') === true)
  2387. {
  2388. if((uroGetCBChecked('_cbNativeConvoMarkers')) && (uroBetaEditor === false)) useDefaultConvoMarker = true;
  2389. if((uroGetCBChecked('_cbNativeBetaConvoMarkers')) && (uroBetaEditor === true)) useDefaultConvoMarker = true;
  2390. if(uroGetCBChecked('_cbCommentCount')) addCommentCount = true;
  2391. }
  2392. else
  2393. {
  2394. useDefaultConvoMarker = true;
  2395. }
  2396.  
  2397. var uRCM_masterEnable = uroGetCBChecked('_cbMasterEnable');
  2398. divElem = document.getElementById(W.map.updateRequestLayer.id);
  2399. if(divElem.childNodes.length > 0)
  2400. {
  2401. for(objIdx = 0; objIdx < uroCustomMarkerList.length; objIdx++)
  2402. {
  2403. customType = -1;
  2404. var cmlObj = uroCustomMarkerList[objIdx];
  2405. if(uRCM_masterEnable === true)
  2406. {
  2407. customType = cmlObj.customType;
  2408. }
  2409. if(customType < 100)
  2410. {
  2411. urID = cmlObj.urID;
  2412. var nComments = cmlObj.nComments;
  2413. var iconObj = W.map.updateRequestLayer.markers[urID].icon;
  2414. newSpan = '';
  2415.  
  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. elmID = "customMarker_"+urID;
  2481. customMarker = '';
  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.mapUpdateRequests.objects[urID] !== undefined)
  2490. {
  2491. if(W.model.mapUpdateRequests.objects[urID].attributes.open === false) customType += 1;
  2492. }
  2493. customMarker = '<img src="'+uroIcons[customType][0]+'">';
  2494. }
  2495. else
  2496. {
  2497. if(document.getElementById(elmID) !== null)
  2498. {
  2499. document.getElementById(elmID).remove();
  2500. }
  2501. }
  2502. if(newSpan !== '')
  2503. {
  2504. iconObj.$div.prepend(newSpan);
  2505. if(customMarker !== '')
  2506. {
  2507. if(document.getElementById(elmID) !== null)
  2508. {
  2509. document.getElementById(elmID).innerHTML = customMarker;
  2510. }
  2511. }
  2512.  
  2513. if(addCommentCount)
  2514. {
  2515. var styleLeft;
  2516. if(nComments < 10) styleLeft = '11px';
  2517. else if(nComments < 100) styleLeft = '8px';
  2518. else styleLeft = '5px';
  2519. elmID = "commentCount_"+urID;
  2520. if(document.getElementById(elmID+"_inner") !== null)
  2521. {
  2522. document.getElementById(elmID+"_inner").innerHTML = nComments;
  2523. document.getElementById(elmID+"_inner").style.left = styleLeft;
  2524. }
  2525. }
  2526. }
  2527. }
  2528. }
  2529. }
  2530. }
  2531.  
  2532. else if(markerType == 'mp')
  2533. {
  2534. divElem = document.getElementById(W.map.problemLayer.id);
  2535. if(divElem.childNodes.length > 0)
  2536. {
  2537. for(objIdx = 0; objIdx < uroCustomMarkerList.length; objIdx++)
  2538. {
  2539. customType = uroCustomMarkerList[objIdx].customType;
  2540. if((customType >= 100) || (customType == -1))
  2541. {
  2542. urID = uroCustomMarkerList[objIdx].urID;
  2543. elmID = "customMarker_"+urID;
  2544. if(customType != -1)
  2545. {
  2546. if(document.getElementById(elmID) === null)
  2547. {
  2548. newSpan = '<span id="'+elmID+'" style="position:absolute;pointer-events:none;"></span>';
  2549. if(W.map.problemLayer.markers[urID] !== undefined)
  2550. {
  2551. W.map.problemLayer.markers[urID].icon.$div.prepend(newSpan);
  2552. }
  2553. }
  2554. if(document.getElementById(elmID) !== null)
  2555. {
  2556. customType = uroGetCustomMarkerIdx(customType);
  2557. if(W.model.problems.objects[urID] !== undefined)
  2558. {
  2559. if(W.model.problems.objects[urID].attributes.open === false) customType += 1;
  2560. }
  2561. customMarker = '<img src="'+uroIcons[customType][0]+'">';
  2562. document.getElementById(elmID).innerHTML = customMarker;
  2563. }
  2564. }
  2565. else
  2566. {
  2567. if(document.getElementById(elmID) !== null)
  2568. {
  2569. document.getElementById(elmID).remove();
  2570. }
  2571. }
  2572. }
  2573. }
  2574. }
  2575. }
  2576. }
  2577.  
  2578.  
  2579. function uroChangeCustomMarkers(urID,isHighlighted,customType,markerType)
  2580. {
  2581. if(document.getElementById('customMarker_'+urID) !== null)
  2582. {
  2583. if(markerType == "ur")
  2584. {
  2585. if(W.model.updateRequestSessions.objects[urID].open === false) customType += 1;
  2586. }
  2587. else if(markerType == "mp")
  2588. {
  2589. if(W.model.problems.objects[urID].attributes.open === false) customType += 1;
  2590. }
  2591.  
  2592. if(isHighlighted === true)
  2593. {
  2594. document.getElementById('customMarker_'+urID).innerHTML = '<img src="'+uroIcons[customType][1]+'">';
  2595. }
  2596. else
  2597. {
  2598. document.getElementById('customMarker_'+urID).innerHTML = '<img src="'+uroIcons[customType][0]+'">';
  2599. }
  2600. }
  2601. }
  2602.  
  2603. function uroFilterPlaces()
  2604. {
  2605. if(uroFilterPreamble() === false) return;
  2606.  
  2607. if(uroPlaceSelected === true) return;
  2608.  
  2609. if(uroGetCBChecked('_cbDisablePlacesFiltering') === true) return;
  2610.  
  2611. var filterCats = [];
  2612. for(var i=0; i<W.Config.venues.categories.length; i++)
  2613. {
  2614. var parentCategory = W.Config.venues.categories[i];
  2615. var subCategory;
  2616.  
  2617. if(uroGetCBChecked('_cbPlacesFilter-'+parentCategory) === true)
  2618. {
  2619. filterCats.push(parentCategory);
  2620. for(var i1=0; i1<W.Config.venues.subcategories[parentCategory].length; i1++)
  2621. {
  2622. subCategory = W.Config.venues.subcategories[parentCategory][i1];
  2623. filterCats.push(subCategory);
  2624. }
  2625. }
  2626. else
  2627. {
  2628. for(var i2=0; i2<W.Config.venues.subcategories[parentCategory].length; i2++)
  2629. {
  2630. subCategory = W.Config.venues.subcategories[parentCategory][i2];
  2631. if(uroGetCBChecked('_cbPlacesFilter-'+subCategory) === true)
  2632. {
  2633. filterCats.push(subCategory);
  2634. }
  2635. }
  2636. }
  2637. }
  2638.  
  2639. var placeStyle;
  2640.  
  2641. var uFP_filterEditedLessThan = uroGetCBChecked('_cbPlaceFilterEditedLessThan');
  2642. var uFP_filterEditedMoreThan = uroGetCBChecked('_cbPlaceFilterEditedMoreThan');
  2643. var uFP_filterL0 = uroGetCBChecked('_cbHidePlacesL0');
  2644. var uFP_filterL1 = uroGetCBChecked('_cbHidePlacesL1');
  2645. var uFP_filterL2 = uroGetCBChecked('_cbHidePlacesL2');
  2646. var uFP_filterL3 = uroGetCBChecked('_cbHidePlacesL3');
  2647. var uFP_filterL4 = uroGetCBChecked('_cbHidePlacesL4');
  2648. var uFP_filterL5 = uroGetCBChecked('_cbHidePlacesL5');
  2649. var uFP_filterOnLockLevel = (uFP_filterL0 || uFP_filterL1 || uFP_filterL2 || uFP_filterL3 || uFP_filterL4 || uFP_filterL5);
  2650. var uFP_filterNoPhotos = uroGetCBChecked('_cbHideNoPhotoPlaces');
  2651. var uFP_filterWithPhotos = uroGetCBChecked('_cbHidePhotoPlaces');
  2652. var uFP_filterPrivate = uroGetCBChecked('_cbFilterPrivatePlaces');
  2653. var uFP_invertFilters = uroGetCBChecked('_cbInvertPlacesFilter');
  2654. var uFP_masterEnable = uroGetCBChecked('_cbMasterEnable');
  2655. var uFP_thresholdMinDays = document.getElementById('_inputFilterPlaceEditMinDays').value;
  2656. var uFP_thresholdMaxDays = document.getElementById('_inputFilterPlaceEditMaxDays').value;
  2657. for(var v=0; v<W.map.landmarkLayer.features.length; v++)
  2658. {
  2659. placeStyle = 'visible';
  2660. if(uFP_masterEnable === true)
  2661. {
  2662. var lmObj = W.map.landmarkLayer.features[v];
  2663.  
  2664. // when an area place is selected, the drag points for editing the place outline now get added as objects into W.map.landmarkLayer.features,
  2665. // however none of these objects have the .model property - we must therefore check each entry in features[] to see if it has .model before
  2666. // attempting to filter it...
  2667. if(lmObj.model !== undefined)
  2668. {
  2669. if(lmObj.model.attributes.id < 0)
  2670. {
  2671. // don't apply filtering to newly-created places - this allows the user to leave their filtering settings unchanged whilst
  2672. // adding a new place which, once saved, would then be hidden...
  2673. break;
  2674. }
  2675.  
  2676. if((uFP_filterEditedLessThan) || (uFP_filterEditedMoreThan))
  2677. {
  2678. var editDate = lmObj.model.attributes.updatedOn;
  2679. if(editDate === undefined)
  2680. {
  2681. // where a place has never been edited since its creation, use the creation date instead...
  2682. editDate = lmObj.model.attributes.createdOn;
  2683. }
  2684. if(editDate !== undefined)
  2685. {
  2686. var editDaysAgo = uroDateToDays(editDate);
  2687. if(uFP_filterEditedLessThan)
  2688. {
  2689. if(editDaysAgo < uFP_thresholdMinDays)
  2690. {
  2691. placeStyle = 'hidden';
  2692. }
  2693. }
  2694. if(uFP_filterEditedMoreThan)
  2695. {
  2696. if(editDaysAgo > uFP_thresholdMaxDays)
  2697. {
  2698. placeStyle = 'hidden';
  2699. }
  2700. }
  2701. }
  2702. }
  2703.  
  2704. if(placeStyle == 'visible')
  2705. {
  2706. if(uFP_filterOnLockLevel)
  2707. {
  2708. var lockLevel = lmObj.model.attributes.lockRank;
  2709. if ((uFP_filterL0) && (lockLevel === 0)) placeStyle = 'hidden';
  2710. if ((uFP_filterL1) && (lockLevel === 1)) placeStyle = 'hidden';
  2711. if ((uFP_filterL2) && (lockLevel === 2)) placeStyle = 'hidden';
  2712. if ((uFP_filterL3) && (lockLevel === 3)) placeStyle = 'hidden';
  2713. if ((uFP_filterL4) && (lockLevel === 4)) placeStyle = 'hidden';
  2714. if ((uFP_filterL5) && (lockLevel === 5)) placeStyle = 'hidden';
  2715. }
  2716. }
  2717.  
  2718. if(placeStyle == 'visible')
  2719. {
  2720. if(uFP_filterNoPhotos || uFP_filterWithPhotos)
  2721. {
  2722. var nPhotos = 0;
  2723. for(var loop=0; loop<lmObj.model.attributes.images.length; loop++)
  2724. {
  2725. if(lmObj.model.attributes.images[loop].attributes.approved) nPhotos++;
  2726. }
  2727. if((uFP_filterNoPhotos) && (nPhotos === 0)) placeStyle = 'hidden';
  2728. if((uFP_filterWithPhotos) && (nPhotos !== 0)) placeStyle = 'hidden';
  2729. }
  2730. }
  2731.  
  2732.  
  2733. if(placeStyle == 'visible')
  2734. {
  2735. if((uFP_filterPrivate === true) && (lmObj.model.attributes.residential === true))
  2736. {
  2737. placeStyle = 'hidden';
  2738. }
  2739. else
  2740. {
  2741. for(var cat=0; cat<filterCats.length; cat++)
  2742. {
  2743. if(lmObj.model.attributes.categories.contains(filterCats[cat]))
  2744. {
  2745. placeStyle = 'hidden';
  2746. break;
  2747. }
  2748. }
  2749. }
  2750. }
  2751. }
  2752.  
  2753. if(uFP_invertFilters === true)
  2754. {
  2755. if(placeStyle == 'hidden') placeStyle = 'visible';
  2756. else placeStyle = 'hidden';
  2757. }
  2758. }
  2759.  
  2760. var geoID = W.map.landmarkLayer.features[v].geometry.id;
  2761. if(document.getElementById(geoID) !== null)
  2762. {
  2763. document.getElementById(geoID).style.visibility = placeStyle;
  2764. }
  2765. }
  2766. var uFP_filterUneditable = uroGetCBChecked('_cbFilterUneditablePlaceUpdates');
  2767. var uFP_filterLockRanked = uroGetCBChecked('_cbFilterLockRankedPlaceUpdates');
  2768. var uFP_filterFlagged = uroGetCBChecked("_cbFilterFlaggedPUR");
  2769. var uFP_filterNewPlace = uroGetCBChecked("_cbFilterNewPlacePUR");
  2770. var uFP_filterUpdatedDetails = uroGetCBChecked("_cbFilterUpdatedDetailsPUR");
  2771. var uFP_filterNewPhoto = uroGetCBChecked("_cbFilterNewPhotoPUR");
  2772. var uFP_filterMinPURAge = uroGetCBChecked('_cbEnablePURMinAgeFilter');
  2773. var uFP_filterMaxPURAge = uroGetCBChecked('_cbEnablePURMaxAgeFilter');
  2774. var uFP_invertPURFilters = uroGetCBChecked('_cbInvertPURFilters');
  2775. var uFP_filterHighSeverity = uroGetCBChecked('_cbPURFilterHighSeverity');
  2776. var uFP_filterMedSeverity = uroGetCBChecked('_cbPURFilterMediumSeverity');
  2777. var uFP_filterLowSeverity = uroGetCBChecked('_cbPURFilterLowSeverity');
  2778. var uFP_leavePURGeos = uroGetCBChecked('_cbLeavePURGeos');
  2779. var uFP_thresholdMinPURDays = uroGetElmValue('_inputPURFilterMinDays');
  2780. var uFP_thresholdMaxPURDays = uroGetElmValue('_inputPURFilterMaxDays');
  2781. var uFP_isLoggedIn = W.loginManager.isLoggedIn();
  2782. var uFP_userRank = W.loginManager.user.rank;
  2783. var purAge = null;
  2784. for(var pu in W.map.placeUpdatesLayer.markers)
  2785. {
  2786. if(W.map.placeUpdatesLayer.markers.hasOwnProperty(pu))
  2787. {
  2788. var puObj = W.map.placeUpdatesLayer.markers[pu];
  2789. if(uroGetCBChecked('_cbInhibitPURCentering') === true)
  2790. {
  2791. // same style of fix as for UR markers...
  2792. puObj.model.geometry.getBounds = uroStopThatDamnedRecentering;
  2793. }
  2794. if(W.map.placeUpdatesLayer.getVisibility() === true)
  2795. {
  2796. placeStyle = 'visible';
  2797. if(uFP_masterEnable === true)
  2798. {
  2799. if(uFP_masterEnable === true)
  2800. {
  2801. if(uFP_filterUneditable === true)
  2802. {
  2803. if(puObj.model.attributes.permissions === 0)
  2804. {
  2805. placeStyle = 'hidden';
  2806. }
  2807. if((placeStyle == 'visible') && (uFP_isLoggedIn))
  2808. {
  2809. if(uFP_userRank < puObj.model.attributes.lockRank)
  2810. {
  2811. placeStyle = 'hidden';
  2812. }
  2813. }
  2814. if((placeStyle == 'visible') && (puObj.model.attributes.adLocked))
  2815. {
  2816. placeStyle = 'hidden';
  2817. }
  2818. }
  2819.  
  2820. if((placeStyle == 'visible') && (uFP_filterLockRanked === true))
  2821. {
  2822. if(puObj.model.attributes.lockRank !== 0)
  2823. {
  2824. placeStyle = 'hidden';
  2825. }
  2826. }
  2827.  
  2828. if((placeStyle == 'visible') && (uFP_filterFlagged === true))
  2829. {
  2830. if(puObj.icon.imageDiv.className.indexOf('flag') != -1)
  2831. {
  2832. placeStyle = 'hidden';
  2833. }
  2834. }
  2835. if((placeStyle == 'visible') && (uFP_filterNewPlace === true))
  2836. {
  2837. if(puObj.icon.imageDiv.className.indexOf('add_venue') != -1)
  2838. {
  2839. placeStyle = 'hidden';
  2840. }
  2841. }
  2842. if((placeStyle == 'visible') && (uFP_filterUpdatedDetails === true))
  2843. {
  2844. if((puObj.icon.imageDiv.className.indexOf('update_venue') != -1) || (puObj.icon.imageDiv.className.indexOf('multiple') != -1))
  2845. {
  2846. placeStyle = 'hidden';
  2847. }
  2848. }
  2849. if((placeStyle == 'visible') && (uFP_filterNewPhoto === true))
  2850. {
  2851. if(puObj.icon.imageDiv.className.indexOf('add_image') != -1)
  2852. {
  2853. placeStyle = 'hidden';
  2854. }
  2855. }
  2856.  
  2857. if(uFP_invertPURFilters === true)
  2858. {
  2859. if(placeStyle == 'hidden') placeStyle = 'visible';
  2860. else placeStyle = 'hidden';
  2861. }
  2862.  
  2863. if(uFP_filterMinPURAge || uFP_filterMaxPURAge)
  2864. {
  2865. purAge = uroGetPURAge(puObj.model);
  2866. if(uFP_filterMinPURAge === true)
  2867. {
  2868. if(purAge < uFP_thresholdMinPURDays) placeStyle = 'hidden';
  2869. }
  2870. if(uFP_filterMaxPURAge === true)
  2871. {
  2872. if(purAge > uFP_thresholdMaxPURDays) placeStyle = 'hidden';
  2873. }
  2874. }
  2875.  
  2876. if(placeStyle == 'visible')
  2877. {
  2878. var purSeverity = puObj._getSeverity();
  2879. if((uFP_filterHighSeverity) && (purSeverity == "high")) placeStyle = 'hidden';
  2880. if((placeStyle == 'visible') && (uFP_filterMedSeverity) && (purSeverity == "medium")) placeStyle = 'hidden';
  2881. if((placeStyle == 'visible') && (uFP_filterLowSeverity) && (purSeverity == "low")) placeStyle = 'hidden';
  2882. }
  2883. }
  2884. }
  2885.  
  2886. puObj.icon.imageDiv.style.visibility = placeStyle;
  2887.  
  2888. if(uFP_leavePURGeos === false)
  2889. {
  2890. if(puObj.model !== undefined)
  2891. {
  2892. if(puObj.model.geometry !== undefined)
  2893. {
  2894. var puGeo = document.getElementById(puObj.model.geometry.id);
  2895. if(puGeo !== null)
  2896. {
  2897. puGeo.style.visibility = placeStyle;
  2898. }
  2899. }
  2900. }
  2901. }
  2902. }
  2903. }
  2904. }
  2905. }
  2906.  
  2907. function uroFilterCameras()
  2908. {
  2909. if(uroFilterPreamble() === false) return;
  2910. var camLayer = document.getElementById(uroRootContainer+'_svgRoot');
  2911. if(camLayer === null)
  2912. {
  2913. if(uroNullCamLayer === false)
  2914. {
  2915. uroAddLog('caught null camLayer');
  2916. uroNullCamLayer = true;
  2917. }
  2918. return;
  2919. }
  2920. uroNullCamLayer = false;
  2921. if(uroMouseIsDown === false) W.map.camerasLayer.redraw();
  2922. if(uroGetCBChecked('_cbMasterEnable') === true)
  2923. {
  2924. for (var uroCamObj in W.model.cameras.objects)
  2925. {
  2926. if(W.model.cameras.objects.hasOwnProperty(uroCamObj))
  2927. {
  2928. var uroCamUpdater = '';
  2929. var uroCamUpdaterRank = -1;
  2930. var uroCamCreator = '';
  2931. var uroCamCreatorRank = -1;
  2932. var uroCam = W.model.cameras.objects[uroCamObj];
  2933. var uroCamStyle = 'visible';
  2934. if(uroCam.attributes.createdBy !== null)
  2935. {
  2936. if(W.model.users.objects[uroCam.attributes.createdBy] !== undefined)
  2937. {
  2938. uroCamCreator = W.model.users.objects[uroCam.attributes.createdBy].userName;
  2939. uroCamCreatorRank = W.model.users.objects[uroCam.attributes.createdBy].rank;
  2940. }
  2941. }
  2942.  
  2943. if(uroCam.attributes.updatedBy !== null)
  2944. {
  2945. if(W.model.users.objects[uroCam.attributes.updatedBy] !== undefined)
  2946. {
  2947. uroCamUpdater = W.model.users.objects[uroCam.attributes.updatedBy].userName;
  2948. uroCamUpdaterRank = W.model.users.objects[uroCam.attributes.updatedBy].rank;
  2949. }
  2950. }
  2951.  
  2952. var uroCamApproved = uroCam.attributes.validated;
  2953. var uroCamType = uroCam.attributes.type;
  2954.  
  2955. if(uroGetCBChecked('_cbShowOnlyMyCams') === true)
  2956. {
  2957. if((uroUserID != uroCam.attributes.createdBy)&&(uroUserID != uroCam.attributes.updatedBy)) uroCamStyle = 'hidden';
  2958. }
  2959.  
  2960. if((uroGetCBChecked('_cbShowWorldCams') === false) || (uroGetCBChecked('_cbShowUSACams') === false) || (uroGetCBChecked('_cbShowNonWorldCams') === false))
  2961. {
  2962. var posWorld = uroCamCreator.indexOf('world_');
  2963. var posUSA = uroCamCreator.indexOf('usa_');
  2964.  
  2965. if((uroGetCBChecked('_cbShowWorldCams') === false) && (posWorld === 0)) uroCamStyle = 'hidden';
  2966. if((uroGetCBChecked('_cbShowUSACams') === false) && (posUSA === 0)) uroCamStyle = 'hidden';
  2967. if((uroGetCBChecked('_cbShowNonWorldCams') === false) && (posWorld !== 0) && (posUSA !== 0)) uroCamStyle = 'hidden';
  2968. }
  2969.  
  2970. if((uroGetCBChecked('_cbShowApprovedCams') === false) || (uroGetCBChecked('_cbShowNonApprovedCams') === false))
  2971. {
  2972. if((uroGetCBChecked('_cbShowApprovedCams') === false) && (uroCamApproved === true)) uroCamStyle = 'hidden';
  2973. if((uroGetCBChecked('_cbShowNonApprovedCams') === false) && (uroCamApproved === false)) uroCamStyle = 'hidden';
  2974. }
  2975.  
  2976. if((uroGetCBChecked('_cbShowNonApprovedCams') === true) && (uroCamApproved === false))
  2977. {
  2978. if(((uroGetCBChecked('_cbShowOlderCreatedNonApproved') === true)) && (uroGetCameraAge(uroCam,1) <= uroGetElmValue('_inputCameraMinCreatedDays'))) uroCamStyle = 'hidden';
  2979. if(((uroGetCBChecked('_cbShowOlderUpdatedNonApproved') === true)) && (uroGetCameraAge(uroCam,0) <= uroGetElmValue('_inputCameraMinUpdatedDays'))) uroCamStyle = 'hidden';
  2980. }
  2981.  
  2982. if((uroGetCBChecked('_cbShowSpeedCams') === false) || (uroGetCBChecked('_cbShowRedLightCams') === false) || (uroGetCBChecked('_cbShowDummyCams') === false))
  2983. {
  2984. if((uroGetCBChecked('_cbShowSpeedCams') === false) && (uroCamType == 2)) uroCamStyle = 'hidden';
  2985. if((uroGetCBChecked('_cbShowRedLightCams') === false) && (uroCamType == 4)) uroCamStyle = 'hidden';
  2986. if((uroGetCBChecked('_cbShowDummyCams') === false) && (uroCamType == 3)) uroCamStyle = 'hidden';
  2987. }
  2988.  
  2989. if(uroGetCBChecked('_cbShowSpeedCams') === true)
  2990. {
  2991. if((uroGetCBChecked('_cbShowIfNoSpeedSet') === false) && (uroCam.attributes.speed === null)) uroCamStyle = 'hidden';
  2992. if((uroGetCBChecked('_cbShowIfSpeedSet') === false) && (uroCam.attributes.speed !== null)) uroCamStyle = 'hidden';
  2993. }
  2994.  
  2995. if(uroGetCBChecked('_cbHideCreatedByMe') === true)
  2996. {
  2997. if(uroUserID == uroCam.attributes.createdBy) uroCamStyle = 'hidden';
  2998. }
  2999. if((uroGetCBChecked('_cbHideCreatedByRank0') === true) && (uroCamCreatorRank === 0)) uroCamStyle = 'hidden';
  3000. if((uroGetCBChecked('_cbHideCreatedByRank1') === true) && (uroCamCreatorRank == 1)) uroCamStyle = 'hidden';
  3001. if((uroGetCBChecked('_cbHideCreatedByRank2') === true) && (uroCamCreatorRank == 2)) uroCamStyle = 'hidden';
  3002. if((uroGetCBChecked('_cbHideCreatedByRank3') === true) && (uroCamCreatorRank == 3)) uroCamStyle = 'hidden';
  3003. if((uroGetCBChecked('_cbHideCreatedByRank4') === true) && (uroCamCreatorRank == 4)) uroCamStyle = 'hidden';
  3004. if((uroGetCBChecked('_cbHideCreatedByRank5') === true) && (uroCamCreatorRank == 5)) uroCamStyle = 'hidden';
  3005.  
  3006. if(uroGetCBChecked('_cbHideUpdatedByMe') === true)
  3007. {
  3008. if(uroUserID == uroCam.attributes.updatedBy) uroCamStyle = 'hidden';
  3009. }
  3010. if((uroGetCBChecked('_cbHideUpdatedByRank0') === true) && (uroCamUpdaterRank === 0)) uroCamStyle = 'hidden';
  3011. if((uroGetCBChecked('_cbHideUpdatedByRank1') === true) && (uroCamUpdaterRank == 1)) uroCamStyle = 'hidden';
  3012. if((uroGetCBChecked('_cbHideUpdatedByRank2') === true) && (uroCamUpdaterRank == 2)) uroCamStyle = 'hidden';
  3013. if((uroGetCBChecked('_cbHideUpdatedByRank3') === true) && (uroCamUpdaterRank == 3)) uroCamStyle = 'hidden';
  3014. if((uroGetCBChecked('_cbHideUpdatedByRank4') === true) && (uroCamUpdaterRank == 4)) uroCamStyle = 'hidden';
  3015. if((uroGetCBChecked('_cbHideUpdatedByRank5') === true) && (uroCamUpdaterRank == 5)) uroCamStyle = 'hidden';
  3016.  
  3017. if((uroGetCBChecked('_cbHideCWLCams') === true) && (uroIsCamOnWatchList(uroCam.attributes.id) != -1)) uroCamStyle = 'hidden';
  3018.  
  3019. var uroCamGeometryID = uroCam.geometry.id;
  3020. if(camLayer.getElementById(uroCamGeometryID) !== null)
  3021. {
  3022. if(uroCamStyle == "hidden")
  3023. {
  3024. camLayer.getElementById(uroCamGeometryID).remove();
  3025. }
  3026. }
  3027. }
  3028. }
  3029. }
  3030. }
  3031.  
  3032. function uroFilterURs_onObjectsChanged()
  3033. {
  3034. if(uroBackfilling === false)
  3035. {
  3036. if(uroURDialogIsOpen === false)
  3037. {
  3038. uroURBackfill();
  3039. }
  3040. uroFilterURs();
  3041. }
  3042. }
  3043. function uroFilterURs_onObjectsAdded()
  3044. {
  3045. if(uroBackfilling === false)
  3046. {
  3047. uroURBackfill();
  3048. uroFilterURs();
  3049. }
  3050. }
  3051. function uroFilterURs_onObjectsRemoved()
  3052. {
  3053. if(uroBackfilling === false)
  3054. {
  3055. uroURBackfill();
  3056. uroFilterURs();
  3057. }
  3058. }
  3059.  
  3060.  
  3061. function uroURBackfill_GetData(lon, lat, blockSize)
  3062. {
  3063. lon = parseFloat(lon);
  3064. lat = parseFloat(lat);
  3065. blockSize = parseFloat(blockSize);
  3066. uroAddLog('Backfill square '+lon+','+lat);
  3067. var xmlReq = new XMLHttpRequest();
  3068.  
  3069. var tURL = 'https://' + document.location.host;
  3070. tURL += Waze.Config.api_base;
  3071. tURL += '/Features?language=en&mapUpdateRequestFilter=0';
  3072. tURL += '&bbox='+(lon)+','+(lat)+','+(lon + blockSize)+','+(lat + blockSize);
  3073. xmlReq.open('GET',tURL,false);
  3074. try
  3075. {
  3076. xmlReq.send();
  3077. uroAddLog('response '+xmlReq.status+' received');
  3078. if (xmlReq.status === 200)
  3079. {
  3080. var tResp = JSON.parse(xmlReq.responseText);
  3081. var urCount = tResp.mapUpdateRequests.objects.length;
  3082.  
  3083. uroAddLog(urCount+' URs loaded for backfill processing');
  3084. if(urCount == 500)
  3085. {
  3086. uroAddLog('WARNING - backfill data may have been pre-filtered by server');
  3087. }
  3088.  
  3089. var backfilled = 0;
  3090. for(var i=0; i<urCount; i++)
  3091. {
  3092. var urID = tResp.mapUpdateRequests.objects[i].id;
  3093. if(W.model.mapUpdateRequests.objects[urID] === undefined)
  3094. {
  3095. var newUR = require('Waze/Feature/Vector/UpdateRequest');
  3096. var tUR = new newUR(tResp.mapUpdateRequests.objects[i]);
  3097. var tPoint = new OpenLayers.Geometry.Point();
  3098. tPoint.x = tResp.mapUpdateRequests.objects[i].geometry.coordinates[0];
  3099. tPoint.y = tResp.mapUpdateRequests.objects[i].geometry.coordinates[1];
  3100. tPoint.transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913"));
  3101. tUR.geometry = tPoint;
  3102. var tReqBounds = new OpenLayers.Geometry.Polygon();
  3103. var tBounds = new OpenLayers.Bounds();
  3104. tBounds.left = tPoint.x;
  3105. tBounds.right = tPoint.x;
  3106. tBounds.top = tPoint.y;
  3107. tBounds.bottom = tPoint.y;
  3108. tReqBounds.bounds = tBounds;
  3109. tUR.requestBounds = tReqBounds;
  3110. W.model.mapUpdateRequests.put(tUR);
  3111. backfilled++;
  3112. }
  3113. }
  3114.  
  3115. uroAddLog(backfilled+' URs backfilled');
  3116. }
  3117. else
  3118. {
  3119. uroAddLog('request failed (status != 200)');
  3120. }
  3121. }
  3122. catch(err)
  3123. {
  3124. uroAddLog('UR backfill request failed (exception '+err+' caught)');
  3125. }
  3126. }
  3127.  
  3128. function uroURBackfill()
  3129. {
  3130. if((uroGetCBChecked('_cbURBackfill') === false) || (uroGetCBChecked('_cbMasterEnable') === false))
  3131. {
  3132. return;
  3133. }
  3134.  
  3135. var nativeURCount = Object.keys(W.model.mapUpdateRequests.objects).length;
  3136. if(nativeURCount < 500)
  3137. {
  3138. return;
  3139. }
  3140.  
  3141. uroAddLog('exactly 500 URs loaded, possible server-side filtering requiring backfill...');
  3142.  
  3143. var subSize = 0.1;
  3144. var vpWidth = W.map.getExtent().getWidth();
  3145. var vpHeight = W.map.getExtent().getHeight();
  3146. var vpCentre = W.map.getCenter();
  3147. var vpLL = new OpenLayers.LonLat();
  3148. var vpUR = new OpenLayers.LonLat();
  3149. vpLL.lon = vpCentre.lon - (vpWidth / 2);
  3150. vpLL.lat = vpCentre.lat - (vpHeight / 2);
  3151. vpUR.lon = vpCentre.lon + (vpWidth / 2);
  3152. vpUR.lat = vpCentre.lat + (vpHeight / 2);
  3153. vpLL = vpLL.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326"));
  3154. vpUR = vpUR.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326"));
  3155. vpLL.lon -= (subSize / 2);
  3156. vpLL.lat -= (subSize / 2);
  3157. vpUR.lon += (subSize / 2);
  3158. vpUR.lat += (subSize / 2);
  3159. vpLL.lon = +vpLL.lon.toFixed(1);
  3160. vpLL.lat = +vpLL.lat.toFixed(1);
  3161. vpUR.lon = +vpUR.lon.toFixed(1);
  3162. vpUR.lat = +vpUR.lat.toFixed(1);
  3163.  
  3164. uroBackfilling = true;
  3165. for(var bfLat = vpLL.lat; bfLat <= vpUR.lat; bfLat += subSize)
  3166. {
  3167. for(var bfLon = vpLL.lon; bfLon <= vpUR.lon; bfLon += subSize)
  3168. {
  3169. uroURBackfill_GetData(bfLon, bfLat, subSize);
  3170. }
  3171. }
  3172. uroBackfilling = false;
  3173. uroFilterURs();
  3174. }
  3175.  
  3176.  
  3177. function uroStopThatDamnedRecentering()
  3178. {
  3179. return W.map.getExtent();
  3180. }
  3181.  
  3182. function uroFilterURs()
  3183. {
  3184. // compatibility fix for URComments - based on code supplied by RickZabel
  3185. var hasActiveURFilters = false;
  3186. if(uroGetCBChecked('_cbMasterEnable') === true)
  3187. {
  3188. var urTabInputs = document.getElementById('uroCtrlURs').getElementsByTagName('input');
  3189. for(var loop = 0; loop < urTabInputs.length; loop++)
  3190. {
  3191. if(urTabInputs[loop].type == 'checkbox')
  3192. {
  3193. var ignoreCB = false;
  3194. ignoreCB = ignoreCB || (urTabInputs[loop].id == '_cbCaseInsensitive');
  3195. ignoreCB = ignoreCB || (urTabInputs[loop].id == '_cbNoFilterForTaggedURs');
  3196. if((urTabInputs[loop].checked) && (ignoreCB === false))
  3197. {
  3198. hasActiveURFilters = true;
  3199. break;
  3200. }
  3201. }
  3202. }
  3203. }
  3204. sessionStorage.UROverview_hasActiveURFilters = hasActiveURFilters;
  3205. if(uroFilterPreamble() === false) return;
  3206. uroRefreshUpdateRequestSessions();
  3207. var selectorResolver = document.getElementById('_selectURResolverID');
  3208. var selectorCommentUser = document.getElementById('_selectURUserID');
  3209.  
  3210. if(uroGetCBChecked('_cbURResolverIDFilter') === false)
  3211. {
  3212. while(selectorResolver.options.length > 0)
  3213. {
  3214. selectorResolver.options.remove(0);
  3215. }
  3216. }
  3217. if(uroGetCBChecked('_cbURUserIDFilter') === false)
  3218. {
  3219. while(selectorCommentUser.options.length > 0)
  3220. {
  3221. selectorCommentUser.options.remove(0);
  3222. }
  3223. }
  3224. if(Object.keys(W.model.updateRequestSessions.objects).length === 0)
  3225. {
  3226. return;
  3227. }
  3228. var commenterUser = null;
  3229. if(uroGetCBChecked('_cbURUserIDFilter') === true)
  3230. {
  3231. if(selectorCommentUser.options.length === 0)
  3232. {
  3233. uroUpdateUserList();
  3234. }
  3235. if(selectorCommentUser.selectedOptions[0] !== undefined)
  3236. {
  3237. commenterUser = parseInt(selectorCommentUser.selectedOptions[0].value);
  3238. }
  3239. }
  3240. var resolverUser = null;
  3241. if(uroGetCBChecked('_cbURResolverIDFilter') === true)
  3242. {
  3243. if(selectorResolver.options.length === 0)
  3244. {
  3245. uroUpdateResolverList();
  3246. }
  3247. if(selectorResolver.selectedOptions[0] !== undefined)
  3248. {
  3249. resolverUser = parseInt(selectorResolver.selectedOptions[0].value);
  3250. }
  3251. }
  3252. uroCustomMarkerList = [];
  3253.  
  3254. var uFURs_masterEnable = uroGetCBChecked('_cbMasterEnable');
  3255. var filterOutsideEditableArea = uroGetCBChecked('_cbURFilterOutsideArea');
  3256. var filterSolved = uroGetCBChecked('_cbFilterSolved');
  3257. var filterUnidentified = uroGetCBChecked('_cbFilterUnidentified');
  3258. var filterClosed = uroGetCBChecked('_cbFilterClosedUR');
  3259. var filterOpen = uroGetCBChecked('_cbFilterOpenUR');
  3260. var filterDescMustBePresent = uroGetCBChecked('_cbURDescriptionMustBePresent');
  3261. var filterDescMustBeAbsent = uroGetCBChecked('_cbURDescriptionMustBeAbsent');
  3262. var filterKeywordMustBePresent = uroGetCBChecked('_cbEnableKeywordMustBePresent');
  3263. var filterKeywordMustBeAbsent = uroGetCBChecked('_cbEnableKeywordMustBeAbsent');
  3264. var filterMinURAge = uroGetCBChecked('_cbEnableMinAgeFilter');
  3265. var filterMaxURAge = uroGetCBChecked('_cbEnableMaxAgeFilter');
  3266. var filterMinComments = uroGetCBChecked('_cbEnableMinCommentsFilter');
  3267. var filterMaxComments = uroGetCBChecked('_cbEnableMaxCommentsFilter');
  3268. var filterReporterLastCommenter = uroGetCBChecked('_cbHideIfReporterLastCommenter');
  3269. var filterReporterNotLastCommenter = uroGetCBChecked('_cbHideIfReporterNotLastCommenter');
  3270. var filterHideAnyComments = uroGetCBChecked('_cbHideAnyComments');
  3271. var filterHideNotLastCommenter = uroGetCBChecked('_cbHideIfNotLastCommenter');
  3272. var filterHideMyComments = uroGetCBChecked('_cbHideMyComments');
  3273. var filterIfLastCommenter = uroGetCBChecked('_cbHideIfLastCommenter');
  3274. var filterIfNotLastCommenter = uroGetCBChecked('_cbHideIfNotLastCommenter');
  3275. var filterCommentMinAge = uroGetCBChecked('_cbEnableCommentAgeFilter2');
  3276. var filterCommentMaxAge = uroGetCBChecked('_cbEnableCommentAgeFilter');
  3277. var filterUserID = uroGetCBChecked('_cbURUserIDFilter');
  3278. var filterMyFollowed = uroGetCBChecked('_cbHideMyFollowed');
  3279. var filterMyUnfollowed = uroGetCBChecked('_cbHideMyUnfollowed');
  3280. var filterWazeAuto = uroGetCBChecked('_cbFilterWazeAuto');
  3281. var filterRoadworks = uroGetCBChecked('_cbFilterRoadworks');
  3282. var filterConstruction = uroGetCBChecked('_cbFilterConstruction');
  3283. var filterClosure = uroGetCBChecked('_cbFilterClosure');
  3284. var filterEvent = uroGetCBChecked('_cbFilterEvent');
  3285. var filterNote = uroGetCBChecked('_cbFilterNote');
  3286. var filterIncorrectTurn = uroGetCBChecked('_cbFilterIncorrectTurn');
  3287. var filterIncorrectAddress = uroGetCBChecked('_cbFilterIncorrectAddress');
  3288. var filterIncorrectRoute = uroGetCBChecked('_cbFilterIncorrectRoute');
  3289. var filterMissingRoundabout = uroGetCBChecked('_cbFilterMissingRoundabout');
  3290. var filterGeneralError = uroGetCBChecked('_cbFilterGeneralError');
  3291. var filterTurnNotAllowed = uroGetCBChecked('_cbFilterTurnNotAllowed');
  3292. var filterIncorrectJunction = uroGetCBChecked('_cbFilterIncorrectJunction');
  3293. var filterMissingBridgeOverpass = uroGetCBChecked('_cbFilterMissingBridgeOverpass');
  3294. var filterWrongDrivingDirection = uroGetCBChecked('_cbFilterWrongDrivingDirection');
  3295. var filterMissingExit = uroGetCBChecked('_cbFilterMissingExit');
  3296. var filterMissingRoad = uroGetCBChecked('_cbFilterMissingRoad');
  3297. var filterMissingLandmark = uroGetCBChecked('_cbFilterMissingLandmark');
  3298. var filterBlockedRoad = uroGetCBChecked('_cbFilterBlockedRoad');
  3299. var filterUndefined = uroGetCBChecked('_cbFilterUndefined');
  3300. var invertURFilters = uroGetCBChecked('_cbInvertURFilter');
  3301. var noFilterTaggedURs = uroGetCBChecked('_cbNoFilterForTaggedURs');
  3302. var noFilterURInURL = uroGetCBChecked('_cbNoFilterForURInURL');
  3303. var keywordPresent = uroGetElmValue('_textKeywordPresent');
  3304. var keywordAbsent = uroGetElmValue('_textKeywordAbsent');
  3305. var thresholdMinAge = uroGetElmValue('_inputFilterMinDays');
  3306. var thresholdMaxAge = uroGetElmValue('_inputFilterMaxDays');
  3307. var thresholdMinComments = uroGetElmValue('_inputFilterMinComments');
  3308. var thresholdMaxComments = uroGetElmValue('_inputFilterMaxComments');
  3309. var thresholdMaxCommentAge = uroGetElmValue('_inputFilterCommentDays');
  3310. var thresholdMinCommentAge = uroGetElmValue('_inputFilterCommentDays2');
  3311. var urcFilteringIsActive = false;
  3312. var urcCB = document.getElementById('URCommentsFilterEnabled');
  3313. if(urcCB !== null)
  3314. {
  3315. if(urcCB.checked)
  3316. {
  3317. urcFilteringIsActive = true;
  3318. }
  3319. }
  3320. urcCB = document.getElementById('URCommentUROOnlyMyUR');
  3321. if(urcCB !== null)
  3322. {
  3323. if(urcCB.checked)
  3324. {
  3325. urcFilteringIsActive = true;
  3326. }
  3327. }
  3328. urcCB = document.getElementById('URCommentUROHideTagged');
  3329. if(urcCB !== null)
  3330. {
  3331. if(urcCB.checked)
  3332. {
  3333. urcFilteringIsActive = true;
  3334. }
  3335. }
  3336.  
  3337. for (var urobj in W.model.mapUpdateRequests.objects)
  3338. {
  3339. if(W.model.mapUpdateRequests.objects.hasOwnProperty(urobj))
  3340. {
  3341. var ureq = W.model.mapUpdateRequests.objects[urobj];
  3342. if(uroGetCBChecked('_cbInhibitURCentering') === true)
  3343. {
  3344. // seems the easiest way to prevent WME recentering the mapview on the UR when it's clicked, is to replace the
  3345. // getBounds() function in each UR object with one that returns the current mapview extents... Note that
  3346. // simply replacing it with a direct call to W.map.getExtent doesn't work, so we have to use a third-party
  3347. // function to act as the go-between.
  3348. ureq.getRequestBounds().getBounds = uroStopThatDamnedRecentering;
  3349. }
  3350. var urStyle = 'visible';
  3351. var ureqID = null;
  3352. if(ureq.fid === null) ureqID = ureq.attributes.id;
  3353. else ureqID = ureq.fid;
  3354. var inhibitFiltering = ((ureqID == uroURIDInURL) && (noFilterURInURL));
  3355. var hasMyComments = false;
  3356. var nComments = 0;
  3357. var customType = uroGetCustomType(ureqID, "ur");
  3358. if(W.model.updateRequestSessions.objects[ureqID] !== undefined)
  3359. {
  3360. nComments = W.model.updateRequestSessions.objects[ureqID].comments.length;
  3361. if((uFURs_masterEnable === false) && (nComments === 0))
  3362. {
  3363. // when master enable is turned off, we want to make sure that all URs, including ones that were previously hidden, are correctly
  3364. // displayed in their native form - i.e. no comment count or custom conversation bubbles. The easiest way to achieve this is to
  3365. // force the uroRenderCustomMarkers code to test for the presence of these bubbles on each UR, which we do by setting a non-zero
  3366. // comment count for each UR... For URs which genuinely do have no comments we use -1 to indicate that we're not really setting
  3367. // a comment count, but that we still need to do something that wouldn't be achieved by using 0.
  3368. nComments = -1;
  3369. }
  3370. }
  3371. if((uFURs_masterEnable === true) && (inhibitFiltering === false))
  3372. {
  3373. var wazeauto_ur = false;
  3374. var ukroadworks_ur = false;
  3375. var construction_ur = false;
  3376. var closure_ur = false;
  3377. var event_ur = false;
  3378. var note_ur = false;
  3379.  
  3380. var filterByNotIncludedKeyword = false;
  3381. var filterByIncludedKeyword = true;
  3382.  
  3383. var desc = '';
  3384. if(ureq.attributes.description !== null) desc = ureq.attributes.description.replace(/<\/?[^>]+(>|$)/g, "");
  3385.  
  3386. if(customType === 0) ukroadworks_ur = true;
  3387. else if(customType === 1) construction_ur = true;
  3388. else if(customType === 2) closure_ur = true;
  3389. else if(customType === 3) event_ur = true;
  3390. else if(customType === 4) note_ur = true;
  3391.  
  3392. // check UR against editable area...
  3393.  
  3394. if(filterOutsideEditableArea === true)
  3395. {
  3396. if(ureq.canEdit() === false) urStyle = 'hidden';
  3397. }
  3398. // check UR against current session ignore list...
  3399. if(uroIsOnIgnoreList(ureqID)) urStyle = 'hidden';
  3400.  
  3401. // check against closed/not identified filtering if enabled...
  3402. if(filterSolved === true)
  3403. {
  3404. if(ureq.attributes.resolution === 0) urStyle = 'hidden';
  3405. }
  3406. if(filterUnidentified === true)
  3407. {
  3408. if(ureq.attributes.resolution == 1) urStyle = 'hidden';
  3409. }
  3410.  
  3411. if((ureq.attributes.resolvedOn !== null) && (filterClosed === true))
  3412. {
  3413. urStyle = 'hidden';
  3414. }
  3415.  
  3416. if((ureq.attributes.resolvedOn === null) && (filterOpen === true))
  3417. {
  3418. urStyle = 'hidden';
  3419. }
  3420.  
  3421. if(urStyle == 'visible')
  3422. {
  3423. // check UR against keyword filtering if enabled...
  3424. if(filterDescMustBePresent === true)
  3425. {
  3426. if(desc === '') urStyle = 'hidden';
  3427. }
  3428. if(filterDescMustBeAbsent === true)
  3429. {
  3430. if(desc !== '') urStyle = 'hidden';
  3431. }
  3432.  
  3433. if(filterKeywordMustBePresent === true)
  3434. {
  3435. var keywordIsPresentInDesc = uroKeywordPresent(desc,keywordPresent);
  3436. filterByIncludedKeyword &= (!keywordIsPresentInDesc);
  3437. }
  3438. if(filterKeywordMustBeAbsent === true)
  3439. {
  3440. var keywordIsAbsentInDesc = uroKeywordPresent(desc,keywordAbsent);
  3441. filterByNotIncludedKeyword |= keywordIsAbsentInDesc;
  3442. }
  3443. }
  3444.  
  3445. if(urStyle == 'visible')
  3446. {
  3447. // do age-based filtering if enabled
  3448. if(filterMinURAge === true)
  3449. {
  3450. if(uroGetURAge(ureq,0,false) < thresholdMinAge) urStyle = 'hidden';
  3451. }
  3452. if(filterMaxURAge === true)
  3453. {
  3454. if(uroGetURAge(ureq,0,false) > thresholdMaxAge) urStyle = 'hidden';
  3455. }
  3456. }
  3457.  
  3458. if(urStyle == 'visible')
  3459. {
  3460. if(resolverUser !== null)
  3461. {
  3462. if(ureq.attributes.resolvedBy != resolverUser) urStyle = 'hidden';
  3463. }
  3464. }
  3465.  
  3466. if(urStyle == 'visible')
  3467. {
  3468. // do comments/following filtering
  3469. if(W.model.updateRequestSessions.objects[ureqID] !== undefined)
  3470. {
  3471. nComments = W.model.updateRequestSessions.objects[ureqID].comments.length;
  3472. var commentDaysOld = -1;
  3473.  
  3474.  
  3475. if(filterMinComments === true)
  3476. {
  3477. if(nComments < thresholdMinComments) urStyle = 'hidden';
  3478. }
  3479. if(filterMaxComments === true)
  3480. {
  3481. if(nComments > thresholdMaxComments) urStyle = 'hidden';
  3482. }
  3483.  
  3484.  
  3485. if(nComments > 0)
  3486. {
  3487. var reporterIsLastCommenter = false;
  3488. if(W.model.updateRequestSessions.objects[ureqID].comments[nComments-1].userID == -1) reporterIsLastCommenter = true;
  3489.  
  3490. if(filterReporterLastCommenter === true)
  3491. {
  3492. if(reporterIsLastCommenter === true) urStyle = 'hidden';
  3493. }
  3494. else if(filterReporterNotLastCommenter === true)
  3495. {
  3496. if(reporterIsLastCommenter === false) urStyle = 'hidden';
  3497. }
  3498.  
  3499. hasMyComments = uroURHasMyComments(ureqID);
  3500. if(hasMyComments === false)
  3501. {
  3502. if(filterHideAnyComments === true) urStyle = 'hidden';
  3503. if(filterHideNotLastCommenter === true) urStyle = 'hidden';
  3504. }
  3505. else
  3506. {
  3507. if(filterHideMyComments === true) urStyle = 'hidden';
  3508.  
  3509. var userIsLastCommenter = false;
  3510. if(W.model.updateRequestSessions.objects[ureqID].comments[nComments-1].userID == uroUserID) userIsLastCommenter = true;
  3511.  
  3512. if(filterIfLastCommenter === true)
  3513. {
  3514. if(userIsLastCommenter === true) urStyle = 'hidden';
  3515. }
  3516. else if(filterIfNotLastCommenter === true)
  3517. {
  3518. if(userIsLastCommenter === false) urStyle = 'hidden';
  3519. }
  3520. }
  3521. commentDaysOld = uroGetCommentAge(W.model.updateRequestSessions.objects[ureqID].comments[nComments-1]);
  3522. if((filterCommentMinAge === true) && (commentDaysOld != -1))
  3523. {
  3524. if(thresholdMinCommentAge > commentDaysOld) urStyle = 'hidden';
  3525. }
  3526. if((filterCommentMaxAge === true) && (commentDaysOld != -1))
  3527. {
  3528. if(thresholdMaxCommentAge < commentDaysOld) urStyle = 'hidden';
  3529. }
  3530.  
  3531. var cidx;
  3532. if((commenterUser !== null) && (urStyle != 'hidden'))
  3533. {
  3534. urStyle = 'hidden';
  3535. for(cidx=0; cidx<nComments; cidx++)
  3536. {
  3537. if(W.model.updateRequestSessions.objects[ureqID].comments[cidx].userID == commenterUser)
  3538. {
  3539. urStyle = 'visible';
  3540. break;
  3541. }
  3542. }
  3543. }
  3544.  
  3545. var commentText = '';
  3546. for(cidx=0; cidx<nComments; cidx++)
  3547. {
  3548. commentText += W.model.updateRequestSessions.objects[ureqID].comments[cidx].text;
  3549. }
  3550.  
  3551. if(filterKeywordMustBePresent === true)
  3552. {
  3553. var keywordIsPresentInComments = uroKeywordPresent(commentText,keywordPresent);
  3554. filterByIncludedKeyword &= (!keywordIsPresentInComments);
  3555. }
  3556. if(filterKeywordMustBeAbsent === true)
  3557. {
  3558. var keywordIsAbsentInComments = uroKeywordPresent(commentText,keywordAbsent);
  3559. filterByNotIncludedKeyword |= keywordIsAbsentInComments;
  3560. }
  3561. }
  3562. else
  3563. {
  3564. if(filterUserID === true)
  3565. {
  3566. urStyle = 'hidden';
  3567. }
  3568. }
  3569.  
  3570. filterByNotIncludedKeyword &= filterKeywordMustBeAbsent;
  3571. filterByIncludedKeyword &= filterKeywordMustBePresent;
  3572. if(filterByNotIncludedKeyword || filterByIncludedKeyword)
  3573. {
  3574. urStyle = 'hidden';
  3575. }
  3576.  
  3577.  
  3578. if(W.model.updateRequestSessions.objects[ureqID].isFollowing === true)
  3579. {
  3580. if(filterMyFollowed === true) urStyle = 'hidden';
  3581. }
  3582. else
  3583. {
  3584. if(filterMyUnfollowed === true) urStyle = 'hidden';
  3585. }
  3586. }
  3587. }
  3588.  
  3589. if(urStyle == 'visible')
  3590. {
  3591. // Test for Waze automatic URs before any others - these always (?) get inserted as General Error URs,
  3592. // so we can't filter them by type...
  3593. if(desc.indexOf('Waze Automatic:') != -1)
  3594. {
  3595. wazeauto_ur = true;
  3596. }
  3597.  
  3598. if(wazeauto_ur === true)
  3599. {
  3600. if(filterWazeAuto === true) urStyle = 'hidden';
  3601. }
  3602.  
  3603. else if(ukroadworks_ur === true)
  3604. {
  3605. if(filterRoadworks === true) urStyle = 'hidden';
  3606. }
  3607. else if(construction_ur === true)
  3608. {
  3609. if(filterConstruction === true) urStyle = 'hidden';
  3610. }
  3611. else if(closure_ur === true)
  3612. {
  3613. if(filterClosure === true) urStyle = 'hidden';
  3614. }
  3615. else if(event_ur === true)
  3616. {
  3617. if(filterEvent === true) urStyle = 'hidden';
  3618. }
  3619. else if(note_ur === true)
  3620. {
  3621. if(filterNote === true) urStyle = 'hidden';
  3622. }
  3623.  
  3624. else if(ureq.attributes.type == 6)
  3625. {
  3626. if(filterIncorrectTurn === true) urStyle = 'hidden';
  3627. }
  3628. else if(ureq.attributes.type == 7)
  3629. {
  3630. if (filterIncorrectAddress === true) urStyle = 'hidden';
  3631. }
  3632. else if(ureq.attributes.type == 8)
  3633. {
  3634. if(filterIncorrectRoute === true) urStyle = 'hidden';
  3635. }
  3636. else if(ureq.attributes.type == 9)
  3637. {
  3638. if(filterMissingRoundabout === true) urStyle = 'hidden';
  3639. }
  3640. else if(ureq.attributes.type == 10)
  3641. {
  3642. if(filterGeneralError === true) urStyle = 'hidden';
  3643. }
  3644. else if(ureq.attributes.type == 11)
  3645. {
  3646. if(filterTurnNotAllowed === true) urStyle = 'hidden';
  3647. }
  3648. else if(ureq.attributes.type == 12)
  3649. {
  3650. if(filterIncorrectJunction === true) urStyle = 'hidden';
  3651. }
  3652. else if(ureq.attributes.type == 13)
  3653. {
  3654. if(filterMissingBridgeOverpass === true) urStyle = 'hidden';
  3655. }
  3656. else if(ureq.attributes.type == 14)
  3657. {
  3658. if(filterWrongDrivingDirection === true) urStyle = 'hidden';
  3659. }
  3660. else if(ureq.attributes.type == 15)
  3661. {
  3662. if(filterMissingExit === true) urStyle = 'hidden';
  3663. }
  3664. else if(ureq.attributes.type == 16)
  3665. {
  3666. if(filterMissingRoad === true) urStyle = 'hidden';
  3667. }
  3668. else if(ureq.attributes.type == 18)
  3669. {
  3670. if(filterMissingLandmark === true) urStyle = 'hidden';
  3671. }
  3672. else if(ureq.attributes.type == 19)
  3673. {
  3674. if(filterBlockedRoad === true) urStyle = 'hidden';
  3675. }
  3676. else if(filterUndefined === true) urStyle = 'hidden';
  3677.  
  3678. if(invertURFilters === true)
  3679. {
  3680. if(urStyle == 'hidden') urStyle = 'visible';
  3681. else urStyle = 'hidden';
  3682. }
  3683. }
  3684.  
  3685. // filtering override for tagged URs
  3686. if(noFilterTaggedURs === true)
  3687. {
  3688. if(ukroadworks_ur === true)
  3689. {
  3690. if(filterRoadworks === false) urStyle = 'visible';
  3691. }
  3692. else if(construction_ur === true)
  3693. {
  3694. if(filterConstruction === false) urStyle = 'visible';
  3695. }
  3696. else if(closure_ur === true)
  3697. {
  3698. if(filterClosure === false) urStyle = 'visible';
  3699. }
  3700. else if(event_ur === true)
  3701. {
  3702. if(filterEvent === false) urStyle = 'visible';
  3703. }
  3704. else if(note_ur === true)
  3705. {
  3706. if(filterNote === false) urStyle = 'visible';
  3707. }
  3708. }
  3709. }
  3710. // only touch marker visibility if we've got active filter settings, or if URComments is not
  3711. // doing any filtering of its own
  3712. if((hasActiveURFilters === true) || (urcFilteringIsActive === false) || (uFURs_masterEnable === false))
  3713. {
  3714. W.map.updateRequestLayer.markers[urobj].icon.imageDiv.style.visibility = urStyle;
  3715. }
  3716. if(urStyle != 'hidden')
  3717. {
  3718. uroAddCustomMarkers(ureqID,customType, hasMyComments, nComments);
  3719. }
  3720. }
  3721. }
  3722. uroRenderCustomMarkers('ur');
  3723. }
  3724.  
  3725.  
  3726. function uroFilterProblems()
  3727. {
  3728. if(uroFilterPreamble() === false) return;
  3729. var selector;
  3730.  
  3731. if((uroGetCBChecked('_cbMPNotClosedUserIDFilter') === false) && (uroGetCBChecked('_cbMPClosedUserIDFilter') === false))
  3732. {
  3733. selector = document.getElementById('_selectMPUserID');
  3734. while(selector.options.length > 0)
  3735. {
  3736. selector.options.remove(0);
  3737. }
  3738. }
  3739.  
  3740. var solverUser = null;
  3741. if((uroGetCBChecked('_cbMPNotClosedUserIDFilter') === true) || (uroGetCBChecked('_cbMPClosedUserIDFilter') === true))
  3742. {
  3743. selector = document.getElementById('_selectMPUserID');
  3744. if(selector.options.length === 0)
  3745. {
  3746. uroUpdateMPSolverList();
  3747. }
  3748. if(selector.selectedOptions[0] !== undefined)
  3749. {
  3750. solverUser = parseInt(selector.selectedOptions[0].value);
  3751. }
  3752. }
  3753.  
  3754. var urobj;
  3755. var problem;
  3756. var problemStyle;
  3757. var problem_marker_img;
  3758.  
  3759. for (urobj in W.model.problems.objects)
  3760. {
  3761. if(W.model.problems.objects.hasOwnProperty(urobj))
  3762. {
  3763. problem = W.model.problems.objects[urobj];
  3764. if(uroGetCBChecked('_cbInhibitMPCentering') === true)
  3765. {
  3766. // same style of fix as for UR markers...
  3767. problem.getDisconnectBounds = uroStopThatDamnedRecentering;
  3768. }
  3769. problemStyle = 'visible';
  3770. var ureqID = null;
  3771. var customType = null;
  3772.  
  3773. if(uroGetCBChecked('_cbMasterEnable') === true)
  3774. {
  3775. ureqID = problem.attributes.id;
  3776. customType = uroGetCustomType(ureqID, "mp");
  3777.  
  3778. // check problem against current session ignore list...
  3779. if(uroIsOnIgnoreList(ureqID)) problemStyle = 'hidden';
  3780.  
  3781.  
  3782. if(uroGetCBChecked('_cbMPFilterOutsideArea') === true)
  3783. {
  3784. if(problem.canEdit() === false)
  3785. {
  3786. problemStyle = 'hidden';
  3787. }
  3788. }
  3789.  
  3790. // check against closed/not identified filtering if enabled...
  3791. problem_marker_img = '';
  3792. if(problem.geometry.id !== null)
  3793. {
  3794. if(document.getElementById(problem.geometry.id) !== null)
  3795. {
  3796. problem_marker_img = document.getElementById(problem.geometry.id).href.baseVal;
  3797. if(uroGetCBChecked('_cbMPFilterSolved') === true)
  3798. {
  3799. if(problem_marker_img.indexOf('_solved') != -1) problemStyle = 'hidden';
  3800. }
  3801. if(uroGetCBChecked('_cbMPFilterUnidentified') === true)
  3802. {
  3803. if(problem_marker_img.indexOf('_rejected') != -1) problemStyle = 'hidden';
  3804. }
  3805. }
  3806. }
  3807.  
  3808. if(uroGetCBChecked('_cbMPFilterClosed') === true)
  3809. {
  3810. if(problem.attributes.open === false)
  3811. {
  3812. problemStyle = 'hidden';
  3813. }
  3814. }
  3815.  
  3816. if(problemStyle == 'visible')
  3817. {
  3818. if(solverUser !== null)
  3819. {
  3820. if((uroGetCBChecked('_cbMPNotClosedUserIDFilter') === true) && (problem.attributes.resolvedBy == solverUser)) problemStyle = 'hidden';
  3821. if((uroGetCBChecked('_cbMPClosedUserIDFilter') === true) && (problem.attributes.resolvedBy != solverUser)) problemStyle = 'hidden';
  3822. }
  3823. }
  3824.  
  3825. if(problemStyle == 'visible')
  3826. {
  3827. var problemType = null;
  3828. if(uroDOMHasTurnProblems)
  3829. {
  3830. problemType = problem.attributes.problemType;
  3831. }
  3832. else
  3833. {
  3834. problemType = problem.attributes.subType;
  3835. }
  3836.  
  3837. if(problemType == 101)
  3838. {
  3839. if(uroGetCBChecked('_cbMPFilterDrivingDirectionMismatch') === true) problemStyle = 'hidden';
  3840. }
  3841. else if(problemType == 102)
  3842. {
  3843. if(uroGetCBChecked('_cbMPFilterMissingJunction') === true) problemStyle = 'hidden';
  3844. }
  3845. else if(problemType == 103)
  3846. {
  3847. if(uroGetCBChecked('_cbMPFilterMissingRoad') === true) problemStyle = 'hidden';
  3848. }
  3849. else if(problemType == 104)
  3850. {
  3851. if(uroGetCBChecked('_cbMPFilterCrossroadsJunctionMissing') === true) problemStyle = 'hidden';
  3852. }
  3853. else if(problemType == 105)
  3854. {
  3855. if(uroGetCBChecked('_cbMPFilterRoadTypeMismatch') === true) problemStyle = 'hidden';
  3856. }
  3857. else if(problemType == 106)
  3858. {
  3859. if(uroGetCBChecked('_cbMPFilterRestrictedTurn') === true) problemStyle = 'hidden';
  3860. }
  3861. else if(problemType == 200)
  3862. {
  3863. if(uroGetCBChecked('_cbMPFilterTurnProblem') === true) problemStyle = 'hidden';
  3864. }
  3865. else if(problemType == 300)
  3866. {
  3867. if(uroGetCBChecked('_cbMPFilterRoadClosureProblem') === true) problemStyle = 'hidden';
  3868. }
  3869. else if(uroGetCBChecked('_cbMPFilterUnknownProblem') === true) problemStyle = 'hidden';
  3870.  
  3871.  
  3872. if(uroGetCBChecked('_cbMPFilterReopenedProblem') === true)
  3873. {
  3874. if((problem.attributes.open === true) && (problem.attributes.resolvedOn !== null))
  3875. {
  3876. problemStyle = 'hidden';
  3877. }
  3878. }
  3879.  
  3880.  
  3881. if(uroGetCBChecked('_cbInvertMPFilter') === true)
  3882. {
  3883. if(problemStyle == 'hidden') problemStyle = 'visible';
  3884. else problemStyle = 'hidden';
  3885. }
  3886.  
  3887.  
  3888. if(problem.attributes.weight <= 3)
  3889. {
  3890. if(uroGetCBChecked('_cbMPFilterLowSeverity') === true) problemStyle = 'hidden';
  3891. }
  3892. else if(problem.attributes.weight <= 7)
  3893. {
  3894. if(uroGetCBChecked('_cbMPFilterMediumSeverity') === true) problemStyle = 'hidden';
  3895. }
  3896. else if(uroGetCBChecked('_cbMPFilterHighSeverity') === true) problemStyle = 'hidden';
  3897. }
  3898. }
  3899.  
  3900. W.map.problemLayer.markers[urobj].icon.imageDiv.style.visibility = problemStyle;
  3901.  
  3902. if((problemStyle != 'hidden') && (ureqID !== null) && (customType !== null))
  3903. {
  3904. uroAddCustomMarkers(ureqID,customType, false, 0);
  3905. }
  3906. }
  3907. }
  3908.  
  3909. if(uroDOMHasTurnProblems)
  3910. {
  3911. for (urobj in W.model.turnProblems.objects)
  3912. {
  3913. if(W.model.turnProblems.objects.hasOwnProperty(urobj))
  3914. {
  3915. problem = W.model.turnProblems.objects[urobj];
  3916. problemStyle = 'visible';
  3917.  
  3918. if(uroGetCBChecked('_cbMasterEnable') === true)
  3919. {
  3920. // check problem against current session ignore list...
  3921. if(uroIsOnIgnoreList(problem.attributes.id)) problemStyle = 'hidden';
  3922.  
  3923. // check against closed/not identified filtering if enabled...
  3924. problem_marker_img = '';
  3925. if(problem.geometry.id !== null)
  3926. {
  3927. if(document.getElementById(problem.geometry.id) !== null)
  3928. {
  3929. problem_marker_img = document.getElementById(problem.geometry.id).href.baseVal;
  3930. if(uroGetCBChecked('_cbMPFilterSolved') === true)
  3931. {
  3932. if(problem_marker_img.indexOf('_solved') != -1) problemStyle = 'hidden';
  3933. }
  3934. if(uroGetCBChecked('_cbMPFilterUnidentified') === true)
  3935. {
  3936. if(problem_marker_img.indexOf('_rejected') != -1) problemStyle = 'hidden';
  3937. }
  3938. }
  3939. }
  3940.  
  3941. if(uroGetCBChecked('_cbMPFilterClosed') === true)
  3942. {
  3943. if(problem.attributes.open === false)
  3944. {
  3945. problemStyle = 'hidden';
  3946. }
  3947. }
  3948.  
  3949. if(problemStyle == 'visible')
  3950. {
  3951. if(uroGetCBChecked('_cbMPFilterTurnProblem') === true) problemStyle = 'hidden';
  3952.  
  3953. if(uroGetCBChecked('_cbMPFilterReopenedProblem') === true)
  3954. {
  3955. if((problem.attributes.open === true) && (problem.attributes.resolvedOn !== null))
  3956. {
  3957. problemStyle = 'hidden';
  3958. }
  3959. }
  3960.  
  3961. if(uroGetCBChecked('_cbInvertMPFilter') === true)
  3962. {
  3963. if(problemStyle == 'hidden') problemStyle = 'visible';
  3964. else problemStyle = 'hidden';
  3965. }
  3966. }
  3967. }
  3968. W.map.problemLayer.markers[urobj].icon.imageDiv.style.visibility = problemStyle;
  3969. }
  3970. }
  3971. }
  3972. uroRenderCustomMarkers('mp');
  3973. }
  3974.  
  3975. function uroToHex(decValue,digits)
  3976. {
  3977. var modifier = 1;
  3978. for(var i=0; i<digits; i++)
  3979. {
  3980. modifier *= 16;
  3981. }
  3982. decValue = parseInt(decValue);
  3983. decValue += modifier;
  3984. var retval = decValue.toString(16);
  3985. retval = retval.substr(-digits);
  3986. retval = retval.toUpperCase();
  3987. return retval;
  3988. }
  3989.  
  3990. function uroFilterPreamble()
  3991. {
  3992. var mapviewport = document.getElementsByClassName("olMapViewport")[0];
  3993. if(mapviewport === null)
  3994. {
  3995. if(uroNullMapViewport === false)
  3996. {
  3997. uroAddLog('caught null mapviewport');
  3998. uroNullMapViewport = true;
  3999. }
  4000. return false;
  4001. }
  4002. uroNullMapViewport = false;
  4003.  
  4004. if((uroGetCBChecked('_cbWhiteBackground') === true) && (uroGetCBChecked('_cbMasterEnable') === true))
  4005. {
  4006. var customColour = '#' + uroToHex(uroGetElmValue('_inputCustomBackgroundRed'),2);
  4007. customColour += uroToHex(uroGetElmValue('_inputCustomBackgroundGreen'),2);
  4008. customColour += uroToHex(uroGetElmValue('_inputCustomBackgroundBlue'),2);
  4009. mapviewport.style.backgroundColor = customColour;
  4010. }
  4011. else
  4012. {
  4013. mapviewport.style.backgroundColor = "#C2C2C2";
  4014. }
  4015.  
  4016. if((uroGetCBChecked('_cbHideAMLayer')) && (uroGetCBChecked('_cbMasterEnable') === true))
  4017. {
  4018. W.map.managedAreasLayer.setOpacity(0);
  4019. }
  4020. else
  4021. {
  4022. W.map.managedAreasLayer.setOpacity(1);
  4023. }
  4024.  
  4025. return true;
  4026. }
  4027.  
  4028. function uroFilterItems_URTabClick()
  4029. {
  4030. uroFilterURs();
  4031. }
  4032. function uroFilterItems_MPTabClick()
  4033. {
  4034. uroFilterProblems();
  4035. }
  4036. function uroFilterItems_PlacesTabClick()
  4037. {
  4038. uroFilterPlaces();
  4039. }
  4040. function uroFilterItems_CamerasTabClick()
  4041. {
  4042. uroFilterCameras();
  4043. }
  4044. function uroFilterItems_MiscTabClick()
  4045. {
  4046. uroFilterItems();
  4047. }
  4048. function uroFilterItems_MasterEnableClick()
  4049. {
  4050. if(uroGetCBChecked('_cbMasterEnable') === false)
  4051. {
  4052. uroHidePopup();
  4053. }
  4054. uroFilterItems();
  4055. }
  4056.  
  4057. function uroScaleTheScaleBar()
  4058. {
  4059. // adjust the scale bar to more accurately reflect true distances at all latitudes
  4060. var currLat = W.map.getCenter().transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326")).lat;
  4061.  
  4062. if((currLat < 85) && (currLat > -85))
  4063. {
  4064. var cosLat = Math.cos((currLat * Math.PI) / 180);
  4065. var scaleElm;
  4066. var elmWidth;
  4067. scaleElm = document.getElementsByClassName('olControlScaleLineTop')[0];
  4068. if(scaleElm.innerHTML.indexOf(' ') !== -1)
  4069. {
  4070. elmWidth = Math.round((scaleElm.clientWidth + 2) / cosLat);
  4071. scaleElm.innerHTML = scaleElm.innerHTML.replace(' ','');
  4072. scaleElm.style.width = elmWidth + 'px';
  4073. }
  4074. scaleElm = document.getElementsByClassName('olControlScaleLineBottom')[0];
  4075. if(scaleElm.innerHTML.indexOf(' ') !== -1)
  4076. {
  4077. elmWidth = Math.round((scaleElm.clientWidth + 2) / cosLat);
  4078. scaleElm.innerHTML = scaleElm.innerHTML.replace(' ','');
  4079. scaleElm.style.width = elmWidth + 'px';
  4080. }
  4081. }
  4082. }
  4083.  
  4084. function uroFilterItems()
  4085. {
  4086. uroScaleTheScaleBar();
  4087. uroFilterProblems();
  4088. uroFilterPlaces();
  4089. uroFilterCameras();
  4090. uroFilterURs();
  4091. }
  4092.  
  4093. function uroFilterItemsOnMove()
  4094. {
  4095. W.map.events.unregister('mousemove',null,uroFilterItemsOnMove);
  4096. uroFilterItems();
  4097. }
  4098.  
  4099.  
  4100. function uroDeleteObject()
  4101. {
  4102. uroAddLog('delete camera ID '+uroShownFID);
  4103. if(W.model.cameras.objects[uroShownFID] === null)
  4104. {
  4105. uroAddLog('camera object not found...');
  4106. return false;
  4107. }
  4108. uroRemoveCamFromWatchList();
  4109. var actionObj = require('Waze/Action/DeleteObject');
  4110. var deleteAction = new actionObj(W.model.cameras.objects[uroShownFID], null);
  4111. W.model.actionManager.add(deleteAction);
  4112. uroExitPopup();
  4113. uroHidePopup();
  4114. return false;
  4115. }
  4116.  
  4117.  
  4118. function uroGetUserNameAndRank(userID)
  4119. {
  4120. var userName;
  4121. var userLevel;
  4122. if(W.model.users.objects[userID] !== undefined)
  4123. {
  4124. userName = W.model.users.objects[userID].userName;
  4125. if(userName === undefined)
  4126. {
  4127. userName = userID;
  4128. }
  4129. userLevel = W.model.users.objects[userID].rank + 1;
  4130. }
  4131. else
  4132. {
  4133. userName = userID;
  4134. userLevel = '?';
  4135. }
  4136. return userName + ' (' + userLevel + ')';
  4137. }
  4138.  
  4139.  
  4140. function uroCheckCommentsForKeyword(idSrc, keyword)
  4141. {
  4142. var ursObj = W.model.updateRequestSessions.objects[idSrc];
  4143. if(typeof(ursObj) == 'undefined') return false;
  4144. if(ursObj.comments.length === 0) return false;
  4145.  
  4146. for(var idx=0; idx<ursObj.comments.length; idx++)
  4147. {
  4148. if(ursObj.comments[idx].text.indexOf(keyword) != -1)
  4149. {
  4150. return true;
  4151. }
  4152. }
  4153. return false;
  4154. }
  4155.  
  4156.  
  4157. function uroGetCustomMarkerIdx(customType)
  4158. {
  4159. if(customType === 0) return 3;
  4160. if(customType === 1) return 3;
  4161. if(customType === 2) return 5;
  4162. if(customType === 3) return 7;
  4163. if(customType === 4) return 9;
  4164. if(customType === 100) return 11;
  4165. if(customType === 101) return 13;
  4166. if(customType === 102) return 15;
  4167. return -1;
  4168. }
  4169.  
  4170. function uroGetCustomType(idSrc, markerType)
  4171. {
  4172. var desc = '';
  4173. if(markerType == "ur")
  4174. {
  4175. var ureq = W.model.mapUpdateRequests.objects[idSrc];
  4176. // UR objects always have a .description attribute, which is set to null if empty...
  4177. if(ureq.attributes.description !== null)
  4178. {
  4179. desc = ureq.attributes.description;
  4180. }
  4181. }
  4182. else if(markerType == "mp")
  4183. {
  4184. var mp = W.model.problems.objects[idSrc];
  4185. // ...whereas MP objects with a blank description don't even get the attribute
  4186. if(mp.attributes.description !== undefined)
  4187. {
  4188. desc = mp.attributes.description;
  4189. }
  4190. }
  4191.  
  4192. if(desc !== '')
  4193. {
  4194. if(desc.indexOf('[ROADWORKS]') != -1) return 0;
  4195. if(desc.indexOf('[CONSTRUCTION]') != -1) return 1;
  4196. if(desc.indexOf('[CLOSURE]') != -1) return 2;
  4197. if(desc.indexOf('[EVENT]') != -1) return 3;
  4198. if(desc.indexOf('[NOTE]') != -1) return 4;
  4199. if(desc.indexOf('[Elgin]') != -1) return 100;
  4200. if(desc.indexOf('[TrafficCast]') != -1) return 101;
  4201. if(desc.indexOf('[TM]') != -1) return 102;
  4202. }
  4203. if(markerType == "ur")
  4204. {
  4205. if(uroCheckCommentsForKeyword(idSrc,'[ROADWORKS]')) return 0;
  4206. if(uroCheckCommentsForKeyword(idSrc,'[CONSTRUCTION]')) return 1;
  4207. if(uroCheckCommentsForKeyword(idSrc,'[CLOSURE]')) return 2;
  4208. if(uroCheckCommentsForKeyword(idSrc,'[EVENT]')) return 3;
  4209. if(uroCheckCommentsForKeyword(idSrc,'[NOTE]')) return 4;
  4210. }
  4211.  
  4212. return -1;
  4213. }
  4214.  
  4215.  
  4216. function uroFormatRestriction(restObj)
  4217. {
  4218. var retval = '<tr>';
  4219. retval += '<td style="text-align:center;">';
  4220. if((restObj.days & 1) == 1) retval += 'S';
  4221. else retval += '-';
  4222. retval += '</td><td style="text-align:center;">';
  4223. if((restObj.days & 2) == 2) retval += 'M';
  4224. else retval += '-';
  4225. retval += '</td><td style="text-align:center;">';
  4226. if((restObj.days & 4) == 4) retval += 'T';
  4227. else retval += '-';
  4228. retval += '</td><td style="text-align:center;">';
  4229. if((restObj.days & 8) == 8) retval += 'W';
  4230. else retval += '-';
  4231. retval += '</td><td style="text-align:center;">';
  4232. if((restObj.days & 16) == 16) retval += 'T';
  4233. else retval += '-';
  4234. retval += '</td><td style="text-align:center;">';
  4235. if((restObj.days & 32) == 32) retval += 'F';
  4236. else retval += '-';
  4237. retval += '</td><td style="text-align:center;">';
  4238. if((restObj.days & 64) == 64) retval += 'S';
  4239. else retval += '-';
  4240.  
  4241. retval += '</td><td>';
  4242.  
  4243. if(restObj.fromDate === null) retval += 'All dates';
  4244. else retval += restObj.fromDate+' to '+restObj.toDate;
  4245.  
  4246. retval += '</td><td>';
  4247.  
  4248. if(restObj.allDay === true) retval += 'All day';
  4249. else retval += restObj.fromTime+' to '+restObj.toTime;
  4250.  
  4251. retval += '</td><td>';
  4252.  
  4253. if(restObj.allVehicleTypes == restObj.vehicleTypes) retval += 'All vehicles';
  4254. else retval += 'Some vehicles';
  4255.  
  4256. retval += '</td><td>';
  4257.  
  4258. if(restObj.description !== null)
  4259. {
  4260. var desc = restObj.description.replace(/<\/?[^>]+(>|$)/g, "");
  4261. desc = uroClickify(desc);
  4262. retval += desc;
  4263. }
  4264.  
  4265. retval += '</td></tr>';
  4266.  
  4267. return retval;
  4268. }
  4269.  
  4270. function uroHidePopup()
  4271. {
  4272. if(uroPopupShown)
  4273. {
  4274. uroDiv.style.visibility = 'hidden';
  4275. uroPopupShown = false;
  4276. uroPopupTimer = -2;
  4277. uroShownFID = -1;
  4278. }
  4279. }
  4280.  
  4281. function uroRecentreSessionOnUR()
  4282. {
  4283. W.map.updateRequestLayer.markers[uroShownFID].icon.imageDiv.click();
  4284. W.map.moveTo(W.map.updateRequestLayer.markers[uroShownFID].lonlat, 5);
  4285. uroHidePopup();
  4286. return false;
  4287. }
  4288.  
  4289. function uroRecentreSessionOnMP()
  4290. {
  4291. W.map.problemLayer.markers[uroShownFID].icon.imageDiv.click();
  4292. W.map.moveTo(W.map.problemLayer.markers[uroShownFID].lonlat, 5);
  4293. uroHidePopup();
  4294. return false;
  4295. }
  4296.  
  4297. function uroRecentreSessionOnPUR()
  4298. {
  4299. W.map.placeUpdatesLayer.markers[uroShownFID].icon.imageDiv.click();
  4300. W.map.moveTo(W.map.placeUpdatesLayer.markers[uroShownFID].lonlat, 5);
  4301. uroHidePopup();
  4302. return false;
  4303. }
  4304.  
  4305. function uroRecentreSessionOnVenueNavPoint()
  4306. {
  4307. W.map.moveTo(uroGetVenueNavPoint(uroShownFID), 5);
  4308. uroHidePopup();
  4309. return false;
  4310. }
  4311.  
  4312. function uroGetDateTimeString(ts)
  4313. {
  4314. var tDateObj = new Date(ts);
  4315. var dateLocale;
  4316. var timeLocale;
  4317. if(uroGetCBChecked('_cbDateFmtDDMMYY')) dateLocale = 'en-gb';
  4318. if(uroGetCBChecked('_cbDateFmtMMDDYY')) dateLocale = 'en-us';
  4319. if(uroGetCBChecked('_cbDateFmtYYMMDD')) dateLocale = 'ja';
  4320. if(uroGetCBChecked('_cbTimeFmt24H')) timeLocale = 'en-gb';
  4321. if(uroGetCBChecked('_cbTimeFmt12H')) timeLocale = 'en-us';
  4322. return tDateObj.toLocaleDateString(dateLocale) + ' ' + tDateObj.toLocaleTimeString(timeLocale);
  4323. }
  4324.  
  4325. function uroParsePxString(pxString)
  4326. {
  4327. return parseInt(pxString.split("px")[0]);
  4328. }
  4329.  
  4330. function uroStackListObj(fid,x,y)
  4331. {
  4332. this.fid = fid;
  4333. this.x = uroTypeCast(x);
  4334. this.y = uroTypeCast(y);
  4335. }
  4336.  
  4337. function uroRestackMarkers()
  4338. {
  4339. if(uroStackList.length === 0) return;
  4340.  
  4341. var markerCollection = null;
  4342. if(uroStackType == 1) markerCollection = W.map.updateRequestLayer.markers;
  4343. else if(uroStackType == 2) markerCollection = W.map.problemLayer.markers;
  4344. else if(uroStackType == 3) markerCollection = W.map.placeUpdatesLayer.markers;
  4345.  
  4346. if(markerCollection !== null)
  4347. {
  4348. for(var idx=0; idx<uroStackList.length; idx++)
  4349. {
  4350. var orig_x = uroStackList[idx].x + 'px';
  4351. var orig_y = uroStackList[idx].y + 'px';
  4352. var fid = uroStackList[idx].fid;
  4353.  
  4354. if(markerCollection[fid] !== undefined)
  4355. {
  4356. markerCollection[fid].icon.imageDiv.style.left = orig_x;
  4357. markerCollection[fid].icon.imageDiv.style.top = orig_y;
  4358. }
  4359. }
  4360. uroStackList = [];
  4361. uroUnstackedMasterID = null;
  4362. uroStackType = null;
  4363. }
  4364. }
  4365.  
  4366. function uroIsIDAlreadyUnstacked(idSrc)
  4367. {
  4368. if(uroStackList.length === 0) return false;
  4369. for(var idx=0; idx<uroStackList.length; idx++)
  4370. {
  4371. if(uroStackList[idx].fid == idSrc) return true;
  4372. }
  4373. return false;
  4374. }
  4375.  
  4376. function uroCheckStacking(stackType, masterID, unstackedX, unstackedY)
  4377. {
  4378. if(W.map.getZoom() < uroGetElmValue('_inputUnstackZoomLevel')) return;
  4379.  
  4380. if(uroIsIDAlreadyUnstacked(masterID) === true) return;
  4381. if(uroPopupDwellTimer > 0) return;
  4382.  
  4383. uroAddLog('checking for marker stack, type '+stackType+'...');
  4384. var stackList = [];
  4385. var threshSquared = uroGetElmValue('_inputUnstackSensitivity');
  4386. threshSquared *= threshSquared;
  4387.  
  4388. var markerCollection = null;
  4389. var marker;
  4390. var tempX = 1000000000;
  4391. if(stackType == 1) markerCollection = W.map.updateRequestLayer.markers;
  4392. else if(stackType == 2) markerCollection = W.map.problemLayer.markers;
  4393. else if(stackType == 3) markerCollection = W.map.placeUpdatesLayer.markers;
  4394.  
  4395. if(markerCollection !== null)
  4396. {
  4397. for(marker in markerCollection)
  4398. {
  4399. if(markerCollection.hasOwnProperty(marker))
  4400. {
  4401. var testMarkerObj = markerCollection[marker];
  4402. var includeInStack = (testMarkerObj.icon.imageDiv.style.visibility != 'hidden');
  4403. var suppressClosed = (testMarkerObj.icon.imageDiv.classList.contains("recently-closed") & (W.map.updateRequestLayer.showHidden === false));
  4404. if(testMarkerObj.model.attributes.geometry.realX === undefined)
  4405. {
  4406. testMarkerObj.model.attributes.geometry.realX = testMarkerObj.model.attributes.geometry.x;
  4407. testMarkerObj.model.attributes.geometry.x = tempX;
  4408. tempX++;
  4409. }
  4410.  
  4411. if((includeInStack) && (!suppressClosed))
  4412. {
  4413. if(testMarkerObj.id != masterID)
  4414. {
  4415. var xdiff = unstackedX - uroParsePxString(markerCollection[testMarkerObj.id].icon.imageDiv.style.left);
  4416. var ydiff = unstackedY - uroParsePxString(markerCollection[testMarkerObj.id].icon.imageDiv.style.top);
  4417. var distSquared = ((xdiff * xdiff) + (ydiff * ydiff));
  4418. if(distSquared < threshSquared)
  4419. {
  4420. stackList.push(testMarkerObj.id);
  4421. }
  4422. }
  4423. }
  4424. }
  4425. }
  4426. }
  4427. if(stackList.length > 0)
  4428. {
  4429. uroAddLog('markers are stacked!');
  4430. if(uroUnstackedMasterID != masterID)
  4431. {
  4432. uroAddLog('unstacked ID mismatch, relocating markers...');
  4433. uroRestackMarkers();
  4434. uroStackType = stackType;
  4435. uroUnstackedMasterID = masterID;
  4436. uroStackList = [];
  4437.  
  4438. // push the highlighted marker onto the stacklist so uroIsIDAlreadyUnstacked() will return true
  4439. uroStackList.push(new uroStackListObj(masterID,unstackedX,unstackedY));
  4440.  
  4441. for(var shoveIdx=0; shoveIdx < stackList.length; shoveIdx++)
  4442. {
  4443. var fid = stackList[shoveIdx];
  4444. var x = uroParsePxString(markerCollection[fid].icon.imageDiv.style.left);
  4445. var y = uroParsePxString(markerCollection[fid].icon.imageDiv.style.top);
  4446. // store the unstacked marker positions so they can be reinstated later
  4447. uroStackList.push(new uroStackListObj(fid,x,y));
  4448. unstackedX += 10;
  4449. unstackedY -= 30;
  4450. markerCollection[fid].icon.imageDiv.style.left = unstackedX + 'px';
  4451. markerCollection[fid].icon.imageDiv.style.top = unstackedY + 'px';
  4452. }
  4453.  
  4454. // hide other markers to prevent confusion with the unstacked markers
  4455. for(marker in markerCollection)
  4456. {
  4457. if(markerCollection.hasOwnProperty(marker))
  4458. {
  4459. var toHideID = markerCollection[marker].id;
  4460. if(uroIsIDAlreadyUnstacked(toHideID) === false)
  4461. {
  4462. markerCollection[toHideID].icon.imageDiv.style.visibility = 'hidden';
  4463. }
  4464. }
  4465. }
  4466. }
  4467. }
  4468. else
  4469. {
  4470. uroRestackMarkers();
  4471. }
  4472. }
  4473.  
  4474. function uroGetVenueNavPoint(uroFID)
  4475. {
  4476. for(var vObj in W.model.venues.objects)
  4477. {
  4478. if(W.model.venues.objects.hasOwnProperty(vObj))
  4479. {
  4480. if(uroFID == vObj)
  4481. {
  4482. return W.model.venues.objects[vObj].getNavigationPoint().point.toLonLat();
  4483. }
  4484. }
  4485. }
  4486. // just in case... return a safe value if the requested venue object wasn't found
  4487. return W.map.getCenter();
  4488. }
  4489.  
  4490. function uroOpenNewTab()
  4491. {
  4492. // flush the current settings into localStorage before the new tab opens, so that when its instance of
  4493. // URO+ fires up it'll have the same settings as this one
  4494. uroSaveSettings();
  4495. return true;
  4496. }
  4497.  
  4498. function uroEditTBR()
  4499. {
  4500. if(uroTBRObj === null)
  4501. {
  4502. return;
  4503. }
  4504. uroTBRObj.click();
  4505. return false;
  4506. }
  4507.  
  4508. function uroNewLookHighlightedItemsCheck(e)
  4509. {
  4510. if(e == 'dwellTimeout')
  4511. {
  4512. }
  4513. else
  4514. {
  4515. if((uroMouseIsDown) && (e.buttons === 0))
  4516. {
  4517. uroAddLog('trapped erroneous mousedown state');
  4518. uroMouseIsDown = false;
  4519. }
  4520. }
  4521. if(uroMouseIsDown)
  4522. {
  4523. return;
  4524. }
  4525.  
  4526. if(OpenLayers === null)
  4527. {
  4528. if(uroNullOpenLayers === false)
  4529. {
  4530. uroAddLog('caught null OpenLayers');
  4531. uroNullOpenLayers = true;
  4532. }
  4533. return;
  4534. }
  4535. uroNullOpenLayers = false;
  4536.  
  4537. var rc = document.getElementById(uroRootContainer);
  4538. if(rc === null)
  4539. {
  4540. if(uroNullRootContainer === false)
  4541. {
  4542. uroAddLog('caught null rootContainer');
  4543. uroNullRootContainer = true;
  4544. }
  4545. return;
  4546. }
  4547. uroNullRootContainer = false;
  4548.  
  4549. if(W.map.updateRequestLayer === null)
  4550. {
  4551. if(uroNullURLayer === false)
  4552. {
  4553. uroAddLog('caught null UR layer');
  4554. uroNullURLayer = true;
  4555. }
  4556. return;
  4557. }
  4558. uroNullURLayer = false;
  4559.  
  4560. if(W.map.problemLayer === null)
  4561. {
  4562. if(uroNullProblemLayer === false)
  4563. {
  4564. uroAddLog('caught null problem layer');
  4565. uroNullProblemLayer = true;
  4566. }
  4567. return;
  4568. }
  4569. uroNullProblemLayer = false;
  4570.  
  4571. if(uroGetCBChecked('_cbMasterEnable') === false)
  4572. {
  4573. return;
  4574. }
  4575.  
  4576. var mouseX;
  4577. var mouseY;
  4578. if(e == 'dwellTimeout')
  4579. {
  4580. mouseX = uroPrevMouseX;
  4581. mouseY = uroPrevMouseY;
  4582. }
  4583. else
  4584. {
  4585. mouseX = e.pageX - document.getElementById('map').getBoundingClientRect().left;
  4586. mouseY = e.pageY - document.getElementById('map').getBoundingClientRect().top;
  4587.  
  4588. var maxJitter = uroGetElmValue('_inputMaxJitter');
  4589. if((Math.abs(uroPrevMouseX - mouseX) > maxJitter) || (Math.abs(uroPrevMouseY - mouseY) > maxJitter))
  4590. {
  4591. uroPopupDwellTimer = uroGetElmValue('_inputPopupDwellTimeout');
  4592. }
  4593. uroPrevMouseX = mouseX;
  4594. uroPrevMouseY = mouseY;
  4595. }
  4596.  
  4597. var result = '';
  4598. var rw;
  4599. var rh;
  4600.  
  4601. var popupXOffset = uroParsePxString(window.getComputedStyle(document.getElementById('sidebar')).getPropertyValue("width"));
  4602. var popupYOffset = $(document.getElementById("WazeMap")).offset().top - 80;
  4603. var uroPopupX = mouseX + popupXOffset + 10;
  4604. var uroPopupY = mouseY + popupYOffset + 10;
  4605.  
  4606. var objHasIgnoreLink = false;
  4607. var objHasDeleteLink = false;
  4608. var objHasAddWatchLink = false;
  4609. var objHasRemoveWatchLink = false;
  4610. var objHasUpdateWatchLink = false;
  4611. var objHasRecentreSessionLink = false;
  4612. var objHasOpenInNewTabLink = false;
  4613.  
  4614. var isVenue = false;
  4615. var newPopupType = null;
  4616. var markerObj;
  4617. var markerPos;
  4618. var markerImg;
  4619. var ureq;
  4620. var idx;
  4621. var hovered;
  4622.  
  4623. // popup for segment restrictions
  4624. if(uroGetCBChecked('_cbInhibitSegPopup') === false)
  4625. {
  4626. for(var slIdx=0; slIdx < W.map.segmentLayer.features.length; slIdx++)
  4627. {
  4628. if(W.map.segmentLayer.features[slIdx].renderIntent == 'highlight')
  4629. {
  4630. var doPopUp = false;
  4631. var segObj;
  4632. var restObj;
  4633. if(W.map.segmentLayer.features[slIdx].fid === null) segObj = W.map.segmentLayer.features[slIdx].model;
  4634. else segObj = W.map.segmentLayer.features[slIdx];
  4635. result += '<table cellpadding=4 border=1">';
  4636. if(segObj.attributes.fwdRestrictions.length > 0)
  4637. {
  4638. doPopUp = true;
  4639. result += '<tr><td colspan=11><b>A-B restrictions:</b></td></tr>';
  4640. for(idx = 0; idx < segObj.attributes.fwdRestrictions.length; idx++)
  4641. {
  4642. restObj = segObj.attributes.fwdRestrictions[idx];
  4643. result += uroFormatRestriction(restObj);
  4644. }
  4645. }
  4646. if (segObj.attributes.revRestrictions.length > 0)
  4647. {
  4648. doPopUp = true;
  4649. result += '<tr><td colspan=11><b>B-A restrictions:</b></td></tr>';
  4650. for(idx = 0; idx < segObj.attributes.revRestrictions.length; idx++)
  4651. {
  4652. restObj = segObj.attributes.revRestrictions[idx];
  4653. result += uroFormatRestriction(restObj);
  4654. }
  4655. }
  4656. result += '</table>';
  4657. if(W.map.closuresMarkerLayer.getVisibility() === true)
  4658. {
  4659. result += '<table cellpadding=4 border=1" width="100%">';
  4660. if(segObj.attributes.hasClosures === true)
  4661. {
  4662. var hasFwd = false;
  4663. var hasRev = false;
  4664. var rcObj;
  4665. var roadClosure;
  4666. for(roadClosure in W.model.roadClosures.objects)
  4667. {
  4668. if(W.model.roadClosures.objects.hasOwnProperty(roadClosure))
  4669. {
  4670. rcObj = W.model.roadClosures.objects[roadClosure];
  4671. if(rcObj.segID == segObj.attributes.id)
  4672. {
  4673. if(rcObj.forward === true)
  4674. {
  4675. if(hasFwd === false)
  4676. {
  4677. result += '<tr><td colspan=3><b>A-B closures:</b></td></tr>';
  4678. hasFwd = true;
  4679. }
  4680.  
  4681. if(rcObj.active === true)
  4682. {
  4683. result += '<tr>';
  4684. }
  4685. else
  4686. {
  4687. result += '<tr bgcolor="#C0C0C0">';
  4688. }
  4689.  
  4690. var startDate = rcObj.startDate;
  4691. var endDate = "unknown";
  4692. if(rcObj.endDate !== null)
  4693. {
  4694. endDate = rcObj.endDate;
  4695. }
  4696. var provider = "---";
  4697. if(rcObj.provider !== null)
  4698. {
  4699. provider = rcObj.provider;
  4700. }
  4701. var reason = "---";
  4702. if(rcObj.reason !== null)
  4703. {
  4704. reason = rcObj.reason;
  4705. }
  4706. result += '<td>' + startDate + ' to ' + endDate + '</td>';
  4707. result += '<td>' + provider + '</td>';
  4708. result += '<td>' + reason + '</td>';
  4709. result += '</td></tr>';
  4710. }
  4711. else
  4712. {
  4713. hasRev = true;
  4714. }
  4715. }
  4716. }
  4717. }
  4718. if(hasRev === true)
  4719. {
  4720. result += '<tr><td colspan=3><b>B-A closures:</b></td></tr>';
  4721. for(roadClosure in W.model.roadClosures.objects)
  4722. {
  4723. if(W.model.roadClosures.objects.hasOwnProperty(roadClosure))
  4724. {
  4725. rcObj = W.model.roadClosures.objects[roadClosure];
  4726. if(rcObj.segID == segObj.attributes.id)
  4727. {
  4728. if(rcObj.forward === false)
  4729. {
  4730. if(rcObj.active === true)
  4731. {
  4732. result += '<tr>';
  4733. }
  4734. else
  4735. {
  4736. result += '<tr bgcolor="#C0C0C0">';
  4737. }
  4738.  
  4739. result += '<td>' + rcObj.startDate + ' to ' + rcObj.endDate + '</td>';
  4740. result += '<td>' + rcObj.provider + '</td>';
  4741. result += '<td>' + rcObj.reason + '</td>';
  4742. result += '</td></tr>';
  4743. }
  4744. }
  4745. }
  4746. }
  4747. }
  4748. if((hasFwd === true) || (hasRev === true))
  4749. {
  4750. doPopUp = true;
  4751. }
  4752. }
  4753. result += '</table>';
  4754. }
  4755.  
  4756. if(doPopUp === true)
  4757. {
  4758. if(segObj.attributes.id === null) uroFID = segObj.id;
  4759. else uroFID = segObj.attributes.id;
  4760. newPopupType = 'segment_restriction';
  4761. }
  4762. break;
  4763. }
  4764. }
  4765. }
  4766.  
  4767. // popup for restricted turns
  4768. if(newPopupType === null)
  4769. {
  4770. if(uroGetCBChecked('_cbInhibitTurnsPopup') === false)
  4771. {
  4772. var turnMarkerCount = W.map.layers[uroTurnsLayerIdx].markers.length;
  4773. if(turnMarkerCount > 0)
  4774. {
  4775. for(idx=0; idx<turnMarkerCount; idx++)
  4776. {
  4777. markerObj = W.map.layers[uroTurnsLayerIdx].markers[idx];
  4778. var arrowElm = markerObj.icon.imageDiv.childNodes[0];
  4779. markerImg = window.getComputedStyle(arrowElm).getPropertyValue("background-image");
  4780. markerPos = window.getComputedStyle(arrowElm).getPropertyValue("background-position");
  4781. markerPos = markerPos.split(' ');
  4782. markerPos = parseInt(markerPos[1].substr(0,markerPos[1].length-2));
  4783.  
  4784. hovered = false;
  4785.  
  4786. if(markerImg.indexOf('turns-sa7bd56a5e6.png') != -1)
  4787. {
  4788. if(markerPos == -222)
  4789. {
  4790. hovered = true;
  4791. }
  4792. }
  4793. if(hovered === true)
  4794. {
  4795. uroAddLog('hover over restricted turn marker');
  4796. uroTBRObj = arrowElm.childNodes[0];
  4797. var trObj = ($(arrowElm).data('model'));
  4798. var resObj = null;
  4799. if(trObj.fromSeg.attributes.fromRestrictions !== undefined)
  4800. {
  4801. resObj = trObj.fromSeg.attributes.fromRestrictions[trObj.toSeg.attributes.id];
  4802. }
  4803. if(resObj === null)
  4804. {
  4805. if(trObj.fromSeg.attributes.toRestrictions !== undefined)
  4806. {
  4807. resObj = trObj.fromSeg.attributes.toRestrictions[trObj.toSeg.attributes.id];
  4808. }
  4809. }
  4810.  
  4811. result += '<label id="_editTBR">Click to edit</label><br>';
  4812. result += '<table cellpadding=4 border=1">';
  4813. for(var resIdx=0; resIdx < resObj.length; resIdx++)
  4814. {
  4815. result += uroFormatRestriction(resObj[resIdx]);
  4816. }
  4817. result += '</table>';
  4818. uroFID = markerObj.icon.imageDiv._eventCacheID;
  4819. newPopupType = 'turn_restriction';
  4820. break;
  4821. }
  4822. }
  4823. }
  4824. }
  4825. }
  4826.  
  4827. var targetTab = '';
  4828. // popup for landmarks
  4829. if((newPopupType === null) && (uroGetCBChecked('_cbInhibitLandmarkPopup') === false))
  4830. {
  4831. uroPlaceSelected = false;
  4832. for(var llFeatureIdx=0; llFeatureIdx < W.map.landmarkLayer.features.length; llFeatureIdx++)
  4833. {
  4834. var renderIntent = W.map.landmarkLayer.features[llFeatureIdx].renderIntent;
  4835. if(renderIntent == 'highlight')
  4836. {
  4837. var venueObj;
  4838. if(W.map.landmarkLayer.features[llFeatureIdx].fid === null) venueObj = W.map.landmarkLayer.features[llFeatureIdx].model;
  4839. else venueObj = W.map.landmarkLayer.features[llFeatureIdx];
  4840.  
  4841. if(venueObj.attributes.id === null) uroFID = venueObj.id;
  4842. else uroFID = venueObj.attributes.id;
  4843.  
  4844. var navpointPos=new OpenLayers.LonLat();
  4845. navpointPos = uroGetVenueNavPoint(uroFID);
  4846. navpointPos.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326"));
  4847.  
  4848. result += '<b>';
  4849. if(venueObj.attributes.name === '') result += 'Unnamed landmark';
  4850. else result += venueObj.attributes.name;
  4851. result += '</b><br>';
  4852.  
  4853. result += '<ul>';
  4854. for(idx = 0; idx < venueObj.attributes.categories.length; idx++)
  4855. {
  4856. result += '<li>' + I18n.lookup("venues.categories")[venueObj.attributes.categories[idx]];
  4857. }
  4858. result += '</ul>';
  4859.  
  4860. if(venueObj.attributes.residential === true)
  4861. {
  4862. result += '<i>Residential</i>';
  4863. }
  4864.  
  4865. var npLink = document.location.href;
  4866. var npLayers = '&layers='+W.map.mapState.getLayerVisibilityBitmask();
  4867. npLink = npLink.substr(0,npLink.indexOf('?zoom'));
  4868. npLink += '?zoom=5&lat='+navpointPos.lat+'&lon='+navpointPos.lon+npLayers;
  4869.  
  4870. targetTab = "_uroTab_" + Math.round(Math.random()*1000000);
  4871. result += '<hr>Jump to nav point: <a href="'+npLink+'" id="_openInNewTab" target="'+targetTab+'">in new tab</a> - ';
  4872. objHasOpenInNewTabLink = true;
  4873. result += '<a href="#" id="_recentreSession">in this tab</a>';
  4874. objHasRecentreSessionLink = true;
  4875.  
  4876. newPopupType = 'venue';
  4877. isVenue = true;
  4878. break;
  4879. }
  4880. else if((renderIntent == 'select') || (renderIntent == 'highlightselected'))
  4881. {
  4882. uroPlaceSelected = true;
  4883. }
  4884. }
  4885. }
  4886.  
  4887. var unstackedX;
  4888. var unstackedY;
  4889. var ureqID = null;
  4890. var isUR = false;
  4891. var isProblem = false;
  4892. var isTurnProb = false;
  4893. var isPlaceUpdate = false;
  4894. // look for URs, place updates and problems
  4895. if(newPopupType === null)
  4896. {
  4897. var customIdx;
  4898. var idSrc = null;
  4899. if(uroGetCBChecked('_cbInhibitURPopup') === false)
  4900. {
  4901. hovered = false;
  4902. for(var markerURL in W.map.updateRequestLayer.markers)
  4903. {
  4904. if(W.map.updateRequestLayer.markers.hasOwnProperty(markerURL))
  4905. {
  4906. markerObj = W.map.updateRequestLayer.markers[markerURL];
  4907. markerImg = markerObj.icon.$div.css('background-image');
  4908. markerPos = markerObj.icon.$div.css('background-position');
  4909. markerPos = markerPos.split(' ');
  4910. markerPos = parseInt(markerPos[1].substr(0,markerPos[1].length-2));
  4911. var urIDSrc = markerObj.id;
  4912. if(markerImg.indexOf('problems-s8f369ca968.png') != -1)
  4913. {
  4914. if((markerPos == -403) || (markerPos == -483) || (markerPos == -563) || (markerPos == -643))
  4915. {
  4916. hovered = true;
  4917. uroAddLog('UR image type 1');
  4918. }
  4919. }
  4920. else if(markerImg.indexOf('problems-se224ab677e.png') != -1)
  4921. {
  4922. if((markerPos == -40) || (markerPos == -160) || (markerPos == -200) || (markerPos == -240))
  4923. {
  4924. hovered = true;
  4925. uroAddLog('UR image type 2');
  4926. }
  4927. }
  4928. else
  4929. {
  4930. if(markerPos > -200)
  4931. {
  4932. hovered = true;
  4933. uroAddLog('UR image type 3');
  4934. }
  4935. }
  4936. if(hovered === true)
  4937. {
  4938. isUR = true;
  4939. newPopupType = 'ur';
  4940. uroAddLog('hover over UR ID '+urIDSrc);
  4941.  
  4942. unstackedX = uroParsePxString(W.map.updateRequestLayer.markers[urIDSrc].icon.imageDiv.style.left);
  4943. unstackedY = uroParsePxString(W.map.updateRequestLayer.markers[urIDSrc].icon.imageDiv.style.top);
  4944.  
  4945. // override popup base position
  4946. uroPopupX = unstackedX + popupXOffset + 6;
  4947. uroPopupY = unstackedY + popupYOffset + 46;
  4948. uroPopupX -= uroParsePxString(W.map.segmentLayer.div.style.left);
  4949. uroPopupY -= uroParsePxString(W.map.segmentLayer.div.style.top);
  4950.  
  4951. // check for stacking...
  4952. if(uroShownFID != idSrc)
  4953. {
  4954. uroCheckStacking(1,urIDSrc, unstackedX, unstackedY);
  4955. }
  4956.  
  4957. if(urIDSrc != uroCustomMarkerFID)
  4958. {
  4959. if(uroCustomMarkerFID !== null)
  4960. {
  4961. customIdx = uroGetCustomMarkerIdx(uroGetCustomType(uroCustomMarkerFID, uroCustomMarkerType));
  4962. uroChangeCustomMarkers(uroCustomMarkerFID,false,customIdx,uroCustomMarkerType);
  4963. uroCustomMarkerFID = null;
  4964. }
  4965. customIdx = uroGetCustomMarkerIdx(uroGetCustomType(urIDSrc, "ur"));
  4966. if(customIdx != -1)
  4967. {
  4968. uroCustomMarkerFID = urIDSrc;
  4969. uroCustomMarkerType = "ur";
  4970. uroChangeCustomMarkers(urIDSrc,hovered,customIdx,uroCustomMarkerType);
  4971. }
  4972. }
  4973. idSrc = urIDSrc;
  4974. break;
  4975. }
  4976. }
  4977. }
  4978. if((hovered === false) && (uroStackType == 1))
  4979. {
  4980. uroRestackMarkers();
  4981. uroFilterURs();
  4982. }
  4983.  
  4984. if((idSrc === null) && (uroCustomMarkerFID !== null))
  4985. {
  4986. customIdx = uroGetCustomMarkerIdx(uroGetCustomType(uroCustomMarkerFID, uroCustomMarkerType));
  4987. uroChangeCustomMarkers(uroCustomMarkerFID,false, customIdx,uroCustomMarkerType);
  4988. uroCustomMarkerFID = null;
  4989. uroCustomMarkerType = null;
  4990. }
  4991. }
  4992.  
  4993. if((newPopupType === null) && (uroGetCBChecked('_cbInhibitPUPopup') === false))
  4994. {
  4995. hovered = false;
  4996. for(var markerPUL in W.map.placeUpdatesLayer.markers)
  4997. {
  4998. if(W.map.placeUpdatesLayer.markers.hasOwnProperty(markerPUL))
  4999. {
  5000. markerObj = W.map.placeUpdatesLayer.markers[markerPUL];
  5001. markerImg = markerObj.icon.$div.css('background-image');
  5002. markerPos = markerObj.icon.$div.css('background-position');
  5003. markerPos = markerPos.split(' ');
  5004. markerPos = parseInt(markerPos[1].substr(0,markerPos[1].length-2));
  5005.  
  5006. if(markerImg.indexOf('placeUpdates-sb30471988c.png') != -1)
  5007. {
  5008. // absolute offsets: 0 = new place, -120 = flagged, -240 = new photo, -360 = updated details
  5009. // relative offsets: 0 = green, -40 = highlighted, -80 = default
  5010. if(((markerPos + 40) % 120) === 0)
  5011. {
  5012. hovered = true;
  5013. uroAddLog('PUR marker type 1');
  5014. }
  5015. }
  5016. else if(markerImg.indexOf('placeUpdates-s2e8d9c5ce4.png') != -1)
  5017. {
  5018. if
  5019. (
  5020. (markerObj.icon.$div.css("filter") == "brightness(110%)") ||
  5021. (markerObj.icon.$div.css("webkit-filter") == "brightness(1.1)")
  5022. )
  5023. {
  5024. hovered = true;
  5025. uroAddLog('PUR marker type 2');
  5026. }
  5027. }
  5028. if(hovered === true)
  5029. {
  5030. idSrc = markerObj.id;
  5031. unstackedX = uroParsePxString(W.map.placeUpdatesLayer.markers[idSrc].icon.imageDiv.style.left);
  5032. unstackedY = uroParsePxString(W.map.placeUpdatesLayer.markers[idSrc].icon.imageDiv.style.top);
  5033.  
  5034. // override popup base position
  5035. uroPopupX = unstackedX + popupXOffset + 6;
  5036. uroPopupY = unstackedY + popupYOffset + 46;
  5037. uroPopupX -= uroParsePxString(W.map.segmentLayer.div.style.left);
  5038. uroPopupY -= uroParsePxString(W.map.segmentLayer.div.style.top);
  5039.  
  5040. if(uroShownFID != idSrc)
  5041. {
  5042. // check for stacking...
  5043. uroCheckStacking(3,idSrc, unstackedX, unstackedY);
  5044. }
  5045.  
  5046. isPlaceUpdate = true;
  5047. newPopupType = 'pur';
  5048. uroAddLog('hover over placeUpdate ID '+idSrc);
  5049. break;
  5050. }
  5051. }
  5052. }
  5053. if((hovered === false) && (uroStackType == 3))
  5054. {
  5055. uroRestackMarkers();
  5056. uroFilterPlaces();
  5057. }
  5058. }
  5059.  
  5060. if((newPopupType === null) && (uroGetCBChecked('_cbInhibitMPPopup') === false))
  5061. {
  5062. hovered = false;
  5063. for(var markerPL in W.map.problemLayer.markers)
  5064. {
  5065. if(W.map.problemLayer.markers.hasOwnProperty(markerPL))
  5066. {
  5067. markerObj = W.map.problemLayer.markers[markerPL];
  5068. markerImg = markerObj.icon.$div.css('background-image');
  5069. markerPos = markerObj.icon.$div.css('background-position');
  5070. markerPos = markerPos.split(' ');
  5071. markerPos = parseInt(markerPos[1].substr(0,markerPos[1].length-2));
  5072.  
  5073. if(markerImg.indexOf('problems-s8f369ca968.png') != -1)
  5074. {
  5075. if((markerPos == -65) || (markerPos == -145) || (markerPos == -225) || (markerPos == -305))
  5076. {
  5077. hovered = true;
  5078. uroAddLog('Problem image type 1');
  5079. }
  5080. }
  5081. else if(markerImg.indexOf('problems-se224ab677e.png') != -1)
  5082. {
  5083. if((markerPos == -320) || (markerPos == -560) || (markerPos == -520) || (markerPos == -440))
  5084. {
  5085. hovered = true;
  5086. uroAddLog('Problem image type 2');
  5087. }
  5088. }
  5089. else
  5090. {
  5091. if(markerPos > -200)
  5092. {
  5093. hovered = true;
  5094. uroAddLog('Problem image type 3');
  5095. }
  5096. }
  5097. if(hovered === true)
  5098. {
  5099. idSrc = null;
  5100. if(markerObj.model.fid === null) idSrc = markerObj.id;
  5101. else idSrc = markerObj.model.fid;
  5102.  
  5103. unstackedX = uroParsePxString(W.map.problemLayer.markers[idSrc].icon.imageDiv.style.left);
  5104. unstackedY = uroParsePxString(W.map.problemLayer.markers[idSrc].icon.imageDiv.style.top);
  5105.  
  5106. // override popup base position
  5107. uroPopupX = unstackedX + popupXOffset + 6;
  5108. uroPopupY = unstackedY + popupYOffset + 46;
  5109. uroPopupX -= uroParsePxString(W.map.segmentLayer.div.style.left);
  5110. uroPopupY -= uroParsePxString(W.map.segmentLayer.div.style.top);
  5111.  
  5112. // check for stacking...
  5113. if(uroShownFID != idSrc)
  5114. {
  5115. uroCheckStacking(2,idSrc, unstackedX, unstackedY);
  5116. }
  5117.  
  5118. if(idSrc != uroCustomMarkerFID)
  5119. {
  5120. if(uroCustomMarkerFID !== null)
  5121. {
  5122. customIdx = uroGetCustomMarkerIdx(uroGetCustomType(uroCustomMarkerFID, uroCustomMarkerType));
  5123. uroChangeCustomMarkers(uroCustomMarkerFID,false,customIdx,uroCustomMarkerType);
  5124. uroCustomMarkerFID = null;
  5125. uroCustomMarkerType = null;
  5126. }
  5127. customIdx = uroGetCustomMarkerIdx(uroGetCustomType(idSrc, "mp"));
  5128. if(customIdx != -1)
  5129. {
  5130. uroCustomMarkerFID = idSrc;
  5131. uroCustomMarkerType = "mp";
  5132. uroChangeCustomMarkers(idSrc,hovered,customIdx,uroCustomMarkerType);
  5133. }
  5134. }
  5135.  
  5136.  
  5137. isProblem = true;
  5138. newPopupType = 'map_problem';
  5139. uroAddLog('hover over problem ID '+idSrc);
  5140.  
  5141. break;
  5142. }
  5143. }
  5144. }
  5145. if((hovered === false) && (uroStackType == 2))
  5146. {
  5147. uroRestackMarkers();
  5148. uroFilterProblems();
  5149. }
  5150. if((idSrc === null) && (uroCustomMarkerFID !== null))
  5151. {
  5152. var newCustomIdx = uroGetCustomMarkerIdx(uroGetCustomType(uroCustomMarkerFID, uroCustomMarkerType));
  5153. uroChangeCustomMarkers(uroCustomMarkerFID, false, newCustomIdx, uroCustomMarkerType);
  5154. uroCustomMarkerFID = null;
  5155. uroCustomMarkerType = null;
  5156. }
  5157. }
  5158.  
  5159. if (idSrc !== null)
  5160. {
  5161. ureq = null;
  5162. if(isUR) ureq = W.model.mapUpdateRequests.objects[idSrc];
  5163. else if(isProblem)
  5164. {
  5165. ureq = W.model.problems.objects[idSrc];
  5166. if(ureq === undefined)
  5167. {
  5168. if(uroDOMHasTurnProblems)
  5169. {
  5170. ureq = W.model.turnProblems.objects[idSrc];
  5171. if(ureq !== undefined) isTurnProb = true;
  5172. }
  5173. }
  5174. }
  5175. else if(isPlaceUpdate) ureq = W.map.placeUpdatesLayer.markers[idSrc].model;
  5176.  
  5177. if(ureq.fid !== null) ureqID = ureq.fid;
  5178. else if(ureq.id !== null) ureqID = ureq.id;
  5179. else if(ureq.attributes.id !== null) ureqID = ureq.attributes.id;
  5180.  
  5181. uroFID = ureqID;
  5182. }
  5183. else
  5184. {
  5185. uroFID = -1;
  5186. }
  5187.  
  5188. //if((uroFID != uroShownFID) && (uroFID != -1))
  5189. if(uroFID != -1)
  5190. {
  5191. var uroDaysResolved;
  5192. if(isUR)
  5193. {
  5194. uroAddLog('building popup for UR '+idSrc);
  5195. result = '<b>Update Request ('+idSrc+'): ' + I18n.lookup("update_requests.types")[ureq.attributes.type] + '</b><br>';
  5196. if(ureq.attributes.description !== null)
  5197. {
  5198. var desc = ureq.attributes.description.replace(/<\/?[^>]+(>|$)/g, "");
  5199. if(desc != "null")
  5200. {
  5201. desc = uroClickify(desc);
  5202. result += desc + '<br>';
  5203. }
  5204. }
  5205. var uroDaysOld = uroGetURAge(ureq,0,false);
  5206. var uroSubmittedTS = uroGetURAge(ureq,0,true);
  5207. if(uroSubmittedTS != -1)
  5208. {
  5209. uroSubmittedTS = uroGetDateTimeString(uroSubmittedTS);
  5210. }
  5211. if(uroDaysOld != -1)
  5212. {
  5213. result += '<i>Submitted ' + uroParseDaysAgo(uroDaysOld) + ' ';
  5214. if(uroSubmittedTS != -1) result += '(' + uroSubmittedTS + ') ';
  5215. if(ureq.attributes.guestUserName !== undefined)
  5216. {
  5217. result += 'via Livemap';
  5218. if(ureq.attributes.guestUserName !== '')
  5219. {
  5220. result += ' by '+ureq.attributes.guestUserName.replace(/<\/?[^>]+(>|$)/g, "");
  5221. }
  5222. }
  5223. result += '</i>';
  5224. }
  5225. if(ureq.attributes.resolvedOn !== null)
  5226. {
  5227. uroDaysResolved = uroGetURAge(ureq,1,false);
  5228. var uroResolvedTS = uroGetURAge(ureq,1,true);
  5229. if(uroResolvedTS != -1)
  5230. {
  5231. uroResolvedTS = uroGetDateTimeString(uroResolvedTS);
  5232. }
  5233.  
  5234. if(uroDaysResolved != -1)
  5235. {
  5236. result += '<br><i>Closed ' + uroParseDaysAgo(uroDaysResolved) + ' ';
  5237. if(uroResolvedTS != -1) result += '(' + uroResolvedTS + ')</i>';
  5238.  
  5239. result += '<br><i>Marked as ';
  5240. if(ureq.attributes.resolution === 0) result += 'solved';
  5241. else if(ureq.attributes.resolution == 1) result += 'not identified';
  5242. else result += 'unknown';
  5243. if(ureq.attributes.resolvedBy !== null)
  5244. {
  5245. result += ' by '+uroGetUserNameAndRank(ureq.attributes.resolvedBy);
  5246. }
  5247. result += '</i>';
  5248. }
  5249. }
  5250. if(W.model.updateRequestSessions.objects[ureqID] !== undefined)
  5251. {
  5252. var hasMyComments = uroURHasMyComments(ureqID);
  5253. var nComments = W.model.updateRequestSessions.objects[ureqID].comments.length;
  5254. result += '<br>' + nComments + ' comment';
  5255. if(nComments != 1) result += 's';
  5256. if((hasMyComments === false) && (nComments > 0)) result += ' (none by me)';
  5257. if(nComments > 0)
  5258. {
  5259. var commentDaysOld = uroGetCommentAge(W.model.updateRequestSessions.objects[ureqID].comments[nComments-1]);
  5260. if(commentDaysOld != -1)
  5261. {
  5262. result += ', last update '+uroParseDaysAgo(commentDaysOld);
  5263. }
  5264. }
  5265. }
  5266. }
  5267. else if(isProblem)
  5268. {
  5269. uroAddLog('building popup for problem '+idSrc);
  5270. if(isTurnProb) result = '<b>Turn Problem ('+idSrc+'): ' + I18n.lookup("problems.types").turn.title;
  5271. else
  5272. {
  5273. result = '<b>Map Problem ('+idSrc+'): ';
  5274.  
  5275. var problemType = null;
  5276. if(uroDOMHasTurnProblems)
  5277. {
  5278. problemType = ureq.attributes.problemType;
  5279. }
  5280. else
  5281. {
  5282. problemType = ureq.attributes.subType;
  5283. }
  5284.  
  5285. if(problemType == 300)
  5286. {
  5287. result += I18n.lookup("problems.panel.closure.title");
  5288. }
  5289. else
  5290. {
  5291. if(I18n.lookup("problems.types")[problemType] === undefined) result += 'Unknown problem type ('+problemType+')';
  5292. else result += I18n.lookup("problems.types")[problemType].title;
  5293. }
  5294. }
  5295. result += '</b><br>';
  5296. if(ureq.attributes.description !== undefined)
  5297. {
  5298. result += 'Description: ' + ureq.attributes.description + '<br>';
  5299. }
  5300. if(ureq.attributes.extraInfo !== undefined)
  5301. {
  5302. result += 'ExtraInfo: ' + ureq.attributes.extraInfo + '<br>';
  5303. }
  5304. if(ureq.attributes.provider !== undefined)
  5305. {
  5306. result += 'Provider: ' + ureq.attributes.provider + '<br>';
  5307. }
  5308. if(ureq.attributes.resolvedOn !== undefined)
  5309. {
  5310. uroDaysResolved = uroGetURAge(ureq,1,false);
  5311. if(uroDaysResolved != -1)
  5312. {
  5313. result += '<br><i>Closed ' + uroParseDaysAgo(uroDaysResolved) + ' ';
  5314. if(ureq.attributes.resolvedBy !== undefined)
  5315. {
  5316. result += ' by '+uroGetUserNameAndRank(ureq.attributes.resolvedBy);
  5317. }
  5318.  
  5319. if((ureq.attributes.open === true) && (ureq.attributes.resolvedOn !== undefined))
  5320. {
  5321. result += '<br>Reopened by Waze';
  5322. }
  5323. result += '</i>';
  5324. }
  5325. }
  5326. }
  5327. else if(isPlaceUpdate)
  5328. {
  5329. uroAddLog('building popup for placeUpdate '+idSrc);
  5330. result = '<b>';
  5331. if(ureq.attributes.name === '') result += 'Unnamed landmark';
  5332. else result += ureq.attributes.name;
  5333. result += '</b><br>';
  5334.  
  5335. result += '<ul>';
  5336. for(idx = 0; idx < ureq.attributes.categories.length; idx++)
  5337. {
  5338. result += '<li>' + I18n.lookup("venues.categories")[ureq.attributes.categories[idx]];
  5339. }
  5340. result += '</ul>';
  5341.  
  5342. if(ureq.attributes.residential === true)
  5343. {
  5344. result += '<i>Residential</i>';
  5345. }
  5346.  
  5347. var daysOld = uroGetPURAge(ureq);
  5348. if(daysOld != -1)
  5349. {
  5350. result += '<br><i>Submitted '+uroParseDaysAgo(daysOld)+'</i>';
  5351. }
  5352. }
  5353.  
  5354. // add "open new WME tab" link
  5355. var urPos=new OpenLayers.LonLat();
  5356. if(isPlaceUpdate)
  5357. {
  5358. urPos=ureq.geometry.bounds.centerLonLat.clone();
  5359. }
  5360. else
  5361. {
  5362. if(ureq.geometry.realX === undefined)
  5363. {
  5364. urPos.lon = ureq.geometry.x;
  5365. }
  5366. else
  5367. {
  5368. urPos.lon = ureq.geometry.realX;
  5369. }
  5370. urPos.lat = ureq.geometry.y;
  5371. }
  5372. urPos.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326"));
  5373. var urLink = document.location.href;
  5374. var urLayers = '&layers='+W.map.mapState.getLayerVisibilityBitmask();
  5375. urLink = urLink.substr(0,urLink.indexOf('?zoom'));
  5376. urLink += '?zoom=5&lat='+urPos.lat+'&lon='+urPos.lon+urLayers;
  5377.  
  5378. if(isUR) urLink += '&mapUpdateRequest='+idSrc;
  5379. else if(isTurnProb) urLink += '&showturn='+idSrc+'&endshow';
  5380. else if(isProblem) urLink += '&mapProblem='+idSrc;
  5381. else if(isPlaceUpdate) urLink += '&showpur='+idSrc+'&endshow';
  5382.  
  5383. targetTab = "_uroTab_" + Math.round(Math.random()*1000000);
  5384. result += '<hr><ul><li><a href="'+urLink+'" id="_openInNewTab" target="'+targetTab+'">Open in new tab</a> - ';
  5385. objHasOpenInNewTabLink = true;
  5386. result += '<a href="#" id="_recentreSession">centre in current tab</a>';
  5387. objHasRecentreSessionLink = true;
  5388.  
  5389. // add "open new livemap tab" link
  5390. var lmLink = null;
  5391. if(document.getElementsByClassName("waze-header-menu").length === 0)
  5392. {
  5393. uroAddLog('Livemap link in livemap element');
  5394. lmLink = document.getElementById('livemap').href;
  5395. }
  5396. else
  5397. {
  5398. uroAddLog('Livemap link in header menu, locating...');
  5399. var menuItems = document.getElementsByClassName("waze-header-menu")[0];
  5400. for(var miloop = 0; miloop<menuItems.childElementCount; miloop++)
  5401. {
  5402. if(menuItems.children[miloop].innerHTML.indexOf('livemap') != -1)
  5403. {
  5404. uroAddLog('found link in menu entry '+miloop);
  5405. lmLink = menuItems.children[miloop].getElementsByTagName('a')[0].href;
  5406. uroAddLog(lmLink);
  5407. }
  5408. }
  5409. }
  5410. if(lmLink !== null)
  5411. {
  5412. var zpos = lmLink.indexOf('?');
  5413. if(zpos > -1) lmLink = lmLink.substr(0,zpos);
  5414. lmLink += '?zoom=17&lat='+urPos.lat+'&lon='+urPos.lon+'&layers=BTTTT';
  5415. result += '<li><a href="'+lmLink+'" target="_lmTab">Open in new livemap tab</a>';
  5416. }
  5417.  
  5418. if(!isPlaceUpdate)
  5419. {
  5420. // add "ignore for this session" link
  5421. result += '<li><a href="#" id="_addtoignore">Hide for this session</a></ul>';
  5422. objHasIgnoreLink = true;
  5423. }
  5424. }
  5425. }
  5426.  
  5427. // look for cameras
  5428. if((newPopupType === null) && (uroGetCBChecked('_cbInhibitCamPopup') === false))
  5429. {
  5430. for(var clFeatureIdx = 0; clFeatureIdx < W.map.camerasLayer.features.length; clFeatureIdx++)
  5431. {
  5432. if(W.map.camerasLayer.features[clFeatureIdx].renderIntent == 'highlight')
  5433. {
  5434. if(W.map.camerasLayer.features[clFeatureIdx].fid === null) ureq = W.map.camerasLayer.features[clFeatureIdx].model;
  5435. else ureq = W.map.camerasLayer.features[clFeatureIdx];
  5436.  
  5437. if(ureq.fid === null) ureqID = ureq.attributes.id;
  5438. else ureqID = ureq.fid;
  5439.  
  5440. // test isSelected() so that we only do overview data on cameras that are being hovered over
  5441. if(ureq.isSelected() === false)
  5442. {
  5443. newPopupType = 'camera';
  5444. uroFID = ureqID;
  5445. uroAddLog('generating popup for camera '+uroFID);
  5446. if(I18n.lookup("edit.camera.fields.type") === undefined)
  5447. {
  5448. result += '<b>Camera: ' + ureq.TYPES[ureq.attributes.type] + '</b><br>';
  5449. }
  5450. else
  5451. {
  5452. result += '<b>Camera: ' + I18n.lookup("edit.camera.fields.type")[ureq.attributes.type] + '</b><br>';
  5453. }
  5454. result += 'ID: '+uroFID+'<br>';
  5455. result += 'Created by ';
  5456. var userID;
  5457. if(W.model.users.get(ureq.attributes.createdBy) !== undefined)
  5458. {
  5459. userID = ureq.attributes.createdBy;
  5460. result += uroGetUserNameAndRank(userID);
  5461. }
  5462. else result += 'unknown';
  5463. result += ', ';
  5464. var camAge = uroGetCameraAge(ureq,1);
  5465. if(camAge != -1)
  5466. {
  5467. result += uroParseDaysAgo(camAge);
  5468. }
  5469. else result += 'unknown days ago';
  5470. result += '<br>Updated by ';
  5471. if(W.model.users.get(ureq.attributes.updatedBy) !== undefined)
  5472. {
  5473. userID = ureq.attributes.updatedBy;
  5474. var userName = W.model.users.objects[userID].userName;
  5475. var userLevel = W.model.users.objects[userID].rank + 1;
  5476. result += userName + ' (' + userLevel + ')';
  5477. }
  5478. else result += 'unknown';
  5479. result += ', ';
  5480. camAge = uroGetCameraAge(ureq,0);
  5481. if(camAge != -1)
  5482. {
  5483. result += uroParseDaysAgo(camAge);
  5484. }
  5485. else result += 'unknown days ago';
  5486. result += '<br>Speed data: ';
  5487. result += uroGetCameraSpeedString(ureq.attributes.speed);
  5488. result += '<hr><ul>';
  5489. if(uroIsCamOnWatchList(uroFID) != -1)
  5490. {
  5491. result += '<li><a href="#" id="_updatewatchlist">Update watchlist entry</a>';
  5492. result += '<li><a href="#" id="_removefromwatchlist">Remove from watchlist</a>';
  5493. objHasUpdateWatchLink = true;
  5494. objHasRemoveWatchLink = true;
  5495. }
  5496. else
  5497. {
  5498. result += '<li><a href="#" id="_addtowatchlist">Add to watchlist</a>';
  5499. objHasAddWatchLink = true;
  5500. }
  5501. if(ureq.attributes.permissions !== 0)
  5502. {
  5503. result += '<li><a href="#" id="_deleteobject">Delete Camera</a>';
  5504. objHasDeleteLink = true;
  5505. }
  5506. result += '</ul>';
  5507. }
  5508. break;
  5509. }
  5510. }
  5511. }
  5512.  
  5513.  
  5514. if((newPopupType !== null) && (uroPopupDwellTimer === 0))
  5515. {
  5516. if((uroFID != uroShownFID) || (newPopupType != uroShownPopupType))
  5517. {
  5518. if(uroFID != uroShownFID) uroAddLog('FID mismatch, show popup: '+uroFID+'/'+uroShownFID);
  5519. else uroAddLog('Popup type mismatch: '+newPopupType+'/'+uroShownPopupType);
  5520. uroShownFID = uroFID;
  5521. uroShownPopupType = newPopupType;
  5522. uroPopupShown = false;
  5523. }
  5524.  
  5525. if(uroPopupShown === false)
  5526. {
  5527. uroAddLog('display popup at '+uroPopupX+','+uroPopupY);
  5528. uroPopupShown = true;
  5529. uroDiv.style.height = "auto";
  5530. uroDiv.style.width = "auto";
  5531. uroDiv.innerHTML = result;
  5532. if((uroFID != -1) && (objHasIgnoreLink === true))
  5533. {
  5534. uroAddEventListener('_addtoignore','click', uroAddToIgnoreList, true);
  5535. }
  5536. if(objHasDeleteLink === true)
  5537. {
  5538. uroAddEventListener('_deleteobject','click', uroDeleteObject, true);
  5539. }
  5540. if(objHasRemoveWatchLink === true)
  5541. {
  5542. uroAddEventListener('_removefromwatchlist','click', uroRemoveCamFromWatchList, true);
  5543. }
  5544. if(objHasAddWatchLink === true)
  5545. {
  5546. uroAddEventListener('_addtowatchlist','click', uroAddCamToWatchList, true);
  5547. }
  5548. if(objHasUpdateWatchLink === true)
  5549. {
  5550. uroAddEventListener('_updatewatchlist','click', uroUpdateCamWatchList, true);
  5551. }
  5552. if(objHasOpenInNewTabLink === true)
  5553. {
  5554. uroAddEventListener('_openInNewTab','mouseup', uroOpenNewTab, true);
  5555. }
  5556. if(objHasRecentreSessionLink === true)
  5557. {
  5558. if(isUR) uroAddEventListener('_recentreSession', 'click', uroRecentreSessionOnUR, true);
  5559. else if((isProblem)||(isTurnProb)) uroAddEventListener('_recentreSession', 'click', uroRecentreSessionOnMP, true);
  5560. else if(isPlaceUpdate) uroAddEventListener('_recentreSession', 'click', uroRecentreSessionOnPUR, true);
  5561. else if(isVenue) uroAddEventListener('_recentreSession', 'click', uroRecentreSessionOnVenueNavPoint, true);
  5562. }
  5563. if(newPopupType == 'turn_restriction')
  5564. {
  5565. uroAddEventListener('_editTBR','click', uroEditTBR, true);
  5566. }
  5567.  
  5568. // restrict the popup width to be no wider than half the window width to avoid it completely
  5569. // overlapping the marker it's associated with - by keeping it to half the window width we
  5570. // guarantee that it'll fit either to the left or the right of the marker no matter how far
  5571. // across the screen the marker is located...
  5572. rw = parseInt(uroDiv.clientWidth);
  5573. if(rw > (window.innerWidth / 2))
  5574. {
  5575. rw = (window.innerWidth / 2);
  5576. uroDiv.style.width = rw+'px';
  5577. }
  5578. // get the div height after any adjustment of the width above, to account for whatever content
  5579. // reflow may have occurred as a result of reducing the width...
  5580. rh = parseInt(uroDiv.clientHeight);
  5581.  
  5582. if((uroPopupX + rw) > window.innerWidth)
  5583. {
  5584. // where the popup would be off the right hand side of the screen, move it completely over to the
  5585. // other side of the mouse pointer
  5586. uroPopupX -= (rw + 20);
  5587. if(uroPopupX < 0) uroPopupX = 0;
  5588. }
  5589. if((uroPopupY + rh) > window.innerHeight)
  5590. {
  5591. // where the popup would be off the bottom of the screen, shift it up just far enough to be
  5592. // fully visible
  5593. uroPopupY -= (((uroPopupY + rh) - window.innerHeight) + 30);
  5594. if(uroPopupY < 0) uroPopupY = 0;
  5595. }
  5596. uroDiv.style.top = uroPopupY+'px';
  5597. uroDiv.style.left = uroPopupX+'px';
  5598. uroDiv.style.visibility = 'visible';
  5599. }
  5600. uroPopupTimer = -1;
  5601. }
  5602. else if((newPopupType === null) && (uroPopupDwellTimer !== 0) && (uroPopupShown === true))
  5603. {
  5604. uroHidePopup();
  5605. }
  5606. else
  5607. {
  5608. if((uroPopupTimer == -1) && (uroFID != uroShownFID))
  5609. {
  5610. uroPopupTimer = uroGetElmValue('_inputPopupEntryTimeout');
  5611. }
  5612. }
  5613. }
  5614.  
  5615. function uroRestyleWMETabs()
  5616. {
  5617. // The nav-tabs class is now also used for the General/Closures tabs on the segment edit panel, so we have
  5618. // to restrict the scope of this code to just those nav-tab classed elements within the user-tabs element.
  5619. var navTabs = document.getElementById('user-tabs').getElementsByClassName("nav-tabs")[0].children;
  5620. for(var loop = 0; loop<navTabs.length; loop++)
  5621. {
  5622. navTabs[loop].children[0].style.padding = "4px";
  5623. }
  5624. var panelDisplay = '';
  5625. if(uroGetCBChecked('_cbHideEditorInfo'))
  5626. {
  5627. panelDisplay = "none";
  5628. }
  5629. document.getElementById("user-details").style.display = panelDisplay;
  5630. setTimeout(uroRestyleWMETabs,1000);
  5631. }
  5632.  
  5633. function uroExclusiveCB()
  5634. {
  5635. var cbChecked = uroGetCBChecked(this.id);
  5636.  
  5637. if(cbChecked === true)
  5638. {
  5639. var pairedList = this.attributes.pairedWith.value.split(',');
  5640. for(var i=0; i<pairedList.length; i++)
  5641. {
  5642. uroSetCBChecked(pairedList[i], false);
  5643. }
  5644. }
  5645. }
  5646.  
  5647.  
  5648. function uroGetAMs(e)
  5649. {
  5650. var amList = '';
  5651. if(W.map.managedAreasLayer.getVisibility() === true)
  5652. {
  5653. var mouseX = e.pageX - document.getElementById('map').getBoundingClientRect().left;
  5654. var mouseY = e.pageY - document.getElementById('map').getBoundingClientRect().top - document.getElementById('toolbar').clientHeight;
  5655. var mousePixel = new OL.Pixel(mouseX, mouseY);
  5656. var mousePoint = W.map.getLonLatFromPixel(mousePixel).toPoint();
  5657.  
  5658. for(var amObj in W.model.managedAreas.objects)
  5659. {
  5660. if(W.model.managedAreas.objects[amObj].geometry.containsPoint(mousePoint))
  5661. {
  5662. if(amList !== '') amList += ', ';
  5663. amList += uroGetUserNameAndRank(W.model.managedAreas.objects[amObj].userID);
  5664. }
  5665. }
  5666. if(amList === '')
  5667. {
  5668. amList = 'none';
  5669. }
  5670. amList = "<b>Area Managers:</b> "+amList;
  5671. }
  5672. document.getElementById("uroAMList").innerHTML = amList;
  5673. }
  5674.  
  5675.  
  5676. function uroMouseDown()
  5677. {
  5678. uroMouseIsDown = true;
  5679. }
  5680.  
  5681. function uroMouseUp()
  5682. {
  5683. uroMouseIsDown = false;
  5684. }
  5685.  
  5686. function uroUREvent_onObjectsChanged()
  5687. {
  5688. }
  5689.  
  5690. function uroUREvent_onObjectsAdded()
  5691. {
  5692. if(uroGetCBChecked('_cbURResolverIDFilter') === true)
  5693. {
  5694. uroUpdateResolverList();
  5695. }
  5696. uroFilterURs();
  5697. }
  5698.  
  5699. function uroUREvent_onObjectsRemoved()
  5700. {
  5701. }
  5702.  
  5703. function uroGetSelectedURCommentCount()
  5704. {
  5705. if(W.model.updateRequestSessions.objects[uroSelectedURID] !== undefined)
  5706. {
  5707. var cachedCommentCount = W.model.updateRequestSessions.objects[uroSelectedURID].comments.length;
  5708. uroAddLog(uroSelectedURID+':'+cachedCommentCount+' '+uroExpectedCommentCount);
  5709.  
  5710. // if there aren't the same number of cached comments as there are comments in the UR dialog list, initiate
  5711. // a refresh of the comment data...
  5712. if(cachedCommentCount != uroExpectedCommentCount)
  5713. {
  5714. if(uroPendingCommentDataRefresh === true)
  5715. {
  5716. if(cachedCommentCount > 0)
  5717. {
  5718. uroCachedLastCommentID = W.model.updateRequestSessions.objects[uroSelectedURID].comments[cachedCommentCount-1].id;
  5719. }
  5720. else
  5721. {
  5722. uroCachedLastCommentID = null;
  5723. }
  5724. uroAddLog('updateRequestSessions refresh required for UR '+uroSelectedURID);
  5725. if(uroCachedLastCommentID !== null)
  5726. {
  5727. uroAddLog('last comment ID for this UR is '+uroCachedLastCommentID);
  5728. }
  5729. else
  5730. {
  5731. uroAddLog('first comment for this UR, no previous comment to ID');
  5732. }
  5733. var idList = [];
  5734. idList.push(uroSelectedURID);
  5735. // need to delete the existing cache object first, as .get() is only capable of creating new objects,
  5736. // it doesn't seem able to update an existing object with new data
  5737. W.model.updateRequestSessions.remove(W.model.updateRequestSessions.objects[uroSelectedURID]);
  5738. W.model.updateRequestSessions.get(idList);
  5739. // the call to .get() initiates a XMLHttpRequest for the data, so we now need to switch modes - the
  5740. // refresh process has started so we're no longer pending, but we are now waiting for the XMLHttpRequest
  5741. // to return something...
  5742. uroPendingCommentDataRefresh = false;
  5743. uroWaitingCommentDataRefresh = true;
  5744. }
  5745. else
  5746. {
  5747. if(cachedCommentCount > 0)
  5748. {
  5749. var currentLastCommentID = W.model.updateRequestSessions.objects[uroSelectedURID].comments[cachedCommentCount-1].id;
  5750. if(currentLastCommentID == uroCachedLastCommentID)
  5751. {
  5752. // most recent comment loaded for this UR is the same one that was present at the start of this
  5753. // refresh process, so kick back into pending mode so we can retry the .get()...
  5754. uroAddLog('latest comment ID still the same, reverting to pending mode...');
  5755. uroPendingCommentDataRefresh = true;
  5756. }
  5757. else
  5758. {
  5759. // something may have gone awry here - the most recent comment loaded for this UR doesn't have the
  5760. // same ID as the one present at the start of the refresh process, yet the comment counts still don't
  5761. // match up, which suggests either a comment got lost along the way or someone else has commented on
  5762. // the same UR at almost the same time. To get out of the loop this would create, assume that a
  5763. // mismatch in the IDs means the .get() has completed successfully no matter what the new comment
  5764. // count is, and take this new count to be the count we were expecting all along...
  5765. uroAddLog('latest comment ID different, but expected count not correct...');
  5766. uroExpectedCommentCount = cachedCommentCount;
  5767. }
  5768. }
  5769. else
  5770. {
  5771. uroAddLog('first comment on this UR not received yet, reverting to pending mode...');
  5772. uroPendingCommentDataRefresh = true;
  5773. }
  5774. }
  5775.  
  5776. }
  5777. else
  5778. {
  5779. // if the WME session is loaded with a UR already selected, such that WME has opened the UR dialog as part
  5780. // of the session startup process, adding new comments to the UR cause the cached data to be updated immediately.
  5781. // This prevents URO+ from switching into waiting mode in the above block of code, so we have to instead do
  5782. // it here by comparing the cached count against the expected count following the Send click event.
  5783. if(cachedCommentCount >= uroExpectedCommentCount)
  5784. {
  5785. uroPendingCommentDataRefresh = false;
  5786. uroWaitingCommentDataRefresh = true;
  5787. uroExpectedCommentCount = null;
  5788. }
  5789.  
  5790. // once the cached data has been updated, refilter the URs so that the new comment count is taken into account
  5791. // immediately for filtering and display purposes
  5792. if(uroWaitingCommentDataRefresh === true)
  5793. {
  5794. uroWaitingCommentDataRefresh = false;
  5795. uroFilterURs();
  5796. uroAddLog('refresh complete');
  5797. }
  5798. }
  5799. }
  5800. }
  5801.  
  5802. function uroAddedComment()
  5803. {
  5804. // when the user clicks the Send button to submit a new UR comment, this event handler fires before the new comment is
  5805. // posted to the server and thus also before the comment list gets updated in the UR dialog. So we take the current
  5806. // comment count and, if the new comment edit box isn't empty, increment it by 1 to get the expected count. Then we
  5807. // set the pending flag true to initiate a session refresh on the next 100ms tick
  5808. uroExpectedCommentCount = W.map.panelRegion.currentView.conversationView.conversation.comments.length;
  5809. if(document.getElementsByClassName('new-comment-text')[0].value !== '')
  5810. {
  5811. uroExpectedCommentCount++;
  5812. uroAddLog('new comment added to UR '+uroSelectedURID+', cache refresh required...');
  5813. uroPendingCommentDataRefresh = true;
  5814. }
  5815. else
  5816. {
  5817. uroPendingCommentDataRefresh = false;
  5818. }
  5819. }
  5820.  
  5821. function uroInhibitNextUpdateRequestButton(e)
  5822. {
  5823. e.stopPropagation();
  5824. document.getElementsByClassName('close-panel')[0].click();
  5825. }
  5826. function uroTenthSecondTick()
  5827. {
  5828. if(uroSetupListeners)
  5829. {
  5830. if(W.loginManager.isLoggedIn())
  5831. {
  5832. uroSetupListeners = false;
  5833.  
  5834. // filter markers when the marker objects are modified (this happens whenever WME needs to load fresh marker data
  5835. // due to having panned/zoomed the map beyond the extents of the previously loaded data)
  5836. W.model.mapUpdateRequests.events.register("objectschanged", null, uroFilterURs_onObjectsChanged);
  5837. W.model.mapUpdateRequests.events.register("objectsadded", null, uroFilterURs_onObjectsAdded);
  5838. W.model.mapUpdateRequests.events.register("objectsremoved", null, uroFilterURs_onObjectsRemoved);
  5839.  
  5840. W.model.updateRequestSessions.events.register("objectschanged", null, uroUREvent_onObjectsChanged);
  5841. W.model.updateRequestSessions.events.register("objectsadded", null, uroUREvent_onObjectsAdded);
  5842. W.model.updateRequestSessions.events.register("objectsremoved", null, uroUREvent_onObjectsRemoved);
  5843.  
  5844. W.model.cameras.events.register("objectschanged", null, uroFilterCameras);
  5845. W.model.cameras.events.register("objectsadded", null, uroFilterCameras);
  5846. W.model.cameras.events.register("objectsremoved", null, uroFilterCameras);
  5847. W.model.problems.events.register("objectschanged", null, uroFilterProblems);
  5848. W.model.problems.events.register("objectsadded", null, uroFilterProblems);
  5849. W.model.problems.events.register("objectsremoved", null, uroFilterProblems);
  5850. W.model.venues.events.register("objectschanged", null, uroFilterPlaces);
  5851. W.model.venues.events.register("objectsadded", null, uroFilterPlaces);
  5852. W.model.venues.events.register("objectsremoved", null, uroFilterPlaces);
  5853.  
  5854. var userTabs = document.getElementById(uroUserTabId);
  5855. var tabContent = null;
  5856.  
  5857. var navTabs = userTabs.getElementsByClassName('nav-tabs')[0];
  5858. tabContent = document.getElementById('user-info').getElementsByClassName('tab-content')[0];
  5859. var newtabUR = document.createElement('li');
  5860. newtabUR.innerHTML = '<a href="#sidepanel-uroverview" data-toggle="tab">URO+</a>';
  5861. navTabs.appendChild(newtabUR);
  5862. uroControls.id = "sidepanel-uroverview";
  5863. uroControls.className = "tab-pane";
  5864. tabContent.appendChild(uroControls);
  5865.  
  5866. uroAddEventListener('_btnUndoLastHide',"click", uroRemoveLastAddedIgnore, true);
  5867. uroAddEventListener('_btnClearSessionHides',"click", uroRemoveAllIgnores, true);
  5868. uroEnableIgnoreListControls();
  5869.  
  5870. uroAddEventListener('_btnClearCamWatchList',"click", uroClearCamWatchList, true);
  5871. uroAddEventListener('_btnSettingsToText',"click", uroSettingsToText, true);
  5872. uroAddEventListener('_btnTextToSettings',"click", uroTextToSettings, true);
  5873. uroAddEventListener('_btnResetSettings',"click", uroDefaultSettings, true);
  5874. uroAddEventListener('_btnClearSettingsText',"click", uroClearSettingsText, true);
  5875. uroAddEventListener('_cbMasterEnable',"click", uroFilterItems_MasterEnableClick, true);
  5876.  
  5877. uroSetOnClick("_linkSelectUserRequests",uroShowURTab);
  5878. uroSetOnClick("_linkSelectMapProblems",uroShowMPTab);
  5879. uroSetOnClick("_linkSelectPlaces",uroShowPlacesTab);
  5880. uroSetOnClick("_linkSelectCameras",uroShowCameraTab);
  5881. uroSetOnClick("_linkSelectMisc",uroShowMiscTab);
  5882. uroSetOnClick("_linkSelectOWL",uroShowOWLTab);
  5883.  
  5884. for(var idx=0;idx<W.Config.venues.categories.length;idx++)
  5885. {
  5886. uroSetOnClick('_uroPlacesGroupState-'+idx,uroPlacesGroupCollapseExpand);
  5887. }
  5888.  
  5889. // add exclusiveCB click handlers to all checkboxes with a pairedWith attribute
  5890. var cbList = document.getElementsByTagName('input');
  5891. for (var optIdx=0;optIdx<cbList.length;optIdx++)
  5892. {
  5893. if((cbList[optIdx].id.indexOf('_cb') === 0) && (cbList[optIdx].attributes.pairedWith !== undefined))
  5894. {
  5895. uroSetOnClick(cbList[optIdx].id,uroExclusiveCB);
  5896. }
  5897. }
  5898.  
  5899. var dbgMode = "none";
  5900. if(uroShowDebugOutput)
  5901. {
  5902. dbgMode = "inline";
  5903. }
  5904. document.getElementById('_uroDebugMode').style.display = dbgMode;
  5905. uroAddEventListener('_uroVersion',"click", uroToggleDebug, true);
  5906.  
  5907. uroAddLog('finalise onload');
  5908. uroLoadSettings();
  5909. uroNewLookCheckDetailsRequest();
  5910. if(uroGetCBChecked('_cbEnableDTE'))
  5911. {
  5912. if(dteControlsIdx != -1)
  5913. {
  5914. dteSetNewTabLength();
  5915. }
  5916. else
  5917. {
  5918. uroAddLog('ERROR - archive panel not found!');
  5919. uroSetStyleDisplay(uroUserTabId,'');
  5920. }
  5921. }
  5922.  
  5923. // filter markers as and when the map is moved
  5924. W.map.events.register("moveend", null, uroFilterItems);
  5925. W.map.events.register("mousemove", null, uroGetAMs);
  5926. W.map.events.register("mousemove", null, uroNewLookHighlightedItemsCheck);
  5927. W.map.events.registerPriority("mousedown", null, uroMouseDown);
  5928.  
  5929. // trap mousedown on Streetview marker drag
  5930. document.getElementsByClassName('street-view-control')[0].onmousedown = uroMouseDown;
  5931.  
  5932. W.map.events.register("mouseup", null, uroMouseUp);
  5933.  
  5934. uroSetStyles(uroCtrlURs);
  5935. uroSetStyles(uroCtrlMPs);
  5936. uroSetStyles(uroCtrlPlaces);
  5937. uroSetStyles(uroCtrlCameras);
  5938. uroSetStyles(uroCtrlMisc);
  5939. uroSetStyles(uroOWL);
  5940.  
  5941. uroShowURTab();
  5942. uroRestyleWMETabs();
  5943. uroUserID = W.loginManager.getLoggedInUser().id;
  5944. uroFilterItems();
  5945. }
  5946. }
  5947. else
  5948. {
  5949. var mousePos = document.getElementsByClassName('mouse-position')[0].innerHTML;
  5950.  
  5951. if(document.getElementsByClassName('panel')[0] === undefined)
  5952. {
  5953. uroHidePopupOnPanelOpen = true;
  5954. }
  5955.  
  5956. if(uroPopupShown === true)
  5957. {
  5958. var hidePopup = false;
  5959. if((mousePos == '00.00000, 00.00000') && (uroMouseInPopup === false))
  5960. {
  5961. hidePopup = true;
  5962. }
  5963. if(document.getElementsByClassName('panel')[0] !== undefined)
  5964. {
  5965. if(uroHidePopupOnPanelOpen === true)
  5966. {
  5967. hidePopup = true;
  5968. uroHidePopupOnPanelOpen = false;
  5969. }
  5970. }
  5971.  
  5972. if(hidePopup === true)
  5973. {
  5974. uroHidePopup();
  5975. }
  5976. }
  5977.  
  5978. if((uroAreaNameHoverObj !== null) && (uroAreaNameHoverTime != -1) && (uroAreaNameOverlayShown === false))
  5979. {
  5980. if(++uroAreaNameHoverTime > 5)
  5981. {
  5982. uroAreaNameOverlaySetup();
  5983. }
  5984. }
  5985. uroReplaceAreaNames(false);
  5986.  
  5987. if(uroPopupTimer > 0)
  5988. {
  5989. if(uroMouseInPopup === false)
  5990. {
  5991. uroPopupTimer--;
  5992. }
  5993. }
  5994. if(uroPopupTimer === 0)
  5995. {
  5996. uroHidePopup();
  5997. }
  5998.  
  5999. if(uroPopupDwellTimer > 0)
  6000. {
  6001. uroPopupDwellTimer--;
  6002. if(uroPopupDwellTimer === 0)
  6003. {
  6004. uroNewLookHighlightedItemsCheck('dwellTimeout');
  6005. }
  6006. }
  6007.  
  6008. if(document.getElementsByClassName("archive-panel")[0] === undefined)
  6009. {
  6010. if(dteClearHighlightsOnPanelClose)
  6011. {
  6012. dteClearListHighlight();
  6013. dteClearHighlightsOnPanelClose = false;
  6014. }
  6015. }
  6016. else
  6017. {
  6018. if(dteArmClearHighlightsOnPanelClose)
  6019. {
  6020. dteArmClearHighlightsOnPanelClose = false;
  6021. dteClearHighlightsOnPanelClose = true;
  6022. }
  6023. }
  6024.  
  6025. // replace the "next xxx" button on UR, MP and PUR editing UIs
  6026. if(W.map.panelRegion.hasView() === true)
  6027. {
  6028. var doneString = I18n.lookup('problems.panel.done');
  6029. var updateButton = false;
  6030.  
  6031. var nurButton = document.getElementsByClassName('btn btn-block next')[0];
  6032. if(nurButton !== undefined)
  6033. {
  6034. var nextURString = I18n.lookup('update_requests.panel.next');
  6035. var nextMPString = I18n.lookup('problems.panel.next');
  6036. updateButton = ((nurButton.innerHTML.indexOf(nextURString) !== -1) && (uroGetCBChecked('_cbInhibitNURButton') === true));
  6037. if(updateButton === false)
  6038. {
  6039. updateButton = ((nurButton.innerHTML.indexOf(nextMPString) !== -1) && (uroGetCBChecked('_cbInhibitNMPButton') === true));
  6040. }
  6041. }
  6042. else
  6043. {
  6044. nurButton = document.getElementsByClassName('btn btn-block next-venue')[0];
  6045. if(nurButton !== undefined)
  6046. {
  6047. var nextPURString = I18n.lookup('venues.update_requests.panel.next_venue');
  6048. updateButton = ((nurButton.innerHTML.indexOf(nextPURString) !== -1) && (uroGetCBChecked('_cbInhibitNPURButton') === true));
  6049. }
  6050. }
  6051.  
  6052. if(updateButton === true)
  6053. {
  6054. // first change its label...
  6055. nurButton.innerHTML = doneString;
  6056. // ...then add a new click handler that'll inhibit the native ones
  6057. nurButton.addEventListener("click", uroInhibitNextUpdateRequestButton, false);
  6058. uroAddLog('inhibit Next UR/MP/PUR button');
  6059. }
  6060. }
  6061. // test for the opening or closing of the UR editing dialog so we can detect when a new comment is added
  6062. var URDialogIsOpen = (document.getElementsByClassName('new-comment-form').length == 1);
  6063. if(URDialogIsOpen)
  6064. {
  6065. var thisSelectedURID = W.map.panelRegion.currentView.conversationView.conversation.getID();
  6066. if(thisSelectedURID != uroSelectedURID)
  6067. {
  6068. // if the user selects a new UR whilst the editing dialog is still open, treat it in the
  6069. // same way as if the user had selected that UR with the dialog closed
  6070. uroURDialogIsOpen = false;
  6071. }
  6072. if(uroURDialogIsOpen === false)
  6073. {
  6074. // user is editing a new UR
  6075. uroSelectedURID = thisSelectedURID;
  6076. // add our own click event handler to the Send button, so we can do stuff whenever a new comment is added
  6077. document.getElementsByClassName('new-comment-form')[0].getElementsByClassName('btn')[0].addEventListener("click", uroAddedComment, false);
  6078. uroAddLog('user is editing UR '+uroSelectedURID);
  6079. uroExpectedCommentCount = W.model.updateRequestSessions.objects[uroSelectedURID].comments.length;
  6080. }
  6081. }
  6082. else if(uroURDialogIsOpen === true)
  6083. {
  6084. // dialog was open and has now been closed
  6085. uroSelectedURID = null;
  6086. }
  6087. uroURDialogIsOpen = URDialogIsOpen;
  6088.  
  6089. if(((uroPendingCommentDataRefresh === true) || (uroWaitingCommentDataRefresh === true)) && (uroSelectedURID !== null))
  6090. {
  6091. uroAddLog('check completion of comment data refresh for UR '+uroSelectedURID+' ('+uroPendingCommentDataRefresh+','+uroWaitingCommentDataRefresh+')');
  6092. uroGetSelectedURCommentCount();
  6093. }
  6094.  
  6095. var selectedTotal = W.selectionManager.selectedItems.length;
  6096. if((selectedTotal > 0) && (document.getElementById('_uroDivOWLBtns') === null))
  6097. {
  6098. var selectedClass = W.selectionManager.selectedItems[0].model.CLASS_NAME;
  6099. var displayAddToOWLBtn = false;
  6100. var displayUpdateOWLBtn = false;
  6101. var displayRemoveFromOWLBtn = false;
  6102. var selectedSegments = false;
  6103. var selectedLandmarks = false;
  6104. var fid;
  6105. var loop;
  6106.  
  6107. // WME only seems to allow multi-object selections for segments, so testing the class of the first object in the
  6108. // selection list tells us the class of any other objects in the list too...
  6109. if(selectedClass == "Waze.Feature.Vector.Segment")
  6110. {
  6111. selectedSegments = true;
  6112. for(loop=0; loop<selectedTotal; loop++)
  6113. {
  6114. fid = W.selectionManager.selectedItems[loop].model.attributes.id;
  6115. var segIdx = uroIsSegOnWatchList(fid);
  6116. if(segIdx == -1)
  6117. {
  6118. displayAddToOWLBtn = true;
  6119. }
  6120. else
  6121. {
  6122. if(uroSegDataChanged(segIdx))
  6123. {
  6124. displayUpdateOWLBtn = true;
  6125. }
  6126. displayRemoveFromOWLBtn = true;
  6127. }
  6128. }
  6129. }
  6130.  
  6131. else if(selectedClass == "Waze.Feature.Vector.Landmark")
  6132. {
  6133. selectedLandmarks = true;
  6134. for(loop=0; loop<selectedTotal; loop++)
  6135. {
  6136. fid = W.selectionManager.selectedItems[loop].model.attributes.id;
  6137. var placeIdx = uroIsPlaceOnWatchList(fid);
  6138. if(placeIdx == -1)
  6139. {
  6140. displayAddToOWLBtn = true;
  6141. }
  6142. else
  6143. {
  6144. if(uroPlaceDataChanged(placeIdx))
  6145. {
  6146. displayUpdateOWLBtn = true;
  6147. }
  6148. displayRemoveFromOWLBtn = true;
  6149. }
  6150. }
  6151. }
  6152.  
  6153. var btnHTML = '<div id="_uroDivOWLBtns">';
  6154. if((displayAddToOWLBtn === true) && (displayUpdateOWLBtn === false))
  6155. {
  6156. btnHTML += '<button class="btn btn-default" id="_btnAddUpdateOWL">Add to OWL</button>';
  6157. }
  6158. else if((displayUpdateOWLBtn === true) && (displayAddToOWLBtn === false))
  6159. {
  6160. btnHTML += '<button class="btn btn-default" id="_btnAddUpdateOWL">Update OWL</button>';
  6161. }
  6162. else if((displayAddToOWLBtn === true) && (displayUpdateOWLBtn === true))
  6163. {
  6164. btnHTML += '<button class="btn btn-default" id="_btnAddUpdateOWL">Add to & Update OWL</button>';
  6165. }
  6166.  
  6167. if(displayRemoveFromOWLBtn === true)
  6168. {
  6169. btnHTML += '<button class="btn btn-default" id="_btnRemoveOWL">Remove from OWL</button>';
  6170. }
  6171. btnHTML += '</div>';
  6172. /*
  6173. // once we get around to enabling these again, remember that altering the inner HTML of the
  6174. // segment-edit-general panel when the selected segment is part of a roundabout then disables
  6175. // the onclick handler for the select roundabout button...
  6176. //
  6177. // also remember that the current WME beta has yet another different side panel arrangement
  6178. if(selectedSegments === true)
  6179. {
  6180. document.getElementById("segment-edit-general").innerHTML += btnHTML;
  6181. }
  6182. else if(selectedLandmarks === true)
  6183. {
  6184. document.getElementById("landmark-edit-general").innerHTML += btnHTML;
  6185. }
  6186.  
  6187. if((displayAddToOWLBtn === true)||(displayUpdateOWLBtn === true))
  6188. {
  6189. if(selectedSegments === true)
  6190. {
  6191. uroAddEventListener('_btnAddUpdateOWL','click', uroAddUpdateSegWatchList, true);
  6192. }
  6193. else
  6194. {
  6195. uroAddEventListener('_btnAddUpdateOWL','click', uroAddUpdatePlaceWatchList, true);
  6196. }
  6197. }
  6198.  
  6199. if(displayRemoveFromOWLBtn === true)
  6200. {
  6201. if(selectedSegments === true)
  6202. {
  6203. uroAddEventListener('_btnRemoveOWL','click', uroRemoveSegFromWatchList, true);
  6204. }
  6205. else
  6206. {
  6207. uroAddEventListener('_btnRemoveOWL','click', uroRemovePlaceFromWatchList, true);
  6208. }
  6209. }
  6210. */
  6211. }
  6212. // fix the livemap link in WME beta...
  6213. if(uroBetaEditor === true)
  6214. {
  6215. var lmLink = document.getElementsByClassName('waze-header-menu')[0].children[0].children[0].getAttribute('href');
  6216. if(lmLink.indexOf('https:') === -1)
  6217. {
  6218. uroAddLog('fixing livemap link...');
  6219. lmLink = 'https://www.waze.com' + lmLink;
  6220. document.getElementsByClassName('waze-header-menu')[0].children[0].children[0].setAttribute('href',lmLink);
  6221. }
  6222. }
  6223. }
  6224. }
  6225.  
  6226. function uroToggleURCtrls()
  6227. {
  6228. uroCtrlsHidden = !uroCtrlsHidden;
  6229. if (!uroCtrlsHidden)
  6230. {
  6231. document.getElementById('_hideUCCtrl').innerHTML = "hide";
  6232. if(uroCurrentTab == 1) uroShowURTab();
  6233. else if(uroCurrentTab == 2) uroShowMPTab();
  6234. else if(uroCurrentTab == 3) uroShowPlacesTab();
  6235. else if(uroCurrentTab == 4) uroShowCameraTab();
  6236. else if(uroCurrentTab == 5) uroShowOWLTab();
  6237. else if(uroCurrentTab == 6) uroShowMiscTab();
  6238. }
  6239. else
  6240. {
  6241. document.getElementById('_hideUCCtrl').innerHTML = "show";
  6242. uroSetStyleDisplay('uroCtrlURs','none');
  6243. uroSetStyleDisplay('uroCtrlMPs','none');
  6244. uroSetStyleDisplay('uroCtrlCameras','none');
  6245. uroSetStyleDisplay('uroCtrlMisc','none');
  6246. uroSetStyleDisplay('uroOWL','none');
  6247. }
  6248.  
  6249. return false;
  6250. }
  6251.  
  6252. function uroActiveTab(_id)
  6253. {
  6254. var e = document.getElementById(_id);
  6255. e.style.backgroundColor = "aliceblue";
  6256. e.style.borderTop = "1px solid";
  6257. e.style.borderLeft = "1px solid";
  6258. e.style.borderRight = "1px solid";
  6259. e.style.borderBottom = "0px solid";
  6260. }
  6261.  
  6262. function uroInactiveTab(_id)
  6263. {
  6264. var e = document.getElementById(_id);
  6265. e.style.backgroundColor = "white";
  6266. e.style.borderTop = "0px solid";
  6267. e.style.borderLeft = "0px solid";
  6268. e.style.borderRight = "0px solid";
  6269. e.style.borderBottom = "1px solid";
  6270. }
  6271.  
  6272.  
  6273. function uroInactiveAllTabs()
  6274. {
  6275. uroInactiveTab("_tabSelectCameras");
  6276. uroInactiveTab("_tabSelectMapProblems");
  6277. uroInactiveTab("_tabSelectMisc");
  6278. uroInactiveTab("_tabSelectUserRequests");
  6279. uroInactiveTab("_tabSelectCWL");
  6280. uroInactiveTab("_tabSelectPlaces");
  6281.  
  6282. if(!uroCtrlsHidden)
  6283. {
  6284. uroSetStyleDisplay('uroCtrlURs','none');
  6285. uroSetStyleDisplay('uroCtrlMPs','none');
  6286. uroSetStyleDisplay('uroCtrlCameras','none');
  6287. uroSetStyleDisplay('uroCtrlMisc','none');
  6288. uroSetStyleDisplay('uroOWL','none');
  6289. uroSetStyleDisplay('uroCtrlPlaces','none');
  6290. }
  6291. }
  6292.  
  6293.  
  6294. function uroShowURTab()
  6295. {
  6296. uroInactiveAllTabs();
  6297. uroActiveTab("_tabSelectUserRequests");
  6298. uroCurrentTab = 1;
  6299. if(!uroCtrlsHidden) uroSetStyleDisplay('uroCtrlURs','block');
  6300. return false;
  6301. }
  6302.  
  6303.  
  6304. function uroShowMPTab()
  6305. {
  6306. uroInactiveAllTabs();
  6307. uroActiveTab("_tabSelectMapProblems");
  6308. uroCurrentTab = 2;
  6309. if(!uroCtrlsHidden) uroSetStyleDisplay('uroCtrlMPs','block');
  6310. return false;
  6311. }
  6312.  
  6313. function uroShowPlacesTab()
  6314. {
  6315. uroInactiveAllTabs();
  6316. uroActiveTab("_tabSelectPlaces");
  6317. uroCurrentTab = 3;
  6318. if(!uroCtrlsHidden) uroSetStyleDisplay('uroCtrlPlaces','block');
  6319. for(var idx=0;idx<uroPlacesGroupsCollapsed.length;idx++)
  6320. {
  6321. uroPlacesGroupCEHandler(idx);
  6322. }
  6323. return false;
  6324. }
  6325.  
  6326. function uroShowCameraTab()
  6327. {
  6328. uroInactiveAllTabs();
  6329. uroActiveTab("_tabSelectCameras");
  6330. uroCurrentTab = 4;
  6331. if(!uroCtrlsHidden) uroSetStyleDisplay('uroCtrlCameras','block');
  6332. return false;
  6333. }
  6334.  
  6335. function uroShowOWLTab()
  6336. {
  6337. uroInactiveAllTabs();
  6338. uroActiveTab("_tabSelectCWL");
  6339. uroCurrentTab = 5;
  6340. if(!uroCtrlsHidden) uroSetStyleDisplay('uroOWL','block');
  6341. uroOWLUpdateHTML();
  6342. return false;
  6343. }
  6344.  
  6345. function uroShowMiscTab()
  6346. {
  6347. uroInactiveAllTabs();
  6348. uroActiveTab("_tabSelectMisc");
  6349. uroCurrentTab = 6;
  6350. if(!uroCtrlsHidden) uroSetStyleDisplay('uroCtrlMisc','block');
  6351. return false;
  6352. }
  6353.  
  6354.  
  6355. function uroNewLookCheckDetailsRequest()
  6356. {
  6357. var thisurl = document.location.href;
  6358. var doRetry = true;
  6359. var urID;
  6360. var endmarkerpos = thisurl.indexOf('&endshow');
  6361. var showmarkerpos = thisurl.indexOf('&showturn=');
  6362. if((endmarkerpos != -1) && (showmarkerpos != -1))
  6363. {
  6364. showmarkerpos += 10;
  6365. uroAddLog('showturn tab opened');
  6366. urID = thisurl.substr(showmarkerpos,endmarkerpos-showmarkerpos);
  6367. uroAddLog(' turn problem ID = '+urID);
  6368.  
  6369. try
  6370. {
  6371. W.map.problemLayer.markers[urID].icon.imageDiv.click();
  6372. doRetry = false;
  6373. }
  6374. catch(err)
  6375. {
  6376. uroAddLog('problems not fully loaded, retrying...');
  6377. }
  6378.  
  6379. if(doRetry) setTimeout(uroNewLookCheckDetailsRequest,500);
  6380. }
  6381. else
  6382. {
  6383. showmarkerpos = thisurl.indexOf('&showpur=');
  6384. if((endmarkerpos != -1) && (showmarkerpos != -1))
  6385. {
  6386. showmarkerpos += 9;
  6387. uroAddLog('showPUR tab opened');
  6388. urID = thisurl.substr(showmarkerpos,endmarkerpos-showmarkerpos);
  6389. uroAddLog(' PUR ID = '+urID);
  6390.  
  6391. try
  6392. {
  6393. W.map.placeUpdatesLayer.markers[urID].icon.imageDiv.click();
  6394. doRetry = false;
  6395. }
  6396. catch(err)
  6397. {
  6398. uroAddLog('PURs not fully loaded, retrying...');
  6399. }
  6400.  
  6401. if(doRetry) setTimeout(uroNewLookCheckDetailsRequest,500);
  6402. }
  6403. }
  6404.  
  6405. }
  6406.  
  6407.  
  6408. function uroUpdateMPSolverList()
  6409. {
  6410. if(Object.keys(W.model.problems.objects).length === 0)
  6411. {
  6412. return;
  6413. }
  6414.  
  6415. var resolverList = [];
  6416. var selector = document.getElementById('_selectMPUserID');
  6417. var selectedUser = null;
  6418. if(selector.selectedOptions[0] !== undefined)
  6419. {
  6420. selectedUser = parseInt(selector.selectedOptions[0].value);
  6421. }
  6422. while(selector.options.length > 0)
  6423. {
  6424. selector.options.remove(0);
  6425. }
  6426. var selectedIdx = 0;
  6427. var idx = 0;
  6428.  
  6429. for (var mpobj in W.model.problems.objects)
  6430. {
  6431. if(W.model.problem.objects.hasOwnProperty(mpobj))
  6432. {
  6433. var prob = W.model.problems.objects[mpobj];
  6434. if(prob.attributes.resolvedBy !== null)
  6435. {
  6436. var userID = prob.attributes.resolvedBy;
  6437. var userName = W.model.users.objects[userID].userName;
  6438. if(resolverList.indexOf(userName) == -1)
  6439. {
  6440. resolverList.push(userName);
  6441. selector.options.add(new Option(userName, userID));
  6442. if(userID == selectedUser)
  6443. {
  6444. selectedIdx = idx;
  6445. }
  6446. idx++;
  6447. }
  6448. }
  6449. }
  6450. }
  6451.  
  6452. if(selectedIdx !== null)
  6453. {
  6454. selector.selectedIndex = selectedIdx;
  6455. }
  6456. }
  6457.  
  6458.  
  6459. function uroUpdateResolverList()
  6460. {
  6461. if(Object.keys(W.model.mapUpdateRequests.objects).length === 0)
  6462. {
  6463. return;
  6464. }
  6465.  
  6466. var resolverList = [];
  6467. var selector = document.getElementById('_selectURResolverID');
  6468. var selectedUser = null;
  6469. if(selector.selectedOptions[0] !== undefined)
  6470. {
  6471. selectedUser = parseInt(selector.selectedOptions[0].value);
  6472. }
  6473. while(selector.options.length > 0)
  6474. {
  6475. selector.options.remove(0);
  6476. }
  6477. var selectedIdx = 0;
  6478. var idx = 0;
  6479.  
  6480. for (var urobj in W.model.mapUpdateRequests.objects)
  6481. {
  6482. if(W.model.mapUpdateRequests.objects.hasOwnProperty(urobj))
  6483. {
  6484. var ureq = W.model.mapUpdateRequests.objects[urobj];
  6485. if(ureq.attributes.resolvedBy !== null)
  6486. {
  6487. var userID = ureq.attributes.resolvedBy;
  6488. var userName = W.model.users.objects[userID].userName;
  6489. if(resolverList.indexOf(userName) == -1)
  6490. {
  6491. resolverList.push(userName);
  6492. selector.options.add(new Option(userName, userID));
  6493. if(userID == selectedUser)
  6494. {
  6495. selectedIdx = idx;
  6496. }
  6497. idx++;
  6498. }
  6499. }
  6500. }
  6501. }
  6502. if(selectedIdx !== null)
  6503. {
  6504. selector.selectedIndex = selectedIdx;
  6505. }
  6506. }
  6507.  
  6508. function uroUpdateUserList()
  6509. {
  6510. if(Object.keys(W.model.updateRequestSessions.objects).length === 0) return;
  6511.  
  6512. var selector = document.getElementById('_selectURUserID');
  6513.  
  6514. var selectedUser = null;
  6515. if(selector.selectedOptions[0] !== undefined)
  6516. {
  6517. selectedUser = parseInt(selector.selectedOptions[0].value);
  6518. }
  6519.  
  6520. while(selector.options.length > 0)
  6521. {
  6522. selector.options.remove(0);
  6523. }
  6524.  
  6525. var selectedIdx = null;
  6526.  
  6527. var listedIDs = [];
  6528. for(var ursIdx in W.model.updateRequestSessions.objects)
  6529. {
  6530. if(W.model.updateRequestSessions.objects.hasOwnProperty(ursIdx))
  6531. {
  6532. var ursObj = W.model.updateRequestSessions.objects[ursIdx];
  6533. if(ursObj.comments.length > 0)
  6534. {
  6535. for(var cidx=0; cidx < ursObj.comments.length; cidx++)
  6536. {
  6537. var userID = ursObj.comments[cidx].userID;
  6538. if((listedIDs.indexOf(userID) == -1) && (userID != -1))
  6539. {
  6540. listedIDs.push(userID);
  6541. }
  6542. }
  6543. }
  6544. }
  6545. }
  6546.  
  6547. if(listedIDs.length > 0)
  6548. {
  6549. var users = W.model.users.getByIds(listedIDs);
  6550. for(var idx=0; idx<listedIDs.length; idx++)
  6551. {
  6552. selector.options.add(new Option(users[idx].userName, listedIDs[idx]));
  6553. if(listedIDs[idx] == selectedUser)
  6554. {
  6555. selectedIdx = idx;
  6556. }
  6557. }
  6558. }
  6559.  
  6560.  
  6561. if(selectedIdx !== null)
  6562. {
  6563. selector.selectedIndex = selectedIdx;
  6564. }
  6565. }
  6566.  
  6567.  
  6568. function uroSetStyles(obj)
  6569. {
  6570. obj.style.fontSize = '12px';
  6571. obj.style.lineHeight = '100%';
  6572. obj.style.overflow = 'auto';
  6573. obj.style.height = (window.innerHeight * 0.55) + 'px';
  6574. }
  6575.  
  6576. function uroPlacesGroupCEHandler(groupidx)
  6577. {
  6578. if(uroPlacesGroupsCollapsed[groupidx] === false)
  6579. {
  6580. document.getElementById('_uroPlacesGroup-'+groupidx).style.display = "block";
  6581. document.getElementById('_uroPlacesGroupState-'+groupidx).src = uroIcons[0][0];
  6582. }
  6583. else
  6584. {
  6585. document.getElementById('_uroPlacesGroup-'+groupidx).style.display = "none";
  6586. document.getElementById('_uroPlacesGroupState-'+groupidx).src = uroIcons[0][1];
  6587. }
  6588. }
  6589. function uroPlacesGroupCollapseExpand()
  6590. {
  6591. var groupidx = this.id.substr(21);
  6592. if(uroPlacesGroupsCollapsed[groupidx] === true) uroPlacesGroupsCollapsed[groupidx] = false;
  6593. else uroPlacesGroupsCollapsed[groupidx] = true;
  6594. uroPlacesGroupCEHandler(groupidx);
  6595. return false;
  6596. }
  6597. function uroPopulatePlacesTab()
  6598. {
  6599. var tHTML = '';
  6600. tHTML += '<b>Filter PURs by category/status:</b><br>';
  6601. tHTML += '<input type="checkbox" id="_cbFilterUneditablePlaceUpdates">Ones I can\'t edit</input><br>';
  6602. tHTML += '<input type="checkbox" id="_cbFilterLockRankedPlaceUpdates">Ones with non-zero lockRanks</input><br>';
  6603. tHTML += '<input type="checkbox" id="_cbFilterNewPlacePUR">Ones for new places</input><br>';
  6604. tHTML += '<input type="checkbox" id="_cbFilterUpdatedDetailsPUR">Ones for updated place details</input><br>';
  6605. tHTML += '<input type="checkbox" id="_cbFilterNewPhotoPUR">Ones for new photos</input><br>';
  6606. tHTML += '<input type="checkbox" id="_cbFilterFlaggedPUR">Ones flagged for attention</input><br>';
  6607. tHTML += '<br><input type="checkbox" id="_cbLeavePURGeos">Don\'t hide place polygons/points</input><br>';
  6608. tHTML += '<br><input type="checkbox" id="_cbInvertPURFilters">Invert PUR filters</input><br>';
  6609.  
  6610. tHTML += '<br><b>Filter PURs by severity:</b><br>';
  6611. tHTML += '<input type="checkbox" id="_cbPURFilterLowSeverity">Low</input>&nbsp;&nbsp;';
  6612. tHTML += '<input type="checkbox" id="_cbPURFilterMediumSeverity">Medium</input>&nbsp;&nbsp;';
  6613. tHTML += '<input type="checkbox" id="_cbPURFilterHighSeverity">High</input>';
  6614.  
  6615. tHTML += '<br><b>Filter PURs by age of submission:</b><br>';
  6616. tHTML += '<input type="checkbox" id="_cbEnablePURMinAgeFilter">Hide PURs less than </input>';
  6617. tHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputPURFilterMinDays"> days old<br>';
  6618. tHTML += '<input type="checkbox" id="_cbEnablePURMaxAgeFilter">Hide PURs more than </input>';
  6619. tHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputPURFilterMaxDays"> days old<br>';
  6620.  
  6621. tHTML += '<hr>';
  6622.  
  6623. tHTML += '<br><b>Filter Places by state:</b><br>';
  6624. tHTML += 'Hide if last edited<br>';
  6625. tHTML += '<input type="checkbox" id="_cbPlaceFilterEditedLessThan"> less than </input>';
  6626. tHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterPlaceEditMinDays"> days ago<br>';
  6627. tHTML += '<input type="checkbox" id="_cbPlaceFilterEditedMoreThan"> more than </input>';
  6628. tHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterPlaceEditMaxDays"> days ago<br>';
  6629.  
  6630. tHTML += '<br>Hide if locked at level:<br>';
  6631. tHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHidePlacesL0">1</input>';
  6632. tHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHidePlacesL1">2</input>';
  6633. tHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHidePlacesL2">3</input>';
  6634. tHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHidePlacesL3">4</input>';
  6635. tHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHidePlacesL4">5</input>';
  6636. tHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHidePlacesL5">6</input>';
  6637.  
  6638. tHTML += '<br><br><input type="checkbox" id="_cbHidePhotoPlaces" pairedWith="_cbHideNoPhotoPlaces">Hide or </input>';
  6639. tHTML += '<input type="checkbox" id="_cbHideNoPhotoPlaces" pairedWith="_cbHidePhotoPlaces">show ones with photos</input><br>';
  6640.  
  6641. tHTML += '<br><br><b>Filter Places by category:</b><br>';
  6642.  
  6643. var nCategories = W.Config.venues.categories.length;
  6644. var i;
  6645. if(uroPlacesGroupsCollapsed.length != nCategories)
  6646. {
  6647. for(i=0; i<nCategories; i++)
  6648. {
  6649. uroPlacesGroupsCollapsed.push(false);
  6650. }
  6651. }
  6652.  
  6653. for(i=0; i<nCategories; i++)
  6654. {
  6655. var parentCategory = W.Config.venues.categories[i];
  6656. var localisedName = I18n.lookup("venues.categories")[parentCategory];
  6657.  
  6658. if(uroPlacesGroupsCollapsed[i] === true)
  6659. {
  6660. tHTML += '<img src="'+uroIcons[0][1]+'" id="_uroPlacesGroupState-'+i+'">';
  6661. }
  6662. else
  6663. {
  6664. tHTML += '<img src="'+uroIcons[0][0]+'" id="_uroPlacesGroupState-'+i+'">';
  6665. }
  6666.  
  6667. tHTML += '&nbsp;&nbsp;<input type="checkbox" id="_cbPlacesFilter-'+parentCategory+'"><b>'+localisedName+'</b></input><br>';
  6668. tHTML += '<div id="_uroPlacesGroup-'+i+'" style="padding:3px;border-width:2px;border-style:solid;border-color:#FFFFFF">';
  6669.  
  6670. for(var ii=0; ii<W.Config.venues.subcategories[parentCategory].length; ii++)
  6671. {
  6672. var subCategory = W.Config.venues.subcategories[parentCategory][ii];
  6673. localisedName = I18n.lookup("venues.categories")[subCategory];
  6674. tHTML += '&nbsp;&nbsp;<input type="checkbox" id="_cbPlacesFilter-'+subCategory+'">'+localisedName+'</input><br>';
  6675. }
  6676. tHTML += '</div>';
  6677. }
  6678. tHTML += '<input type="checkbox" id="_cbFilterPrivatePlaces"><b>Residential Places</b></input><br>';
  6679. tHTML += '<br><input type="checkbox" id="_cbInvertPlacesFilter">Invert Place filters?</input>';
  6680.  
  6681. uroCtrlPlaces.innerHTML = tHTML;
  6682. }
  6683.  
  6684. function uroWazeBits()
  6685. {
  6686. // "fake" uroWazeBits() function which only performs layer scan, to stop the uroWazeBits() call in WMETB from
  6687. // messing around with other stuff in the actual uroWazeBits() function (now renamed uroRealWazeBits...) that
  6688. // really only ought to be called once.
  6689. var i;
  6690. for(i=0;i<W.map.layers.length;i++)
  6691. {
  6692. if(W.map.layers[i].name == 'Spotlight') uroMaskLayer = i;
  6693. if(W.map.layers[i].name.indexOf('Waze.Control.SelectHighlightFeature') != -1) uroRootContainer = W.map.layers[i].div.id;
  6694. if(W.map.layers[i].name == 'Node Connections') uroTurnsLayerIdx = i;
  6695. }
  6696. uroPlacesRoot = W.map.landmarkLayer.id + '_vroot';
  6697.  
  6698. for(i=0;i<W.map.controls.length;i++)
  6699. {
  6700. if(W.map.controls[i].CLASS_NAME == 'Waze.View.ArchivePanel') dteControlsIdx = i;
  6701. else if(W.map.controls[i].CLASS_NAME == 'Waze.Control.Archive') dteControlsIdx = i;
  6702.  
  6703. if(W.map.controls[i].id !== null)
  6704. {
  6705. if(W.map.controls[i].id.indexOf('UpdateRequests') != -1) uroURControlsIdx = i;
  6706. if(W.map.controls[i].id.indexOf('MapProblems') != -1) uroProblemControlsIdx = i;
  6707. }
  6708. }
  6709. uroAddLog('uroMaskLayer at idx '+uroMaskLayer);
  6710. uroAddLog('Turns layer at idx '+uroTurnsLayerIdx);
  6711. uroAddLog('uroRootContainer = '+uroRootContainer);
  6712. uroAddLog('Places root layer = '+uroPlacesRoot);
  6713. }
  6714.  
  6715.  
  6716. function uroRealWazeBits()
  6717. {
  6718. if(document.getElementsByClassName("sandbox").length > 0)
  6719. {
  6720. uroAddLog('WME practice mode detected, script is disabled...');
  6721. return;
  6722. }
  6723.  
  6724. uroAddLog('adding WazeBits...'+uroToHex(uroWazeBitsPresent,4));
  6725. if((uroWazeBitsPresent & 0x0001) === 0)
  6726. {
  6727. if(typeof W != "undefined")
  6728. {
  6729. if(typeof W.map != "undefined")
  6730. {
  6731. uroAddLog(' W.map OK');
  6732. uroWazeBitsPresent |= 0x0001;
  6733. }
  6734. }
  6735. }
  6736. if((uroWazeBitsPresent & 0x0002) === 0)
  6737. {
  6738. if(typeof W != "undefined")
  6739. {
  6740. if(typeof W.model != "undefined")
  6741. {
  6742. uroAddLog(' W.model OK');
  6743. uroWazeBitsPresent |= 0x0002;
  6744. }
  6745. }
  6746. }
  6747. if((uroWazeBitsPresent & 0x0004) === 0)
  6748. {
  6749. if(typeof W != "undefined")
  6750. {
  6751. if(typeof W.loginManager != "undefined")
  6752. {
  6753. uroAddLog(' loginManager OK');
  6754. uroWazeBitsPresent |= 0x0004;
  6755. }
  6756. }
  6757. }
  6758. if((uroWazeBitsPresent & 0x0008) === 0)
  6759. {
  6760. if(typeof W != "undefined")
  6761. {
  6762. if(typeof W.selectionManager != "undefined")
  6763. {
  6764. uroAddLog(' selectionManager OK');
  6765. uroWazeBitsPresent |= 0x0008;
  6766. }
  6767. }
  6768. }
  6769. if((uroWazeBitsPresent & 0x0010) === 0)
  6770. {
  6771. if(typeof OpenLayers != "undefined")
  6772. {
  6773. uroAddLog(' OpenLayers OK');
  6774. uroWazeBitsPresent |= 0x0010;
  6775. }
  6776. }
  6777. if((uroWazeBitsPresent & 0x0020) === 0)
  6778. {
  6779. if(typeof Waze != "undefined")
  6780. {
  6781. uroAddLog(' Waze OK');
  6782. uroWazeBitsPresent |= 0x0020;
  6783. }
  6784. }
  6785. if((uroWazeBitsPresent & 0x0040) === 0)
  6786. {
  6787. if(document.getElementById('user-tabs') !== null)
  6788. {
  6789. uroUserTabId = 'user-tabs';
  6790. uroAddLog(' user-tabs OK');
  6791. uroWazeBitsPresent |= 0x0040;
  6792. }
  6793. }
  6794. if((uroWazeBitsPresent & 0x0080) === 0)
  6795. {
  6796. if(document.getElementById('sidepanel-drives') !== null)
  6797. {
  6798. uroAddLog(' sidepanel-drives OK');
  6799. uroWazeBitsPresent |= 0x0080;
  6800. }
  6801. }
  6802. if((uroWazeBitsPresent & 0x0100) === 0)
  6803. {
  6804. if(typeof I18n != "undefined")
  6805. {
  6806. uroAddLog(' I18n OK');
  6807. uroWazeBitsPresent |= 0x0100;
  6808. }
  6809. }
  6810.  
  6811. if(uroWazeBitsPresent !== 0x01FF) setTimeout(uroRealWazeBits,250);
  6812. else if(W.loginManager.isLoggedIn() === false)
  6813. {
  6814. uroAddLog('Waiting for user log-in...');
  6815. setTimeout(uroRealWazeBits,1000);
  6816. }
  6817. else
  6818. {
  6819. uroAddLog('All WazeBits present and correct...');
  6820.  
  6821. uroDOMHasTurnProblems = (W.model.turnProblems !== undefined);
  6822.  
  6823. uroPopulatePlacesTab();
  6824.  
  6825. uroControls.appendChild(uroCtrlURs);
  6826. uroControls.appendChild(uroCtrlMPs);
  6827. uroControls.appendChild(uroCtrlPlaces);
  6828. uroControls.appendChild(uroCtrlCameras);
  6829. uroControls.appendChild(uroOWL);
  6830. uroControls.appendChild(uroCtrlMisc);
  6831. uroControls.appendChild(uroCtrlHides);
  6832. uroControls.appendChild(uroAMList);
  6833.  
  6834. uroCtrlURs.onclick = uroFilterItems_URTabClick;
  6835. uroCtrlMPs.onclick = uroFilterItems_MPTabClick;
  6836. uroCtrlPlaces.onclick = uroFilterItems_PlacesTabClick;
  6837. uroCtrlCameras.onclick = uroFilterItems_CamerasTabClick;
  6838. uroCtrlMisc.onclick = uroFilterItems_MiscTabClick;
  6839.  
  6840. uroWazeBits();
  6841.  
  6842. uroDiv.addEventListener("mouseover", uroEnterPopup, false);
  6843. uroDiv.addEventListener("mouseout", uroExitPopup, false);
  6844.  
  6845. if(sessionStorage.UROverview_FID_IgnoreList === undefined) sessionStorage.UROverview_FID_IgnoreList = '';
  6846. if(sessionStorage.UROverview_FID_WatchList === undefined) sessionStorage.UROverview_FID_WatchList = '';
  6847.  
  6848. if(uroConfirmIntercepted === false) uroAddInterceptor();
  6849. if(uroBetaEditor === true)
  6850. {
  6851. uroAddLog('fixing header links...');
  6852. var nLinks = document.getElementsByClassName('waze-header-menu')[0].children.length;
  6853. for(var link=0; link<nLinks; link++)
  6854. {
  6855. var relLink = document.getElementsByClassName('waze-header-menu')[0].children[link].children[0].getAttribute('href');
  6856. relLink = 'https://www.waze.com' + relLink;
  6857. document.getElementsByClassName('waze-header-menu')[0].children[link].children[0].setAttribute('href',relLink);
  6858. }
  6859. }
  6860.  
  6861. setInterval(uroTenthSecondTick,100);
  6862. uroShowDebugOutput = uroPersistentDebugOutput;
  6863. }
  6864. }
  6865.  
  6866.  
  6867. function uroAddInterceptor()
  6868. {
  6869. uroAddLog('Adding interceptor function...');
  6870. // add interceptor function for confirm(), so that we can auto-select the "OK" option when solving URs
  6871. // which have pending question...
  6872.  
  6873. var _confirm = confirm;
  6874. confirm = function(msg)
  6875. {
  6876. if((I18n.lookup("update_requests.panel.confirm") == msg) && (uroGetCBChecked('_cbDisablePendingQuestions') === true))
  6877. {
  6878. uroAddLog('Intercepted pending comments confirmation...');
  6879. return true;
  6880. }
  6881. else if(typeof(msg) == 'undefined')
  6882. {
  6883. uroAddLog('Intercepted blank confirmation...');
  6884. return true;
  6885. }
  6886. else
  6887. {
  6888. return _confirm(msg);
  6889. }
  6890. };
  6891.  
  6892. uroConfirmIntercepted = true;
  6893. }
  6894.  
  6895.  
  6896. function uroEnterPopup()
  6897. {
  6898. uroMouseInPopup = true;
  6899. }
  6900.  
  6901. function uroExitPopup()
  6902. {
  6903. uroMouseInPopup = false;
  6904. }
  6905.  
  6906. function uroToggleDebug()
  6907. {
  6908. uroShowDebugOutput = !uroShowDebugOutput;
  6909. var dbgMode = "none";
  6910. if(uroShowDebugOutput)
  6911. {
  6912. dbgMode = "inline";
  6913. }
  6914. document.getElementById('_uroDebugMode').style.display = dbgMode;
  6915. }
  6916.  
  6917. function uroInitialise()
  6918. {
  6919. if(document.URL.indexOf('editor-beta') != -1) uroBetaEditor = true;
  6920. var urlBits = document.URL.split("&mapUpdateRequest=");
  6921. if(urlBits.length == 2)
  6922. {
  6923. uroURIDInURL = parseInt(urlBits[1].split('&')[0]);
  6924. uroAddLog('found UR ID '+uroURIDInURL+' in URL');
  6925. }
  6926.  
  6927. // create a new div to display the UR details floaty-box
  6928. uroDiv = document.createElement('div');
  6929. uroDiv.id = "uroDiv";
  6930. uroDiv.style.position = 'absolute';
  6931. uroDiv.style.visibility = 'hidden';
  6932. uroDiv.style.top = '0';
  6933. uroDiv.style.left = '0';
  6934. uroDiv.style.zIndex = 100;
  6935. uroDiv.style.backgroundColor = 'aliceblue';
  6936. uroDiv.style.borderWidth = '3px';
  6937. uroDiv.style.borderStyle = 'solid';
  6938. uroDiv.style.borderRadius = '10px';
  6939. uroDiv.style.boxShadow = '5px 5px 10px Silver';
  6940. uroDiv.style.padding = '4px';
  6941. document.body.appendChild(uroDiv);
  6942.  
  6943.  
  6944. uroControls = document.createElement('section');
  6945. uroControls.style.fontSize = '12px';
  6946. uroControls.id = 'uroControls';
  6947. var updateURL;
  6948. if(navigator.userAgent.indexOf('Chrome') == -1)
  6949. {
  6950. updateURL = 'https://greasyfork.org/scripts/1952-uroverview-plus-uro';
  6951. }
  6952. else
  6953. {
  6954. updateURL = 'https://chrome.google.com/webstore/detail/uroverview/amdamgkgchnbaopmphhjapmjcdghdphi';
  6955. }
  6956. var tabbyHTML = '<b><a href="'+updateURL+'" target="_blank">UROverview Plus</a></b> <label id="_uroVersion">'+uroVersion+'</label>';
  6957. tabbyHTML += '<label id="_uroDebugMode">(dbg)</label>';
  6958. tabbyHTML += '&nbsp;<input type="checkbox" id="_cbMasterEnable" checked>Enabled</input>';
  6959. tabbyHTML += '<p><table border=0 width="100%"><tr>';
  6960. tabbyHTML += '<td valign="center" align="center" id="_tabSelectUserRequests"><a href="#" id="_linkSelectUserRequests" style="text-decoration:none;font-size:12px">URs</a></td>';
  6961. tabbyHTML += '<td valign="center" align="center" id="_tabSelectMapProblems"><a href="#" id="_linkSelectMapProblems" style="text-decoration:none;font-size:12px">MPs</a></td>';
  6962. tabbyHTML += '<td valign="center" align="center" id="_tabSelectPlaces"><a href="#" id="_linkSelectPlaces" style="text-decoration:none;font-size:12px">Places</a></td>';
  6963. tabbyHTML += '<td valign="center" align="center" id="_tabSelectCameras"><a href="#" id="_linkSelectCameras" style="text-decoration:none;font-size:12px">Cams</a></td>';
  6964. tabbyHTML += '<td valign="center" align="center" id="_tabSelectCWL"><a href="#" id="_linkSelectOWL" style="text-decoration:none;font-size:12px">OWL</a></td>';
  6965. tabbyHTML += '<td valign="center" align="center" id="_tabSelectMisc"><a href="#" id="_linkSelectMisc" style="text-decoration:none;font-size:12px">Misc</a></td>';
  6966. tabbyHTML += '</tr></table>';
  6967. uroControls.innerHTML = tabbyHTML;
  6968.  
  6969.  
  6970. uroCtrlURs = document.createElement('p');
  6971. uroCtrlMPs = document.createElement('p');
  6972. uroCtrlCameras = document.createElement('p');
  6973. uroOWL = document.createElement('p');
  6974. uroCtrlMisc = document.createElement('p');
  6975. uroAMList = document.createElement('div');
  6976. uroCtrlHides = document.createElement('div');
  6977. uroCtrlPlaces = document.createElement('p');
  6978.  
  6979. // UR controls tab
  6980. uroCtrlURs.id = "uroCtrlURs";
  6981. uroCtrlURs.innerHTML = '<br>';
  6982.  
  6983. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbURFilterOutsideArea">Hide URs outside my editable area</input><br>';
  6984. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbNoFilterForURInURL">Don\'t filter UR in URL</input><br><br>';
  6985. uroCtrlURs.innerHTML += '<b>Filter by type:</b><br>';
  6986. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterWazeAuto">Waze Automatic</input><br>';
  6987. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterIncorrectTurn">Incorrect turn</input><br>';
  6988. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterIncorrectAddress">Incorrect address</input><br>';
  6989. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterIncorrectRoute">Incorrect route</input><br>';
  6990. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterMissingRoundabout">Missing roundabout</input><br>';
  6991. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterGeneralError">General error</input><br>';
  6992. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterTurnNotAllowed">Turn not allowed</input><br>';
  6993. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterIncorrectJunction">Incorrect junction</input><br>';
  6994. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterMissingBridgeOverpass">Missing bridge overpass</input><br>';
  6995. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterWrongDrivingDirection">Wrong driving direction</input><br>';
  6996. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterMissingExit">Missing exit</input><br>';
  6997. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterMissingRoad">Missing road</input><br>';
  6998. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterBlockedRoad">Blocked road</input><br>';
  6999. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterMissingLandmark">Missing Landmark</input><br>';
  7000. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterUndefined">Undefined</input><br>';
  7001.  
  7002. uroCtrlURs.innerHTML += '&nbsp;&nbsp;<i>Specially tagged types</i><br>';
  7003. uroCtrlURs.innerHTML += '&nbsp;&nbsp;<input type="checkbox" id="_cbFilterRoadworks">[ROADWORKS]</input><br>';
  7004. uroCtrlURs.innerHTML += '&nbsp;&nbsp;<input type="checkbox" id="_cbFilterConstruction">[CONSTRUCTION]</input><br>';
  7005. uroCtrlURs.innerHTML += '&nbsp;&nbsp;<input type="checkbox" id="_cbFilterClosure">[CLOSURE]</input><br>';
  7006. uroCtrlURs.innerHTML += '&nbsp;&nbsp;<input type="checkbox" id="_cbFilterEvent">[EVENT]</input><br>';
  7007. uroCtrlURs.innerHTML += '&nbsp;&nbsp;<input type="checkbox" id="_cbFilterNote">[NOTE]</input><br><br>';
  7008. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbInvertURFilter">Invert operation of type filters?</input><br>';
  7009.  
  7010. uroCtrlURs.innerHTML += '<hr>';
  7011.  
  7012. uroCtrlURs.innerHTML += '<br><b>Hide by state:</b><br>';
  7013. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterOpenUR">Open</input><br>';
  7014. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterClosedUR">Closed</input><br>';
  7015. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterSolved">Solved</input><br>';
  7016. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterUnidentified">Not identified</input><br><br>';
  7017.  
  7018.  
  7019. uroCtrlURs.innerHTML += '<br><b>Filter by age of submission:</b><br>';
  7020. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableMinAgeFilter">Hide URs less than </input>';
  7021. 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>';
  7022. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableMaxAgeFilter">Hide URs more than </input>';
  7023. 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>';
  7024.  
  7025. uroCtrlURs.innerHTML += '<br><b>Filter by description/comments/following:</b><br>';
  7026. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbURDescriptionMustBePresent" pairedWith="_cbURDescriptionMustBeAbsent">Hide</input> or ';
  7027. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbURDescriptionMustBeAbsent" pairedWith="_cbURDescriptionMustBePresent">show</input> URs with no description<br>';
  7028. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableKeywordMustBePresent">Hide URs not including </input>';
  7029. uroCtrlURs.innerHTML += '<input type="text" style="font-size:14px; line-height:16px; height:22px; margin-bottom:4px;" id="_textKeywordPresent"><br>';
  7030. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableKeywordMustBeAbsent">Hide URs including </input>';
  7031. uroCtrlURs.innerHTML += '<input type="text" style="font-size:14px; line-height:16px; height:22px; margin-bottom:4px;" id="_textKeywordAbsent"><br>';
  7032. uroCtrlURs.innerHTML += '&nbsp;&nbsp;<input type="checkbox" id="_cbCaseInsensitive"><i>Case-insensitive matches?</i></input><br><br>';
  7033.  
  7034. uroCtrlURs.innerHTML += 'With comments from me?<br>';
  7035. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideMyComments" pairedWith="_cbHideAnyComments">Yes </input>';
  7036. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideAnyComments" pairedWith="_cbHideMyComments">No</input><br>';
  7037.  
  7038. uroCtrlURs.innerHTML += 'If last comment made by me?<br>';
  7039. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideIfLastCommenter" pairedWith="_cbHideIfNotLastCommenter">Yes </input>';
  7040. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideIfNotLastCommenter" pairedWith="_cbHideIfLastCommenter">No </input><br>';
  7041.  
  7042. uroCtrlURs.innerHTML += 'If last comment made by UR reporter?<br>';
  7043. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideIfReporterLastCommenter" pairedWith="_cbHideIfReporterNotLastCommenter">Yes </input>';
  7044. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideIfReporterNotLastCommenter" pairedWith="_cbHideIfReporterLastCommenter">No</input><br>';
  7045.  
  7046. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableMinCommentsFilter">With less than </input>';
  7047. uroCtrlURs.innerHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterMinComments"> comments<br>';
  7048. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableMaxCommentsFilter">With more than </input>';
  7049. uroCtrlURs.innerHTML += '<input type="number" min="0" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterMaxComments"> comments<br>';
  7050.  
  7051. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideMyFollowed" pairedWith="_cbHideMyUnfollowed">Ones I am or </input>';
  7052. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideMyUnfollowed" pairedWith="_cbHideMyFollowed">am not following</input><br>';
  7053.  
  7054. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableCommentAgeFilter2">Last comment less than </input>';
  7055. 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>';
  7056. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableCommentAgeFilter">Last comment more than </input>';
  7057. 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>';
  7058.  
  7059. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbURUserIDFilter">Without comments from user</input>';
  7060. uroCtrlURs.innerHTML += '<select id="_selectURUserID" style="width:80%; height:22px;"></select><br>';
  7061. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbURResolverIDFilter">Not resolved by user</input>';
  7062. uroCtrlURs.innerHTML += '<select id="_selectURResolverID" style="width:80%; height:22px;"></select>';
  7063.  
  7064. uroCtrlURs.innerHTML += '<br><br><input type="checkbox" id="_cbNoFilterForTaggedURs"><b>Don\'t apply state/age filters to tagged URs</b></input><br>';
  7065.  
  7066.  
  7067. // Map problems controls tab
  7068. uroCtrlMPs.id = "uroCtrlMPs";
  7069. uroCtrlMPs.innerHTML = '<br>';
  7070.  
  7071. uroCtrlMPs.innerHTML += '<b>Filter MPs by type:</b><br>';
  7072. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterMissingJunction">Missing junction</input><br>';
  7073. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterMissingRoad">Missing road</input><br>';
  7074. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterCrossroadsJunctionMissing">Missing crossroads</input><br>';
  7075. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterDrivingDirectionMismatch">Driving direction mismatch</input><br>';
  7076. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterRoadTypeMismatch">Road type mismatch</input><br>';
  7077. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterRestrictedTurn">Restricted turn might be allowed</input><br>';
  7078. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterRoadClosureProblem">Road closure</input><br>';
  7079. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterUnknownProblem">Unknown problem type</input><br><br>';
  7080. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterTurnProblem">Turn Problems</input><br><br>';
  7081.  
  7082. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterReopenedProblem">Reopened Problems</input><br><br>';
  7083.  
  7084. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbInvertMPFilter">Invert operation of type filters?</input><br>';
  7085.  
  7086. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterOutsideArea">Hide MPs outside my editable area</input><br>';
  7087.  
  7088. uroCtrlMPs.innerHTML += '<br><b>Hide closed/solved/unidentified Problems:</b><br>';
  7089. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterClosed">Closed</input><br>';
  7090. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterSolved">Solved</input><br>';
  7091. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterUnidentified">Not identified</input><br><br>';
  7092.  
  7093. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPClosedUserIDFilter" pairedWith="_cbMPNotClosedUserIDFilter">Closed</input> or ';
  7094. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPNotClosedUserIDFilter" pairedWith="_cbMPClosedUserIDFilter">Not Closed</input> by user';
  7095. uroCtrlMPs.innerHTML += '<select id="_selectMPUserID" style="width:80%; height:22px;"></select><br>';
  7096.  
  7097. uroCtrlMPs.innerHTML += '<br><b>Hide problems (not turn) by severity:</b><br>';
  7098. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterLowSeverity">Low</input>&nbsp;&nbsp;';
  7099. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterMediumSeverity">Medium</input>&nbsp;&nbsp;';
  7100. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterHighSeverity">High</input><br>';
  7101.  
  7102.  
  7103. // Places filtering tab
  7104. uroCtrlPlaces.id = "uroCtrlPlaces";
  7105. uroCtrlPlaces.innerHTML = 'Places filter list being populated, please wait...';
  7106.  
  7107.  
  7108. // Camera controls tab
  7109. uroCtrlCameras.id = "uroCtrlCameras";
  7110. uroCtrlCameras.innerHTML = '<br><b>Show Cameras by creator:</b><br>';
  7111. uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowWorldCams" checked>world_* users</input><br>';
  7112. uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowUSACams" checked>usa_* users</input><br>';
  7113. uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowNonWorldCams" checked>other users</input><br>';
  7114. uroCtrlCameras.innerHTML += '<br><input type="checkbox" id="_cbShowOnlyMyCams">Show ONLY cameras created/edited by me</input><br>';
  7115.  
  7116.  
  7117. uroCtrlCameras.innerHTML += '<br><b>Show Cameras by approval status:</b><br>';
  7118. uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowApprovedCams" checked>approved</input><br>';
  7119. uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowNonApprovedCams" checked>non-approved</input><br>';
  7120. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbShowOlderCreatedNonApproved"> if created more than </input>';
  7121. 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>';
  7122. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbShowOlderUpdatedNonApproved"> if updated more than </input>';
  7123. 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>';
  7124.  
  7125. uroCtrlCameras.innerHTML += '<br><b>Show Cameras by type:</b><br>';
  7126. uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowSpeedCams" checked>Speed</input><br>';
  7127. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbShowIfSpeedSet" checked> with speed data</input><br>';
  7128. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbShowIfNoSpeedSet" checked> with no speed data</input><br>';
  7129. uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowRedLightCams" checked>Red Light</input><br>';
  7130. uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowDummyCams" checked>Dummy</input><br>';
  7131.  
  7132. uroCtrlCameras.innerHTML += '<br><b>Hide Cameras by creator:</b><br>';
  7133. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideCreatedByMe">me</input>';
  7134. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideCreatedByRank0">L1</input>';
  7135. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideCreatedByRank1">L2</input>';
  7136. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideCreatedByRank2">L3</input>';
  7137. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideCreatedByRank3">L4</input>';
  7138. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideCreatedByRank4">L5</input>';
  7139. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideCreatedByRank5">L6</input>';
  7140.  
  7141. uroCtrlCameras.innerHTML += '<br><b>Hide Cameras by updater:</b><br>';
  7142. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideUpdatedByMe">me</input>';
  7143. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideUpdatedByRank0">L1</input>';
  7144. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideUpdatedByRank1">L2</input>';
  7145. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideUpdatedByRank2">L3</input>';
  7146. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideUpdatedByRank3">L4</input>';
  7147. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideUpdatedByRank4">L5</input>';
  7148. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideUpdatedByRank5">L6</input>';
  7149.  
  7150. uroCtrlCameras.innerHTML += '<br><br><b><input type="checkbox" id="_cbHideCWLCams">Hide cameras on watchlist</input></b><br>';
  7151.  
  7152.  
  7153. // Object watchlist tab
  7154. uroOWL.id = "uroOWL";
  7155. uroOWLUpdateHTML();
  7156.  
  7157.  
  7158. // Misc controls tab
  7159. uroCtrlMisc.id = "uroCtrlMisc";
  7160. uroCtrlMisc.innerHTML = '<br><b>Use default conversation markers:</b><br>';
  7161. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbNativeConvoMarkers" checked>in public WME</input><br>';
  7162. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbNativeBetaConvoMarkers" checked>in beta WME</input><br>';
  7163.  
  7164. uroCtrlMisc.innerHTML += '<br><br><b><input type="checkbox" id="_cbCommentCount">Show comment count on UR markers</input></b><br>';
  7165.  
  7166. uroCtrlMisc.innerHTML += '<br><br><b><input type="checkbox" id="_cbURBackfill">Backfill UR data</input></b><br>';
  7167.  
  7168. uroCtrlMisc.innerHTML += '<br><br><b>Marker Unstacking:</b><br>';
  7169. 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>';
  7170. 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>';
  7171.  
  7172. uroCtrlMisc.innerHTML += '<br><br><b>Use custom marker for URs tagged as:</b><br>';
  7173. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomRoadworksMarkers">[ROADWORKS]</input><br>';
  7174. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomConstructionMarkers">[CONSTRUCTION]</input><br>';
  7175. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomClosuresMarkers">[CLOSURE]</input><br>';
  7176. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomEventsMarkers">[EVENT]</input><br>';
  7177. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomNotesMarkers">[NOTE]</input><br>';
  7178.  
  7179. uroCtrlMisc.innerHTML += '<br><br><b>Use custom marker for MPs tagged as:</b><br>';
  7180. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomElginMarkers">[Elgin]</input><br>';
  7181. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomTrafficMasterMarkers">[TM]</input><br>';
  7182. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomTrafficCastMarkers">[TrafficCast]</input><br>';
  7183.  
  7184. uroCtrlMisc.innerHTML += '<br><br><b>Popup mouse behaviour:</b><br>';
  7185. 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>';
  7186. 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>';
  7187. 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>';
  7188.  
  7189. uroCtrlMisc.innerHTML += '<br><br><b>Disable popup for:</b><br>';
  7190. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitURPopup">URs</input><br>';
  7191. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitMPPopup">MPs</input><br>';
  7192. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitCamPopup">Cameras</input><br>';
  7193. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitSegPopup">Segments</input><br>';
  7194. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitTurnsPopup">Restricted Turns</input><br>';
  7195. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitLandmarkPopup">Places</input><br>';
  7196. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitPUPopup">Place Updates</input><br>';
  7197.  
  7198. uroCtrlMisc.innerHTML += '<br><br><b>Date/Time formatting for popups:</b><br>';
  7199. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbDateFmtDDMMYY" pairedWith="_cbDateFmtMMDDYY,_cbDateFmtYYMMDD" checked>day/month/year</input><br>';
  7200. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbDateFmtMMDDYY" pairedWith="_cbDateFmtDDMMYY,_cbDateFmtYYMMDD">month/day/year</input><br>';
  7201. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbDateFmtYYMMDD" pairedWith="_cbDateFmtMMDDYY,_cbDateFmtDDMMYY">year/month/day</input><br><br>';
  7202. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbTimeFmt24H" pairedWith="_cbTimeFmt12H" checked>24 hour</input><br>';
  7203. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbTimeFmt12H" pairedWith="_cbTimeFmt24H">12 hour</input><br><br>';
  7204. uroCtrlMisc.innerHTML += '<i>Unticked uses browser default setting</i>';
  7205.  
  7206. uroCtrlMisc.innerHTML += '<br><br><b><input type="checkbox" id="_cbWhiteBackground">Use custom background colour</input></b><br>';
  7207. 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">';
  7208. 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">';
  7209. 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>';
  7210.  
  7211. uroCtrlMisc.innerHTML += '<br><br><b>Disable map move when selecting:</b><br>';
  7212. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitURCentering">URs</input><br>';
  7213. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitMPCentering">MPs</input><br>';
  7214. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitPURCentering">PURs</input><br>';
  7215.  
  7216. uroCtrlMisc.innerHTML += '<br><br><b>Replace "Next ..." button with "Done" for:</b><br>';
  7217. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitNURButton">URs</input><br>';
  7218. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitNMPButton">MPs</input><br>';
  7219. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitNPURButton">PURs</input><br>';
  7220. uroCtrlMisc.innerHTML += '<br><br><b><input type="checkbox" id="_cbHideAMLayer">Hide Area Manager polygons</input></b><br>';
  7221. uroCtrlMisc.innerHTML += '<b><input type="checkbox" id="_cbDisablePlacesFiltering">Disable Places filtering</input></b><br>';
  7222. ////uroCtrlMisc.innerHTML += '<b><input type="checkbox" id="_cbDisablePendingQuestions">Disable UR Pending Questions confirmation</input></b><br>';
  7223. uroCtrlMisc.innerHTML += '<b><input type="checkbox" id="_cbHideEditorInfo">Hide sidebar editor info</input></b><br>';
  7224. uroCtrlMisc.innerHTML += '<b><input type="checkbox" id="_cbEnableDTE">Drive Tab Enhancement (DTE)</input></b><br>';
  7225.  
  7226. uroCtrlMisc.innerHTML += '<br><br><b>Settings backup/restore/reset:</b><br>';
  7227. uroCtrlMisc.innerHTML += '<input type="button" id="_btnSettingsToText" value="Backup">&nbsp;&nbsp;&nbsp;';
  7228. uroCtrlMisc.innerHTML += '<input type="button" id="_btnTextToSettings" value="Restore">&nbsp;&nbsp;|&nbsp;&nbsp;';
  7229. uroCtrlMisc.innerHTML += '<input type="button" id="_btnResetSettings" value="Reset"><br><br>';
  7230.  
  7231. uroCtrlMisc.innerHTML += '<textarea id="_txtSettings" value="" /><br>';
  7232. uroCtrlMisc.innerHTML += '<input type="button" id="_btnClearSettingsText" value="Clear"><br>';
  7233.  
  7234. // footer for tabs container
  7235. uroCtrlHides.id = 'uroCtrlHides';
  7236. uroCtrlHides.innerHTML = '<input type="button" id="_btnUndoLastHide" value="Undo last hide">&nbsp;&nbsp;&nbsp;';
  7237. uroCtrlHides.innerHTML += '<input type="button" id="_btnClearSessionHides" value="Undo all hides"><p>';
  7238.  
  7239. // footer for AM list
  7240. uroAMList.id = 'uroAMList';
  7241. window.addEventListener("beforeunload", uroSaveSettings, false);
  7242.  
  7243. uroRealWazeBits();
  7244. }
  7245.  
  7246.  
  7247. function dteAddHeader()
  7248. {
  7249. var rlcObj = document.getElementsByClassName("result-list-container");
  7250. if(typeof rlcObj == "undefined") return;
  7251. if(typeof rlcObj[0].children[0] == "undefined") return;
  7252. if(typeof rlcObj[0].children[0].innerHTML == "undefined") return;
  7253.  
  7254. var thtml = rlcObj[0].children[0].innerHTML;
  7255. if(thtml.indexOf('Full drive history') == -1)
  7256. {
  7257. thtml += '<br><br><i><small>Full drive history goes back to '+dteOldestFullDrive.toDateString()+'</small></i>';
  7258. rlcObj[0].children[0].innerHTML = thtml;
  7259. }
  7260. }
  7261.  
  7262.  
  7263. function dteSetNewTabLength()
  7264. {
  7265. uroAddLog('altering ResultsPerPage parameter...');
  7266.  
  7267. var t = document.getElementById('sidepanel-drives');
  7268. t.style.overflow = 'auto';
  7269. t.style.height = (window.innerHeight * 0.6) + 'px';
  7270.  
  7271. var baseloc = 'https://'+window.location.hostname+Waze.Config.api_base+'/Archive/MyList?minDistance=1000';
  7272.  
  7273. var a = new XMLHttpRequest();
  7274. var fullDrives = 0;
  7275. var nPages = 1;
  7276. var foundMissingDrive = false;
  7277.  
  7278. while(!foundMissingDrive)
  7279. {
  7280. var loc = baseloc+'&offset='+fullDrives+'&count=5';
  7281. uroAddLog('requesting '+loc);
  7282. var retries = 0;
  7283. while(retries < 3)
  7284. {
  7285. a.open('GET',loc,false);
  7286. a.send();
  7287. if(a.responseText !== "")
  7288. {
  7289. break;
  7290. }
  7291. retries++;
  7292. }
  7293. if(a.responseText !== "")
  7294. {
  7295. var b = JSON.parse(a.responseText);
  7296. var loadedDrives = b.archives.objects.length;
  7297. uroAddLog('received '+loadedDrives+' drives');
  7298. if(loadedDrives != 5) foundMissingDrive = true;
  7299.  
  7300. for(var loop=0; loop < loadedDrives; loop++)
  7301. {
  7302. if(b.archives.objects[loop].hasFullSession === false)
  7303. {
  7304. foundMissingDrive = true;
  7305. }
  7306. else
  7307. {
  7308. fullDrives++;
  7309. dteOldestFullDrive = new Date(b.archives.objects[loop].startTime);
  7310. }
  7311. }
  7312. }
  7313. else
  7314. {
  7315. foundMissingDrive = true;
  7316. }
  7317. }
  7318.  
  7319. uroAddLog(fullDrives+' full drives in history');
  7320. uroAddLog('oldest drives are on '+dteOldestFullDrive.toDateString());
  7321. if(fullDrives < 5)
  7322. {
  7323. fullDrives = 5;
  7324. uroAddLog('insufficient full drives, using standard drives tab');
  7325. }
  7326. else if(fullDrives > 50)
  7327. {
  7328. nPages = Math.ceil(fullDrives / 50);
  7329. uroAddLog('too many full drives for a single tab page, splitting over '+nPages+' pages...');
  7330. fullDrives = Math.ceil(fullDrives/nPages);
  7331. }
  7332.  
  7333. if((dteOldestFullDrive - dteEpoch) > 0)
  7334. {
  7335. var totalDrives = 0;
  7336. if(W.model.archives.additionalInfo !== null)
  7337. {
  7338. totalDrives = W.model.archives.additionalInfo.totalSessions;
  7339. }
  7340. if(totalDrives !== null)
  7341. {
  7342. uroAddLog('updating drives tab...');
  7343. W.map.controls[dteControlsIdx].sidePanelView.ResultsPerPage = fullDrives;
  7344. uroAddLog(totalDrives+' drives in history');
  7345. W.map.controls[dteControlsIdx].sidePanelView.setSessions(totalDrives);
  7346. W.map.controls[dteControlsIdx].loadSessions(0);
  7347. }
  7348. setInterval(dteAddHeader,250);
  7349. setInterval(dteCheckDriveListChanges,250);
  7350. }
  7351. }
  7352.  
  7353. function dteListClick()
  7354. {
  7355. dteClearListHighlight();
  7356. this.style.backgroundColor = "lightgreen";
  7357. dteArmClearHighlightsOnPanelClose = true;
  7358. }
  7359.  
  7360. function dteClearListHighlight()
  7361. {
  7362. var drivesShown = document.getElementById('sidepanel-drives').getElementsByClassName('result session').length;
  7363. if(drivesShown > 0)
  7364. {
  7365. for(var loop = 0;loop < drivesShown; loop++)
  7366. {
  7367. var listEntry = document.getElementById('sidepanel-drives').getElementsByClassName('result session')[loop];
  7368. listEntry.style.backgroundColor = "";
  7369. }
  7370. }
  7371. }
  7372.  
  7373. function dteCheckDriveListChanges()
  7374. {
  7375. var drivesShown = document.getElementById('sidepanel-drives').getElementsByClassName('result session').length;
  7376. if(drivesShown > 0)
  7377. {
  7378. var topID = document.getElementById('sidepanel-drives').getElementsByClassName('result session')[0].getAttribute('data-id');
  7379. if(topID != dteTopID)
  7380. {
  7381. dteTopID = topID;
  7382. for(var loop = 0;loop < drivesShown; loop++)
  7383. {
  7384. var listEntry = document.getElementById('sidepanel-drives').getElementsByClassName('result session')[loop];
  7385. var driveID = listEntry.getAttribute('data-id');
  7386. var driveObj = W.model.archives.objects[driveID];
  7387. var driveSecs = Math.floor((driveObj.endTime - driveObj.startTime) / 1000);
  7388. var driveHours = Math.floor(driveSecs / 3600);
  7389. driveSecs -= (driveHours * 3600);
  7390. var driveMins = Math.floor(driveSecs / 60);
  7391. driveSecs -= (driveMins * 60);
  7392. var trueTime = (driveHours+':'+("0"+driveMins).slice(-2)+'.'+("0"+driveSecs).slice(-2));
  7393. listEntry.getElementsByTagName('span')[1].innerHTML = trueTime;
  7394. listEntry.addEventListener("click", dteListClick, false);
  7395. }
  7396. }
  7397. }
  7398. }
  7399.  
  7400.  
  7401. function uroBootstrap()
  7402. {
  7403. uroInitialise();
  7404. }
  7405.  
  7406. uroBootstrap();
  7407.