UROverview Plus (URO+)

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

目前為 2015-03-20 提交的版本,檢視 最新版本

  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.41
  9. // ==/UserScript==
  10.  
  11. /*
  12. To-do list
  13. ==========
  14. Extend unstacking to cameras?
  15.  
  16. Restricted turn info popup
  17.  
  18. Place filtering
  19. - by last user to edit
  20. - collapsible filter subcategories
  21.  
  22. First-run information
  23. - show quickstart guide to URO features if no existing settings are present (i.e. new installation)
  24.  
  25. User-defined setting presets
  26.  
  27.  
  28. In Progress
  29. =====================
  30. Addition of segment and place watchlist functionality
  31.  
  32. Friendly naming of managed areas
  33.  
  34.  
  35. Done for this release
  36. =====================
  37. Undo last/all hide buttons are now hidden when not enabled
  38.  
  39. Mousedown state now tracked more reliably after panning the map
  40.  
  41. DTE option now shows true drive times in drive tab
  42.  
  43. PURs can be filtered by age, and their age is shown in the popup
  44.  
  45. SRS works in latest WME Beta
  46.  
  47. Improvements in UR comment count handling
  48.  
  49. */
  50.  
  51. function uroGlobals()
  52. {
  53. uroVersion = "3.41";
  54. uroShowDebugOutput = false;
  55. uroCtrlsHidden = false;
  56. uroCurrentTab = 1;
  57. uroFID = -1;
  58. uroShownFID = -1;
  59. uroShownPopupType = null;
  60. uroInhibitSave = true;
  61. uroPopupTimer = -2;
  62. uroPopupShown = false;
  63. uroSetupListeners = true;
  64. uroRootContainer = null;
  65. uroPlacesRoot = null;
  66. uroMaskLayer = null;
  67. uroCustomMarkerFID = null;
  68. uroConfirmIntercepted = false;
  69. uroCustomMarkerList = [];
  70. uroPendingURSessionIDs = [];
  71. uroRequestedURSessionIDs = [];
  72. uroMouseInPopup = false;
  73. uroURControlsIdx = null;
  74. uroProblemControlsIdx = null;
  75. uroMaskActive = false;
  76. uroTurnsLayerIdx = null;
  77.  
  78. uroNullCamLayer = false;
  79. uroNullOpenLayers = false;
  80. uroNullRootContainer = false;
  81. uroNullURLayer = false;
  82. uroNullProblemLayer = false;
  83. uroNullMapViewport = false;
  84. uroURDialogIsOpen = false;
  85. uroSelectedURID = null;
  86. uroPendingCommentDataRefresh = false;
  87. uroWaitingCommentDataRefresh = false;
  88. uroExpectedCommentCount = null;
  89. uroPlaceSelected = false;
  90. uroMouseIsDown = false;
  91. uroBackfilling = false;
  92. uroUserID = -1;
  93. uroURSCurrentCount = 0;
  94. uroURSPrevCount = 0;
  95. uroDOMHasTurnProblems = false;
  96. uroBetaEditor = false;
  97. uroPracticeMode = false;
  98. uroWazeBitsPresent = 0;
  99.  
  100. uroCWLGroups = new Array();
  101. uroCamWatchObjects = new Array();
  102. uroSegWatchObjects = new Array();
  103. uroPlaceWatchObjects = new Array();
  104. uroFilteredCameraIDs = new Array();
  105. uroFriendlyAreaNames = new Array();
  106. uroAMPosX = null;
  107. uroAMPosY = null;
  108. dteControlsIdx = -1;
  109. dteOldestFullDrive = new Date(0);
  110. dteEpoch = new Date(0);
  111. dteTopID = '';
  112. uroUserTabId = '';
  113. uroUnstackedMasterID = null;
  114. uroStackList = new Array();
  115. uroStackType = null;
  116.  
  117. uroIcons =
  118. [
  119. // stuff used within the URO tabbed UI
  120. // 0 = group collapse/group expand
  121. [
  122. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94CAhYRIqo78SIAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAADtJREFUKM9j/P//PwNJgCQN////ZyFeGyMjIwMDAxMDiWAQamDB9Bb+kKTMBmICdxgFK64AxZKiSE3eAAOXFRnJRfN6AAAAAElFTkSuQmCC",
  123. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94CAhYRDHbt/O0AAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAAE5JREFUKM+9UkEKACAMcmP//7IdgghqMQvytoOKTiMJCRKBZNRpZgbAIcIzsa5XJcgOB8Qaaz3nSt4chlLX3nb9OXRlL7cO2V83I1Dn3QDKfhshMqWScAAAAABJRU5ErkJggg=="
  124. ],
  125. // 1 = addtogroup active/addtogroup idle
  126. [
  127. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94BGhYVKhKBubQAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAAEZJREFUOMtjYBjygBHB/P8fjzJGIszCZQA+gxkYWIjTABPDdAkL8U7G7hIcYcDISEGYwDQSFyZM5AQckYA4F7CQZ8goQAYAMCsd/TxbqrwAAAAASUVORK5CYII=",
  128. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94DAw0tDee2t8AAAABPSURBVDjL7ZAxCgAgDAMT6cP6dH+mUwfBaugmeFMpbTgCPA9j6H2M7MidvCZlAadgADDlIXY7E1OVM5NtB+5kuZN4VDtpleIkVAOrhHxWJoJkNv2QAd51AAAAAElFTkSuQmCC"
  129. ],
  130. // 2 = goto active/goto idle
  131. [
  132. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94BGhYfLAEN9AsAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAAGdJREFUOMutk+EKACEIg7fD93/l3Y+uP5kmeYMgkH0NTUpCRw+acgBynHaCKsgBlpaIhDJQtQchaAtIBuNAlAQSV7OUwPYYGX2kL6Zi37hYYk6NU1ZPui/Y4XWeVsWSDpdkt8bftvEFOy0jJkeygWMAAAAASUVORK5CYII=",
  133. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94DAw0tFm3TfiwAAABySURBVDjLrZNRDsAgCEPp4r306HKy7sMsMRMckZH4ZfqoYEFSMnVJshYAME7aQRS0AOaR9C5UFe5AoRnsQCbAW4wFAklRlaNd1ipIrxHeRwKGZeuuNcEjK554J5x7lohNS+g+4d39Kyqug2jGyqnwtzTengM2Gxwa0GsAAAAASUVORK5CYII="
  134. ],
  135. // replacements for native UR/problem markers
  136. // 3 = normal/selected open roadworks UR
  137. [
  138. "data:image/png;base64,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",
  139. "data:image/png;base64,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"
  140. ],
  141. // 4 = normal/selected closed roadworks UR
  142. [
  143. "data:image/png;base64,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",
  144. "data:image/png;base64,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"
  145. ],
  146. // 5 = normal/selected open closure UR
  147. [
  148. "data:image/png;base64,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",
  149. "data:image/png;base64,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"
  150. ],
  151. // 6 = normal/selected closed closure UR
  152. [
  153. "data:image/png;base64,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",
  154. "data:image/png;base64,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"
  155. ],
  156. // 7 = normal/selected open event UR
  157. [
  158. "data:image/png;base64,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",
  159. "data:image/png;base64,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"
  160. ],
  161. // 8 = normal/selected closed event UR
  162. [
  163. "data:image/png;base64,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",
  164. "data:image/png;base64,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"
  165. ],
  166. // 9 = normal/selected open note UR
  167. [
  168. "data:image/png;base64,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",
  169. "data:image/png;base64,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"
  170. ],
  171. // 10 = normal/selected closed note UR
  172. [
  173. "data:image/png;base64,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",
  174. "data:image/png;base64,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"
  175. ]
  176. ];
  177.  
  178. uroMarkers =
  179. [
  180. // 0 = comment count circle
  181. ["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=="],
  182. // 1 = green comment marker
  183. ["data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAaCAYAAAA5WTUBAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB90HAxYNHpXrSkMAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAABX9JREFUSMetlmuMFeUZx3/vvDNzZs5tL4dlu7sIuimYWJRQTTXGC6XRFBQIDau0pckmYIiJpmnTD40x9BLUGInES5sGRKmQwrIktsFCTeul2g8mXqrREl2atVph3cU9u3vOzjlzeWdePzCrG7PsnkXfL3PLPO8vz/M+//8jmHmJ81y/fD/T0jPc6xm+NRwQgI7LSh1mnl6zRfcEfnhprOIsgDRlLePY76sx0a8m2T90cnSIC1izQYhcyWlZ8K3crlDUtyxeU9CXbCrYy5xvs8DsBOBTdYYB/00+OFoNPzpRFbZ2948N+L+ofOJVvg4Is+2bTSvtxclfO250m2/dutpqt5bMGmg4+pBn970QDr9SH1NnrNVDJ8snLxRCAJmWi/Lfcbs5cdXOUnbNss3zSu2JgcO8sWN0Mhm2r24URH4JwDEd2d2y0nruqt+Wit9fejtCiHlBLC0tx7ti0B5509tEzdoTTEbBfCAcYGHHlU0Pt6+yl2+4/najXgmIghidaBKV4HsRKlAIQ2BIY1aQgbPv2klFtk98WD82F8RUJBNodorWitgK1t60+QbTr4bs3niIR2/rI/IVtQmfR3sOs3vjIbTWc/Rowq1bV9uhqPd2XFbqaARCAC6wsLDI2dR1U16X6OKBm/9Ibdxn+1MbCbyIx37YTxJr7jrcc55un15Xg3ZrCYvXFLSZp3cuCDMtSRFodTuN67t7iuZvrnsCr1znvjfuRGvNwz/4E2EtYtueDQgE0pbEKiHyI2rjAdIyMKSB1hoVxDgFG8OCSzYV7JEXyz3AA3NlwgaagJxSqvPi5HKkaSAMwa+u3UMcxdQnAsK64sDPTuBPBoT1iChQ7PzuUzy45mke6eljZLDMQ7ccYNe6g+xc/SRjoxN0ixUEfnhpI+XIAAUgE0dJpmR+g0zWwnYtTEvy62v3EvkKrTX+ZMhjm48QhzFxlCCEIFYJY6cr/H7LUbwxn6AW4ZV9HlnfT0l2MKWuc0HIFMQEkJbkp0c3k23KYLkm2WaHe/7RS7bJQSeaWGmkLbFsyd19t+EWbHSikZZk294NmJYkUQnKjxs0hXMbixRESMsIKvZIptS6iB3/2kboRUjLACHY8fJWdKLJ5GwMea5Fc80OP9m9lr13/Bknb1Nsy9H7+C3su/MYlisZ058gTVlrBOIL0ZBy6FTw74s7C90AZLLWudM+g2CpMEZr6Lvn77R0FrnjiQ0EXsSRe5+n2JZl++H1/Mf7JxnHfr+RcmggBnT9dPzqYH9Ffd5qQsyqmLvWHcS0Jduf3IjtWvzl/pcxbcnPn/kR+WKej455oRoT/Y14RwuwDOiysrJtwZWZ320/tF7OZVhJnKCCmDhOMC2J1pogLV+SiajKT9n742cjzrpL5rJ4AwiAKhBEtXgc33zp2J7n1ZTynfdHaWBnLdxCBssxsV2LfMnFKCTknBzH970U2do92MiMIdNymGmburWR8D2B+J53xaCztHT5vMzLSyq4MsffBo4wsL9aLr/jr4/qqt4ohE4NLKcTUOP6rfJJ/4baig/MpaXlDQHUk0lcI8dzp/p5/d7RWvSxvHn8tDc4HytPpoG4yk+8eILXx98Lrx4YftfsWtlq5GXzrIHKaoi+PzyjTh2ojNf/y7rR/1VfS+POa6hxgIXAEmABYBmmyLavLGzBUasuWpvX3T1Fc6bxbrC/ov5/fFIYoX18+O3qL5UfDwL+hUxWIgVpAxYBremztLKyuWmxs8rtktfEcdwRR0nmnLoagWmaZ+pnkleqH/tH/Ur0NnA2BdBfabwDmtOstAK5abIupo3uKu0sDygDI8B4+k7P50CLWZTUTS2+acrgpp2heFprTwAVoJ6Cfb0jf7qpPQ1geiamQMIpxeUC12fXeEi2BfEDMAAAAABJRU5ErkJggg=="],
  184. // 2 = yellow (own) comment marker
  185. ["data:image/png;base64,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"]
  186. ];
  187.  
  188. }
  189.  
  190.  
  191. function uroBootstrap()
  192. {
  193. var bGreasemonkeyServiceDefined = false;
  194. try {
  195. bGreasemonkeyServiceDefined = (typeof Components.interfaces.gmIGreasemonkeyService === "object");
  196. }
  197. catch (err) { /* Ignore */ }
  198. if (typeof unsafeWindow === "undefined" || ! bGreasemonkeyServiceDefined) {
  199. unsafeWindow = ( function () {
  200. var dummyElem = document.createElement('p');
  201. dummyElem.setAttribute('onclick', 'return window;');
  202. return dummyElem.onclick();
  203. }) ();
  204. }
  205. /* begin running the code! */
  206. uroInitialise();
  207. }
  208.  
  209.  
  210. function uroAddLog(logtext)
  211. {
  212. if(uroShowDebugOutput) console.log('URO+: '+logtext);
  213. }
  214.  
  215. function uroGetCBChecked(cbID)
  216. {
  217. return(document.getElementById(cbID).checked);
  218. }
  219.  
  220. function uroGetElmValue(elmID)
  221. {
  222. return(document.getElementById(elmID).value);
  223. }
  224.  
  225. function uroSetStyleDisplay(elm,style)
  226. {
  227. document.getElementById(elm).style.display = style;
  228. }
  229.  
  230. function uroSetOnClick(elm,fn)
  231. {
  232. document.getElementById(elm).onclick = fn;
  233. }
  234.  
  235. function uroAddEventListener(elm,eventType,eventFn,eventBool)
  236. {
  237. document.getElementById(elm).addEventListener(eventType, eventFn, eventBool);
  238. }
  239.  
  240.  
  241. function uroFirstTimerWelcomePack()
  242. {
  243. uroAddLog('welcome new users to Club URO...');
  244. // to be completed...
  245. }
  246.  
  247. function uroShowUpdateNotes()
  248. {
  249. uroAddLog('let existing users know what\'s new in this release');
  250. var alertMsg = 'URO+ Update Notes...\n\n';
  251. alertMsg += 'Thanks for upgrading to URO+ '+uroVersion+' (20150319). What\'s changed?\n\n';
  252.  
  253. alertMsg += '* Undo last/all hide buttons are now hidden when not enabled\n';
  254. alertMsg += '* Mousedown state now tracked more reliably after panning the map\n';
  255. alertMsg += '* DTE option now shows true drive times in drive tab\n';
  256. alertMsg += '* PURs can be filtered by age, and their age is shown in the popup\n';
  257. alertMsg += '* Improvements in UR comment count handling\n';
  258. if(uroBetaEditor)
  259. {
  260. alertMsg += '\nFor WME Beta:\n';
  261. alertMsg += '* Roundabout selection re-enabled\n';
  262. }
  263.  
  264. alert(alertMsg);
  265. }
  266.  
  267. function uroAdvertiseCustomIcons()
  268. {
  269. uroAddLog('advertise the benefits of custom UR icons...');
  270. var confirmMsg = 'URO+ Installation/Upgrade Processing...\n\n';
  271. 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 which have been tagged with a specific keyword in their description text.\n\n';
  272. confirmMsg += 'Markers are defined for [ROADWORKS], [CONSTRUCTION], [CLOSURE], [EVENT] and [NOTE] tags.\n\n';
  273. confirmMsg += 'Would you like me to automatically enable these custom markers?\n\n';
  274. confirmMsg += 'If you change your mind later on, they can be enabled/disabled via the Misc tab within the URO+ settings';
  275. if(confirm(confirmMsg) == true)
  276. {
  277. document.getElementById('_cbCustomRoadworksMarkers').checked = true;
  278. document.getElementById('_cbCustomConstructionMarkers').checked = true;
  279. document.getElementById('_cbCustomClosuresMarkers').checked = true;
  280. document.getElementById('_cbCustomEventsMarkers').checked = true;
  281. document.getElementById('_cbCustomNotesMarkers').checked = true;
  282. }
  283. }
  284.  
  285.  
  286. function uroGatherSettings(container)
  287. {
  288. var options = '';
  289. var urOptions = document.getElementById(container).getElementsByTagName('input');
  290. for (var optIdx=0;optIdx<urOptions.length;optIdx++)
  291. {
  292. var id = urOptions[optIdx].id;
  293. if((id.indexOf('_cb') == 0)||(id.indexOf('_text') == 0)||(id.indexOf('_input') == 0))
  294. {
  295. options += ':' + id;
  296. if(urOptions[optIdx].type == 'checkbox') options += ',' + urOptions[optIdx].checked.toString();
  297. else if((urOptions[optIdx].type == 'text')||(urOptions[optIdx].type == 'number')) options += ',' + urOptions[optIdx].value.toString();
  298. }
  299. }
  300. return options;
  301. }
  302.  
  303.  
  304. function uroGatherCamWatchList()
  305. {
  306. var liststr = '';
  307. for(var loop=0;loop<uroCamWatchObjects.length;loop++)
  308. {
  309. camObj = uroCamWatchObjects[loop];
  310. if((camObj.fid != undefined) && (camObj.persistent == true))
  311. {
  312. if(loop > 0) liststr += ':';
  313.  
  314. liststr += camObj.fid+',';
  315. liststr += camObj.watch.lon+',';
  316. liststr += camObj.watch.lat+',';
  317. liststr += camObj.watch.type+',';
  318. liststr += camObj.watch.azymuth+',';
  319. liststr += camObj.watch.speed+',';
  320. liststr += camObj.watch.validated+',';
  321. liststr += camObj.groupID+',';
  322. liststr += camObj.server;
  323. }
  324. }
  325. return liststr;
  326. }
  327. function uroGatherSegWatchList()
  328. {
  329. var liststr = '';
  330. for(var loop=0;loop<uroSegWatchObjects.length;loop++)
  331. {
  332. segObj = uroSegWatchObjects[loop];
  333. if((segObj.fid != undefined) && (segObj.persistent == true))
  334. {
  335. if(loop > 0) liststr += ':';
  336. liststr += segObj.fid+',';
  337. liststr += segObj.watch.left+',';
  338. liststr += segObj.watch.right+',';
  339. liststr += segObj.watch.bottom+',';
  340. liststr += segObj.watch.top+',';
  341. liststr += segObj.watch.fromNode+',';
  342. liststr += segObj.watch.toNode+',';
  343. liststr += segObj.watch.fwdDir+',';
  344. liststr += segObj.watch.revDir+',';
  345. liststr += segObj.watch.length+',';
  346. liststr += segObj.watch.level+',';
  347. liststr += segObj.watch.rank+',';
  348. liststr += segObj.watch.roadType+',';
  349. liststr += segObj.watch.updatedOn+',';
  350. liststr += segObj.groupID+',';
  351. liststr += segObj.server;
  352. }
  353. }
  354. return liststr;
  355. }
  356. function uroGatherPlaceWatchList()
  357. {
  358. var liststr = '';
  359. for(var loop=0;loop<uroPlaceWatchObjects.length;loop++)
  360. {
  361. placeObj = uroPlaceWatchObjects[loop];
  362. if((placeObj.fid != undefined) && (placeObj.persistent == true))
  363. {
  364. if(loop > 0) liststr += ':';
  365.  
  366. liststr += placeObj.fid+',';
  367. liststr += placeObj.watch.left+',';
  368. liststr += placeObj.watch.right+',';
  369. liststr += placeObj.watch.bottom+',';
  370. liststr += placeObj.watch.top+',';
  371. liststr += placeObj.watch.name+',';
  372. liststr += placeObj.watch.imageCount+',';
  373. liststr += placeObj.watch.residential+',';
  374. liststr += placeObj.watch.updatedOn+',';
  375. liststr += placeObj.groupID+',';
  376. liststr += placeObj.server;
  377. }
  378. }
  379. return liststr;
  380. }
  381.  
  382. function uroGatherCWLGroups()
  383. {
  384. var liststr = '';
  385. for(var loop=0;loop<uroCWLGroups.length;loop++)
  386. {
  387. groupObj = uroCWLGroups[loop];
  388. if(groupObj.groupID != -1)
  389. {
  390. if(loop > 0) liststr += ':';
  391.  
  392. liststr += groupObj.groupID+',';
  393. liststr += groupObj.groupName+',';
  394. liststr += groupObj.groupCollapsed;
  395. }
  396. }
  397. return liststr;
  398. }
  399.  
  400. function uroSaveSettings()
  401. {
  402. if(uroInhibitSave) return;
  403.  
  404. if (localStorage)
  405. {
  406. localStorage.UROverviewUROptions = uroGatherSettings('uroCtrlURs');
  407. localStorage.UROverviewMPOptions = uroGatherSettings('uroCtrlMPs');
  408. localStorage.UROverviewCameraOptions = uroGatherSettings('uroCtrlCameras');
  409. localStorage.UROverviewMiscOptions = uroGatherSettings('uroCtrlMisc');
  410. localStorage.UROverviewPlacesOptions = uroGatherSettings('uroCtrlPlaces');
  411. localStorage.UROverviewCamWatchList = uroGatherCamWatchList();
  412. localStorage.UROverviewSegWatchList = uroGatherSegWatchList();
  413. localStorage.UROverviewPlaceWatchList = uroGatherPlaceWatchList();
  414. localStorage.UROverviewCWLGroups = uroGatherCWLGroups();
  415. localStorage.UROverviewCurrentVersion = uroVersion;
  416. }
  417. }
  418.  
  419. function uroApplySettings(settings)
  420. {
  421. var options = settings.split(':');
  422. for(var optIdx=0;optIdx<options.length;optIdx++)
  423. {
  424. var fields = options[optIdx].split(',');
  425. if(fields[0].indexOf('_cb') == 0)
  426. {
  427. if(document.getElementById(fields[0]) != null)
  428. {
  429. document.getElementById(fields[0]).checked = (fields[1] == 'true');
  430. }
  431. }
  432. else if((fields[0].indexOf('_input') == 0)||(fields[0].indexOf('_text') == 0))
  433. {
  434. if(document.getElementById(fields[0]) != null) document.getElementById(fields[0]).value = fields[1];
  435. }
  436. }
  437. }
  438.  
  439.  
  440. function uroApplyCamWatchList()
  441. {
  442. var objects = localStorage.UROverviewCamWatchList.split(':');
  443. uroCamWatchObjects = new Array();
  444.  
  445. for(var objIdx=0;objIdx<objects.length;objIdx++)
  446. {
  447. var fields = objects[objIdx].split(',');
  448. // following two bits of code add in blank fields if the user has updated their copy of URO+ from an
  449. // older version which didn't include support for either of these field types
  450. // add default groupID field
  451. if(fields.length == 7)
  452. {
  453. fields.push(0);
  454. }
  455. // set default groupID value to 0 (no group)
  456. if(fields[7] == -1)
  457. {
  458. fields[7] = 0;
  459. }
  460.  
  461. // add default server field
  462. if(fields.length == 8)
  463. {
  464. fields.push('??');
  465. }
  466. // set default server value to unknown
  467. if(fields[8] == 0)
  468. {
  469. fields[8] = '??';
  470. }
  471.  
  472. uroCamWatchObjects.push(new uroCamWatchObj(true,fields[0],fields[1],fields[2],fields[3],fields[4],fields[5],fields[6],fields[7],fields[8]));
  473. }
  474. }
  475. function uroApplySegWatchList()
  476. {
  477. var objects = localStorage.UROverviewSegWatchList.split(':');
  478. uroSegWatchObjects = new Array();
  479.  
  480. for(var objIdx=0;objIdx<objects.length;objIdx++)
  481. {
  482. var fields = objects[objIdx].split(',');
  483. 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]));
  484. }
  485. }
  486. function uroApplyPlaceWatchList()
  487. {
  488. var objects = localStorage.UROverviewPlaceWatchList.split(':');
  489. uroPlaceWatchObjects = new Array();
  490.  
  491. for(var objIdx=0;objIdx<objects.length;objIdx++)
  492. {
  493. var fields = objects[objIdx].split(',');
  494. 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]));
  495. }
  496. }
  497.  
  498. function uroApplyCWLGroups()
  499. {
  500. var objects = localStorage.UROverviewCWLGroups.split(':');
  501. uroCWLGroups = new Array();
  502.  
  503. for(var objIdx=0;objIdx<objects.length;objIdx++)
  504. {
  505. var fields = objects[objIdx].split(',');
  506. if(fields.length < 2)
  507. {
  508. fields.push(false);
  509. }
  510. uroCWLGroups.push(new uroOWLGroupObj(fields[0],fields[1],(fields[2] == 'true')));
  511. }
  512. }
  513.  
  514. function uroLoadSettings()
  515. {
  516. var isNewInstall = true;
  517. var isUpgradeInstall = true;
  518. var notifyAboutCustomIcons = true;
  519. uroAddLog('loadSettings()');
  520. if (localStorage.UROverviewUROptions)
  521. {
  522. uroAddLog('recover UR tab settings');
  523. uroApplySettings(localStorage.UROverviewUROptions);
  524. isNewInstall = false;
  525. }
  526. if (localStorage.UROverviewCameraOptions)
  527. {
  528. uroAddLog('recover camera tab settings');
  529. uroApplySettings(localStorage.UROverviewCameraOptions);
  530. isNewInstall = false;
  531. }
  532.  
  533. if (localStorage.UROverviewMPOptions)
  534. {
  535. uroAddLog('recover MP tab settings');
  536. uroApplySettings(localStorage.UROverviewMPOptions);
  537. isNewInstall = false;
  538. }
  539.  
  540. if (localStorage.UROverviewPlacesOptions)
  541. {
  542. uroAddLog('recover Places tab settings');
  543. uroApplySettings(localStorage.UROverviewPlacesOptions);
  544. isNewInstall = false;
  545. }
  546. if (localStorage.UROverviewMiscOptions)
  547. {
  548. uroAddLog('recover misc tab settings');
  549. uroApplySettings(localStorage.UROverviewMiscOptions);
  550. isNewInstall = false;
  551. if(localStorage.UROverviewCurrentVersion)
  552. {
  553. notifyAboutCustomIcons = false;
  554. }
  555. else
  556. {
  557. if(uroGetCBChecked('_cbCustomRoadworksMarkers') == true) notifyAboutCustomIcons = false;
  558. if(uroGetCBChecked('_cbCustomConstructionMarkers')== true) notifyAboutCustomIcons = false;
  559. if(uroGetCBChecked('_cbCustomClosuresMarkers') == true) notifyAboutCustomIcons = false;
  560. if(uroGetCBChecked('_cbCustomEventsMarkers') == true) notifyAboutCustomIcons = false;
  561. if(uroGetCBChecked('_cbCustomNotesMarkers') == true) notifyAboutCustomIcons = false;
  562. }
  563. }
  564. if(localStorage.UROverviewCWLGroups)
  565. {
  566. uroAddLog('recover CWL groups');
  567. uroApplyCWLGroups();
  568. isNewInstall = false;
  569. }
  570. else
  571. {
  572. uroAddLog('set default CWL group');
  573. uroCWLGroups.push(new uroOWLGroupObj(0,'No group',false));
  574. }
  575.  
  576. if(localStorage.UROverviewCamWatchList)
  577. {
  578. uroAddLog('recover camera watchlist');
  579. uroApplyCamWatchList();
  580. uroGetCurrentCamWatchListObjects();
  581. isNewInstall = false;
  582. }
  583.  
  584. if(localStorage.UROverviewSegWatchList)
  585. {
  586. uroAddLog('recover segment watchlist');
  587. uroApplySegWatchList();
  588. uroGetCurrentSegWatchListObjects();
  589. isNewInstall = false;
  590. }
  591.  
  592. if(localStorage.UROverviewPlaceWatchList)
  593. {
  594. uroAddLog('recover places watchlist');
  595. uroApplyPlaceWatchList();
  596. //uroGetCurrentPlaceWatchListObjects();
  597. isNewInstall = false;
  598. }
  599. if(localStorage.UROverviewCurrentVersion)
  600. {
  601. uroAddLog('comparing install versions');
  602. if(localStorage.UROverviewCurrentVersion == uroVersion)
  603. {
  604. isUpgradeInstall = false;
  605. }
  606. }
  607. if(isNewInstall)
  608. {
  609. uroFirstTimerWelcomePack();
  610. }
  611. else if(isUpgradeInstall)
  612. {
  613. uroShowUpdateNotes();
  614. }
  615. if(notifyAboutCustomIcons)
  616. {
  617. uroAdvertiseCustomIcons();
  618. }
  619. uroInhibitSave = false;
  620. }
  621.  
  622. function uroSettingsToText()
  623. {
  624. var txtSettings = '';
  625. uroSaveSettings();
  626. if (localStorage.UROverviewUROptions)
  627. {
  628. txtSettings += '[UROverviewUROptions][len=' + localStorage.UROverviewUROptions.length + ']' + localStorage.UROverviewUROptions + '[END]';
  629. }
  630. if (localStorage.UROverviewCameraOptions)
  631. {
  632. txtSettings += '[UROverviewCameraOptions][len=' + localStorage.UROverviewCameraOptions.length + ']' + localStorage.UROverviewCameraOptions + '[END]';
  633. }
  634. if (localStorage.UROverviewMPOptions)
  635. {
  636. txtSettings += '[UROverviewMPOptions][len=' + localStorage.UROverviewMPOptions.length + ']' + localStorage.UROverviewMPOptions + '[END]';
  637. }
  638. if (localStorage.UROverviewMiscOptions)
  639. {
  640. txtSettings += '[UROverviewMiscOptions][len=' + localStorage.UROverviewMiscOptions.length + ']' + localStorage.UROverviewMiscOptions + '[END]';
  641. }
  642. if (localStorage.UROverviewCamWatchList)
  643. {
  644. txtSettings += '[UROverviewCamWatchList][len=' + localStorage.UROverviewCamWatchList.length + ']' + localStorage.UROverviewCamWatchList + '[END]';
  645. }
  646. if (localStorage.UROverviewSegWatchList)
  647. {
  648. txtSettings += '[UROverviewSegWatchList][len=' + localStorage.UROverviewSegWatchList.length + ']' + localStorage.UROverviewSegWatchList + '[END]';
  649. }
  650. if (localStorage.UROverviewPlaceWatchList)
  651. {
  652. txtSettings += '[UROverviewPlaceWatchList][len=' + localStorage.UROverviewPlaceWatchList.length + ']' + localStorage.UROverviewPlaceWatchList + '[END]';
  653. }
  654. if (localStorage.UROverviewCWLGroups)
  655. {
  656. txtSettings += '[UROverviewCWLGroups][len=' + localStorage.UROverviewCWLGroups.length + ']' + localStorage.UROverviewCWLGroups + '[END]';
  657. }
  658. if (localStorage.UROverviewPlacesOptions)
  659. {
  660. txtSettings += '[UROverviewPlacesOptions][len=' + localStorage.UROverviewPlacesOptions.length + ']' + localStorage.UROverviewPlacesOptions + '[END]';
  661. }
  662. document.getElementById('_txtSettings').value = txtSettings;
  663. document.getElementById('_txtSettings').focus();
  664. document.getElementById('_txtSettings').select();
  665. }
  666.  
  667. function uroTextToSettings()
  668. {
  669. var txtSettings = '';
  670. txtSettings = uroGetElmValue('_txtSettings');
  671. if(txtSettings.indexOf('[END]') == -1) return;
  672. var subText = txtSettings.split('[END]');
  673. for(var i=0;i<subText.length;i++)
  674. {
  675. var bPos = subText[i].indexOf(']');
  676. if(bPos != -1)
  677. {
  678. var settingID = subText[i].substr(1,bPos-1);
  679. subText[i] = subText[i].substr(bPos+1);
  680. bPos = subText[i].indexOf(']');
  681. if(bPos != -1)
  682. {
  683. var settingLength = subText[i].substr(5,bPos-5);
  684. subText[i] = subText[i].substr(bPos+1);
  685. if(subText[i].length == settingLength)
  686. {
  687. if(settingID == 'UROverviewCamWatchList') localStorage.UROverviewCamWatchList = subText[i];
  688. if(settingID == 'UROverviewCWLGroups') localStorage.UROverviewCWLGroups = subText[i];
  689. if(settingID == 'UROverviewUROptions') localStorage.UROverviewUROptions = subText[i];
  690. if(settingID == 'UROverviewCameraOptions') localStorage.UROverviewCameraOptions = subText[i];
  691. if(settingID == 'UROverviewMPOptions') localStorage.UROverviewMPOptions = subText[i];
  692. if(settingID == 'UROverviewMiscOptions') localStorage.UROverviewMiscOptions = subText[i];
  693. if(settingID == 'UROverviewPlacesOptions') localStorage.UROverviewPlacesOptions = subText[i];
  694. }
  695. }
  696. }
  697. }
  698. uroLoadSettings();
  699. }
  700.  
  701. function uroClearSettingsText()
  702. {
  703. document.getElementById('_txtSettings').value = '';
  704. }
  705.  
  706.  
  707. function uroDateToDays(dateToConvert)
  708. {
  709. var dateNow = new Date();
  710. var elapsedSinceEpoch = dateNow.getTime();
  711. var elapsedSinceEvent = elapsedSinceEpoch - dateToConvert;
  712. dateNow.setHours(0);
  713. dateNow.setMinutes(0);
  714. dateNow.setSeconds(0);
  715. dateNow.setMilliseconds(0);
  716. var elapsedSinceMidnight = elapsedSinceEpoch - dateNow.getTime();
  717. if(elapsedSinceEvent < elapsedSinceMidnight)
  718. {
  719. // event occurred today...
  720. return 0;
  721. }
  722. else
  723. {
  724. // event occurred at some point prior to midnight this morning, so return a minimum value of 1...
  725. return 1 + Math.floor((elapsedSinceEvent - elapsedSinceMidnight) / 86400000);
  726. }
  727. }
  728.  
  729. function uroGetURAge(urObj,ageType)
  730. {
  731. if(ageType == 0)
  732. {
  733. if((urObj.attributes.driveDate == null)||(urObj.attributes.driveDate == 0)) return -1;
  734. return uroDateToDays(urObj.attributes.driveDate);
  735. }
  736. else if(ageType == 1)
  737. {
  738. if((urObj.attributes.resolvedOn == null)||(urObj.attributes.resolvedOn == 0)) return -1;
  739. return uroDateToDays(urObj.attributes.resolvedOn);
  740. }
  741. else
  742. {
  743. return -1;
  744. }
  745. }
  746.  
  747. function uroGetPURAge(purObj)
  748. {
  749. if(purObj.attributes.venueUpdateRequests[0].attributes.dateAdded != null)
  750. {
  751. return uroDateToDays(purObj.attributes.venueUpdateRequests[0].attributes.dateAdded);
  752. }
  753. else
  754. {
  755. return -1;
  756. }
  757. }
  758.  
  759. function uroGetCameraAge(camObj, mode)
  760. {
  761. if(mode == 0)
  762. {
  763. if(camObj.attributes.updatedOn == null) return -1;
  764. return uroDateToDays(camObj.attributes.updatedOn);
  765. }
  766. if(mode == 1)
  767. {
  768. if(camObj.attributes.createdOn == null) return -1;
  769. return uroDateToDays(camObj.attributes.createdOn);
  770. }
  771. }
  772.  
  773. function uroGetCommentAge(commentObj)
  774. {
  775. if(commentObj.createdOn == null) return -1;
  776. return uroDateToDays(commentObj.createdOn);
  777. }
  778.  
  779. function uroParseDaysAgo(days)
  780. {
  781. if(days == 0) return 'today';
  782. else if(days == 1) return '1 day ago';
  783. else return days+' days ago';
  784. }
  785.  
  786. function uroIsCameraSpeedValid(camObj)
  787. {
  788. // returns 1 if the entered speed converts correctly into a multiple of 10MPH
  789. // returns -1 if the entered speed does not convert correctly
  790. // returns 0 if no speed data is present, or if the entered speed is 0
  791. if(camObj.attributes.speed != null)
  792. {
  793. var speed = Math.round(camObj.attributes.speed /1.609);
  794. if(speed == 0) return 0;
  795. else if(speed % 10 == 0) return 1;
  796. else return -1;
  797. }
  798. else return 0;
  799. }
  800.  
  801.  
  802. // --------------------------------------------------------------------------------------------------------------------
  803. // AREA FRIENDLYNAME STUFF
  804. // --------------------------------------------------------------------------------------------------------------------
  805. function uroAFNObj(fName, area, server)
  806. {
  807. this.fName = fName;
  808. this.area = area;
  809. this.server = server;
  810. }
  811.  
  812. function uroReplaceAreaNames()
  813. {
  814. if(uroFriendlyAreaNames.length == 0)
  815. {
  816. return;
  817. }
  818. if(document.getElementById('sidepanel-areas') == undefined)
  819. {
  820. return;
  821. }
  822. if(document.getElementById('sidepanel-areas').getElementsByClassName('result-list')[0].id == "friendlyNamed")
  823. {
  824. return;
  825. }
  826. var areaCount = document.getElementById('sidepanel-areas').getElementsByClassName('result-list')[0].children.length;
  827. if(areaCount == 0)
  828. {
  829. return;
  830. }
  831.  
  832. var localisedManagedArea = I18n.translations[I18n.locale].user.areas.managed_area;
  833. for(loop=0; loop < areaCount; loop++)
  834. {
  835. var title = document.getElementById('sidepanel-areas').getElementsByClassName('result-list')[0].children[loop].getElementsByTagName('p')[0].innerHTML;
  836. if(title == localisedManagedArea)
  837. {
  838. var area = document.getElementById('sidepanel-areas').getElementsByClassName('result-list')[0].children[loop].getElementsByTagName('p')[1].getElementsByTagName('span')[0].innerHTML;
  839. area = parseFloat(area.split(' ')[0]);
  840. for(fnIdx=0; fnIdx < uroFriendlyAreaNames.length; fnIdx++)
  841. {
  842. fnObj = uroFriendlyAreaNames[fnIdx];
  843. if((fnObj.area == area) && (fnObj.server == W.location.code))
  844. {
  845. document.getElementById('sidepanel-areas').getElementsByClassName('result-list')[0].children[loop].getElementsByTagName('p')[0].innerHTML = fnObj.fName +' <i>('+localisedManagedArea+')</i>';
  846. break;
  847. }
  848. }
  849. }
  850. }
  851. document.getElementById('sidepanel-areas').getElementsByClassName('result-list')[0].id = "friendlyNamed";
  852. }
  853.  
  854. function uroAreaNameTest()
  855. {
  856. uroFriendlyAreaNames = new Array();
  857. uroFriendlyAreaNames.push(new uroAFNObj('London',710.93,'row'));
  858. uroFriendlyAreaNames.push(new uroAFNObj('Mexico City',2328.19,'row'));
  859. uroFriendlyAreaNames.push(new uroAFNObj('Shetlands',2618.37,'row'));
  860. uroFriendlyAreaNames.push(new uroAFNObj('Los Angeles',8151.2,'usa'));
  861. }
  862.  
  863. // --------------------------------------------------------------------------------------------------------------------
  864. // WATCHLIST STUFF
  865. // --------------------------------------------------------------------------------------------------------------------
  866.  
  867. // Generic Functions
  868. function uroTypeCast(varin)
  869. {
  870. if(varin == "null") return null;
  871. if(typeof varin == "string") return parseInt(varin);
  872. return varin;
  873. }
  874. function uroOWLGroupObj(groupID, groupName, groupCollapsed)
  875. {
  876. groupID = uroTypeCast(groupID);
  877. this.groupID = groupID;
  878. this.groupName = groupName;
  879. this.groupCount = 0;
  880. this.groupCollapsed = groupCollapsed;
  881. }
  882.  
  883. // Camera Functions
  884. function uroCamWatchObjCheckProps(type, azymuth, speed, validated, lat, lon)
  885. {
  886. if(type != null) type = uroTypeCast(type);
  887. if(azymuth != null) azymuth = uroTruncate(uroTypeCast(azymuth)%360);
  888. if(speed != null) speed = uroTruncate(uroTypeCast(speed));
  889. if(typeof validated == "string") validated = (validated == "true");
  890. if(lat != null) lat = uroTruncate(uroTypeCast(lat));
  891. if(lon != null) lon = uroTruncate(uroTypeCast(lon));
  892.  
  893. this.type = type;
  894. this.azymuth = azymuth;
  895. this.speed = speed;
  896. this.validated = validated;
  897. this.lat = lat;
  898. this.lon = lon;
  899. }
  900. function uroCamWatchObj(persistent, fid, lon, lat, type, azymuth, speed, validated, groupID, server)
  901. {
  902. fid = uroTypeCast(fid);
  903. groupID = uroTypeCast(groupID);
  904. if(typeof persistent == "string") persistent = (persistent == "true");
  905.  
  906. this.fid = fid;
  907. this.persistent = persistent;
  908. this.loaded = false;
  909. this.server = server;
  910. this.groupID = groupID;
  911. this.watch = new uroCamWatchObjCheckProps(type, azymuth, speed, validated, lat, lon);
  912. this.current = new uroCamWatchObjCheckProps(null, null, null, null, null, null);
  913. }
  914. function uroCamDataChanged(idx)
  915. {
  916. camObj = uroCamWatchObjects[idx];
  917. if(camObj.loaded == false) return false;
  918. if(camObj.current.type != camObj.watch.type) return true;
  919. if(camObj.current.azymuth != camObj.watch.azymuth) return true;
  920. if(camObj.current.speed != camObj.watch.speed) return true;
  921. if(camObj.current.validated != camObj.watch.validated) return true;
  922. if(camObj.current.lat != camObj.watch.lat) return true;
  923. if(camObj.current.lon != camObj.watch.lon) return true;
  924. return false;
  925. }
  926. function uroIsCamOnWatchList(fid)
  927. {
  928. for(var loop=0;loop<uroCamWatchObjects.length;loop++)
  929. {
  930. if(uroCamWatchObjects[loop].fid == fid) return loop;
  931. }
  932. return -1;
  933. }
  934. function uroAddCurrentCamWatchData(idx, lat, lon, type, azymuth, speed, validated, server)
  935. {
  936. camObj = uroCamWatchObjects[idx];
  937. camObj.loaded = true;
  938. camObj.server = server;
  939. camObj.current = new uroCamWatchObjCheckProps(type, azymuth, speed, validated, lat, lon)
  940. return(uroCamDataChanged(idx));
  941. }
  942. function uroAddCamToWatchList()
  943. {
  944. if(uroIsCamOnWatchList(uroShownFID) == -1)
  945. {
  946. camObj = W.model.cameras.objects[uroShownFID];
  947. 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));
  948. 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);
  949. uroAddLog('added camera '+uroShownFID+' to watchlist');
  950. uroOWLUpdateHTML();
  951. }
  952. }
  953. function uroRemoveCamFromWatchList()
  954. {
  955. camidx = uroIsCamOnWatchList(uroShownFID);
  956. if(camidx != -1)
  957. {
  958. uroCamWatchObjects.splice(camidx,1);
  959. uroAddLog('removed camera '+uroShownFID+' from watchlist');
  960. uroOWLUpdateHTML();
  961. }
  962. }
  963. function uroUpdateCamWatchList()
  964. {
  965. var camIdx = uroIsCamOnWatchList(uroShownFID);
  966. if(camIdx != -1)
  967. {
  968. var camObj = W.model.cameras.objects[uroShownFID];
  969. uroCamWatchObjects[camIdx].watch = new uroCamWatchObjCheckProps(camObj.attributes.type, camObj.attributes.azymuth, camObj.attributes.speed, camObj.attributes.validated, camObj.geometry.y, camObj.geometry.x);
  970. }
  971. }
  972. function uroClearCamWatchList()
  973. {
  974. if(confirm('Removing all cameras from the OWL cannot be undone\nAre you sure you want to do this?') == true)
  975. {
  976. uroCamWatchObjects = new Array();
  977. uroOWLUpdateHTML();
  978. }
  979. }
  980. function uroRetrieveCameras(lat, lon)
  981. {
  982. var camPos = new OpenLayers.LonLat();
  983. var camChanged = false;
  984. camPos.lon = lon;
  985. camPos.lat = lat;
  986. camPos.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326"));
  987.  
  988. var camURL = 'https://' + document.location.host;
  989. camURL += Waze.Config.api_base;
  990. camURL += '/Features?language=en&cameras=true&bbox=';
  991. var latl = camPos.lat - 0.25;
  992. var latu = camPos.lat + 0.25;
  993. var lonl = camPos.lon - 0.25;
  994. var lonr = camPos.lon + 0.25;
  995. camURL += lonl+','+latl+','+lonr+','+latu;
  996. uroAddLog('retrieving camera data around '+camPos.lon+','+camPos.lat);
  997.  
  998. camReq = new XMLHttpRequest();
  999. camReq.open('GET',camURL,false);
  1000. try
  1001. {
  1002. camReq.send();
  1003. uroAddLog('response '+camReq.status+' received');
  1004. if (camReq.status === 200)
  1005. {
  1006. camData = JSON.parse(camReq.responseText);
  1007. for(var camIdx = 0; camIdx < camData.cameras.objects.length; camIdx++)
  1008. {
  1009. camObj = camData.cameras.objects[camIdx];
  1010. var listIdx = uroIsCamOnWatchList(camObj.id);
  1011. if(listIdx != -1)
  1012. {
  1013. camPos.lon = camObj.geometry.coordinates[0];
  1014. camPos.lat = camObj.geometry.coordinates[1];
  1015. camPos.transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913"));
  1016. camPos.lon = uroTruncate(camPos.lon);
  1017. camPos.lat = uroTruncate(camPos.lat);
  1018. camChanged |= uroAddCurrentCamWatchData(listIdx, camPos.lat, camPos.lon, camObj.type, camObj.azymuth, camObj.speed, camObj.validated, W.location.code);
  1019. }
  1020. else if(camObj.validated == false)
  1021. {
  1022.  
  1023. }
  1024. }
  1025. }
  1026. else
  1027. {
  1028. uroAddLog('request failed (status != 200)');
  1029. }
  1030. }
  1031. catch(err)
  1032. {
  1033. uroAddLog('camera load request failed (exception '+err+' caught)');
  1034. }
  1035. return camChanged;
  1036. }
  1037. function uroGetCurrentCamWatchListObjects()
  1038. {
  1039. var camChanged = false;
  1040. var camsChanged = new Array();
  1041. var camsDeleted = new Array();
  1042. for(var camidx=0;camidx<uroCamWatchObjects.length;camidx++)
  1043. {
  1044. camObj = uroCamWatchObjects[camidx];
  1045. if((camObj.loaded == false) && ((camObj.server == W.location.code) || (camObj.server == '??')))
  1046. {
  1047. if(typeof W.model.cameras.objects[camObj.fid] == 'object')
  1048. {
  1049. if(W.model.cameras.objects[camObj.fid].state != "Delete")
  1050. {
  1051. wazeObj = W.model.cameras.objects[camObj.fid];
  1052. camChanged |= uroAddCurrentCamWatchData(camidx, wazeObj.geometry.y, wazeObj.geometry.x, wazeObj.attributes.type, wazeObj.attributes.azymuth, wazeObj.attributes.speed, wazeObj.attributes.validated);
  1053. }
  1054. else
  1055. {
  1056. camChanged |= uroRetrieveCameras(camObj.watch.lat, camObj.watch.lon);
  1057. }
  1058. }
  1059. else
  1060. {
  1061. camChanged |= uroRetrieveCameras(camObj.watch.lat, camObj.watch.lon);
  1062. }
  1063. }
  1064. }
  1065. if(camChanged)
  1066. {
  1067. for(var camidx=0;camidx<uroCamWatchObjects.length;camidx++)
  1068. {
  1069. if(uroCamDataChanged(camidx))
  1070. {
  1071. camsChanged.push(uroCamWatchObjects[camidx]);
  1072. }
  1073. }
  1074. }
  1075.  
  1076. for(var camidx=0;camidx<uroCamWatchObjects.length;camidx++)
  1077. {
  1078. camObj = uroCamWatchObjects[camidx];
  1079. if((camObj.loaded == false) && (camObj.server == W.location.code))
  1080. {
  1081. camsDeleted.push(camObj);
  1082. }
  1083. }
  1084.  
  1085. if((camsChanged.length > 0) || (camsDeleted.length > 0))
  1086. {
  1087. var alertStr = 'Camera WatchList Alert!!!\r\n';
  1088. for(var camidx=0;camidx<camsChanged.length;camidx++)
  1089. {
  1090. alertStr += 'Camera ID '+camsChanged[camidx].fid+' in group "'+uroFindCWLGroupByIdx(camsChanged[camidx].groupID)+'" has been changed\r\n';
  1091. }
  1092. for(var camidx=0;camidx<camsDeleted.length;camidx++)
  1093. {
  1094. alertStr += 'Camera ID '+camsDeleted[camidx].fid+' in group "'+uroFindCWLGroupByIdx(camsDeleted[camidx].groupID)+'" has been deleted\r\n';
  1095. }
  1096. alert(alertStr);
  1097. }
  1098. }
  1099. function uroClearDeletedCameras()
  1100. {
  1101. for(var camidx=uroCamWatchObjects.length-1;camidx>=0;camidx--)
  1102. {
  1103. if(uroCamWatchObjects[camidx].loaded == false)
  1104. {
  1105. uroShownFID = uroCamWatchObjects[camidx].fid;
  1106. uroRemoveCamFromWatchList();
  1107. }
  1108. }
  1109. }
  1110. function uroClearUnknownServerCameras()
  1111. {
  1112. var confirmMsg = 'Cameras with an unknown server cannot be automatically verified by URO+.\n';
  1113. 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';
  1114. confirmMsg += 'If the cameras then continue to show up as an unknown server, it is safe to delete them...\n\n';
  1115. confirmMsg += 'Do you still wish to proceed with deleting all unknown server cameras?';
  1116. if(confirm(confirmMsg) == true)
  1117. {
  1118. for(var camidx=uroCamWatchObjects.length-1;camidx>=0;camidx--)
  1119. {
  1120. if(uroCamWatchObjects[camidx].server == '??')
  1121. {
  1122. uroShownFID = uroCamWatchObjects[camidx].fid;
  1123. uroRemoveCamFromWatchList();
  1124. }
  1125. }
  1126. }
  1127. }
  1128. function uroRescanCamWatchList()
  1129. {
  1130. for(var camidx=0;camidx<uroCamWatchObjects.length;camidx++)
  1131. {
  1132. uroCamWatchObjects[camidx].loaded = false;
  1133. }
  1134. uroGetCurrentCamWatchListObjects();
  1135. uroOWLUpdateHTML();
  1136. }
  1137. function uroGotoCam()
  1138. {
  1139. var camidx = this.id.substr(13);
  1140. var camPos = new OpenLayers.LonLat();
  1141. camPos.lon = uroCamWatchObjects[camidx].watch.lon;
  1142. camPos.lat = uroCamWatchObjects[camidx].watch.lat;
  1143. W.map.setCenter(camPos,4);
  1144. W.map.camerasLayer.setVisibility(true);
  1145. return false;
  1146. }
  1147. function uroSetCamGroup()
  1148. {
  1149. var camidx = this.id.substr(13);
  1150. return false;
  1151. }
  1152.  
  1153. // Segment Functions
  1154. function uroSegWatchObjCheckProps(left, right, bottom, top, fromNode, toNode, fwdDir, revDir, length, level, rank, roadType, updatedOn)
  1155. {
  1156. if(left != null) left = uroTruncate(uroTypeCast(left));
  1157. if(right != null) right = uroTruncate(uroTypeCast(right));
  1158. if(bottom != null) bottom = uroTruncate(uroTypeCast(bottom));
  1159. if(top != null) top = uroTruncate(uroTypeCast(top));
  1160. if(fromNode != null) fromNode = uroTypeCast(fromNode);
  1161. if(toNode != null) toNode = uroTypeCast(toNode);
  1162. if(fwdDir != null) fwdDir = uroTypeCast(fwdDir);
  1163. if(revDir != null) revDir = uroTypeCast(revDir);
  1164. if(length != null) length = uroTypeCast(length);
  1165. if(level != null) level = uroTypeCast(level);
  1166. if(rank != null) rank = uroTypeCast(rank);
  1167. if(roadType != null) roadType = uroTypeCast(roadType);
  1168. if(updatedOn != null) updatedOn = uroTypeCast(updatedOn);
  1169.  
  1170. this.left = left;
  1171. this.right = right;
  1172. this.bottom = bottom;
  1173. this.top = top;
  1174. this.fromNode = fromNode;
  1175. this.toNode = toNode;
  1176. this.fwdDir = fwdDir;
  1177. this.revDir = revDir;
  1178. this.length = length;
  1179. this.level = level;
  1180. this.rank = rank;
  1181. this.roadType = roadType;
  1182. this.updatedOn = updatedOn;
  1183. }
  1184. function uroSegWatchObj(persistent, fid, left, right, bottom, top, fromNode, toNode, fwdDir, revDir, length, level, rank, roadType, updatedOn, groupID, server)
  1185. {
  1186. fid = uroTypeCast(fid);
  1187. groupID = uroTypeCast(groupID);
  1188. if(typeof persistent == "string") persistent = (persistent == "true");
  1189.  
  1190. this.fid = fid;
  1191. this.persistent = persistent;
  1192. this.loaded = false;
  1193. this.server = server;
  1194. this.groupID = groupID;
  1195. this.watch = new uroSegWatchObjCheckProps(left, right, bottom, top, fromNode, toNode, fwdDir, revDir, length, level, rank, roadType, updatedOn);
  1196. this.current = new uroSegWatchObjCheckProps(null, null, null, null, null, null, null, null, null, null, null, null, null);
  1197. }
  1198. function uroSegDataChanged(idx)
  1199. {
  1200. segObj = uroSegWatchObjects[idx];
  1201. if(segObj.loaded == false) return false;
  1202. if(segObj.current.left != segObj.watch.left) return true;
  1203. if(segObj.current.right != segObj.watch.right) return true;
  1204. if(segObj.current.bottom != segObj.watch.bottom) return true;
  1205. if(segObj.current.top != segObj.watch.top) return true;
  1206. if(segObj.current.fromNode != segObj.watch.fromNode) return true;
  1207. if(segObj.current.toNode != segObj.watch.toNode) return true;
  1208. if(segObj.current.fwdDir != segObj.watch.fwdDir) return true;
  1209. if(segObj.current.revDir != segObj.watch.revDir) return true;
  1210. if(segObj.current.length != segObj.watch.length) return true;
  1211. if(segObj.current.level != segObj.watch.level) return true;
  1212. if(segObj.current.rank != segObj.watch.rank) return true;
  1213. if(segObj.current.roadType != segObj.watch.roadType) return true;
  1214. if(segObj.current.updatedOn != segObj.watch.updatedOn) return true;
  1215. return false;
  1216. }
  1217. function uroIsSegOnWatchList(fid)
  1218. {
  1219. for(var loop=0;loop<uroSegWatchObjects.length;loop++)
  1220. {
  1221. if(uroSegWatchObjects[loop].fid == fid) return loop;
  1222. }
  1223. return -1;
  1224. }
  1225. function uroAddCurrentSegWatchData(idx, left, right, bottom, top, fromNode, toNode, fwdDir, revDir, length, level, rank, roadType, updatedOn, server)
  1226. {
  1227. segObj = uroSegWatchObjects[idx];
  1228. segObj.loaded = true;
  1229. segObj.server = server;
  1230. segObj.current = new uroSegWatchObjCheckProps(left, right, bottom, top, fromNode, toNode, fwdDir, revDir, length, level, rank, roadType, updatedOn);
  1231. return(uroSegDataChanged(idx));
  1232. }
  1233. function uroClearSegWatchList()
  1234. {
  1235. if(confirm('Removing all segments from the OWL cannot be undone\nAre you sure you want to do this?') == true)
  1236. {
  1237. uroSegWatchObjects = new Array();
  1238. uroOWLUpdateHTML();
  1239. }
  1240. }
  1241. function uroAddUpdateSegWatchList()
  1242. {
  1243. selectedCount = W.selectionManager.selectedItems.length;
  1244. if(selectedCount == 0)
  1245. {
  1246. return;
  1247. }
  1248. for(var loop=0;loop < selectedCount; loop++)
  1249. {
  1250. var segObj = W.selectionManager.selectedItems[loop].model.attributes;
  1251. var fid = segObj.id;
  1252. var idx = uroIsSegOnWatchList(fid);
  1253. if(idx != -1)
  1254. {
  1255. 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);
  1256. uroAddLog('updated watchlist details for segment '+fid);
  1257. }
  1258. else
  1259. {
  1260. 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));
  1261. 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);
  1262. uroAddLog('added segment '+fid+' to watchlist');
  1263. }
  1264. }
  1265. //uroOWLUpdateHTML();
  1266. }
  1267. function uroRemoveSegFromWatchList()
  1268. {
  1269. selectedCount = W.selectionManager.selectedItems.length;
  1270. if(selectedCount == 0)
  1271. {
  1272. return;
  1273. }
  1274. for(var loop=0;loop < selectedCount; loop++)
  1275. {
  1276. var fid = W.selectionManager.selectedItems[loop].model.attributes.id;
  1277. var idx = uroIsSegOnWatchList(fid);
  1278. if(idx != -1)
  1279. {
  1280. uroSegWatchObjects.splice(idx,1);
  1281. uroAddLog('removed segment '+fid+' from watchlist');
  1282. }
  1283. }
  1284. //uroOWLUpdateHTML();
  1285. }
  1286. function uroRetrieveSegments(lat, lon)
  1287. {
  1288. var pos = new OpenLayers.LonLat();
  1289. var changed = false;
  1290. pos.lon = lon;
  1291. pos.lat = lat;
  1292. pos.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326"));
  1293. var URL = 'https://' + document.location.host;
  1294. URL += Waze.Config.api_base;
  1295. URL += '/Features?roadTypes=1%2C2%2C3%2C4%2C5%2C6%2C7%2C8%2C9%2C10%2C11%2C12%2C13%2C14%2C15%2C16%2C17%2C18%2C19%2C20%2C21';
  1296. URL += '&bbox=';
  1297. var latl = pos.lat - 0.25;
  1298. var latu = pos.lat + 0.25;
  1299. var lonl = pos.lon - 0.25;
  1300. var lonr = pos.lon + 0.25;
  1301. URL += lonl+','+latl+','+lonr+','+latu;
  1302. URL += '&language=en';
  1303. uroAddLog('retrieving segment data around '+pos.lon+','+pos.lat);
  1304.  
  1305. req = new XMLHttpRequest();
  1306. req.open('GET',URL,false);
  1307. try
  1308. {
  1309. req.send();
  1310. uroAddLog('response '+req.status+' received');
  1311. if (req.status === 200)
  1312. {
  1313. data = JSON.parse(req.responseText);
  1314. for(var idx = 0; idx < data.segments.objects.length; idx++)
  1315. {
  1316. obj = data.segments.objects[idx];
  1317. var listIdx = uroIsSegOnWatchList(obj.id);
  1318. if(listIdx != -1)
  1319. {
  1320. //pos.lon = obj.geometry.coordinates[0];
  1321. //pos.lat = obj.geometry.coordinates[1];
  1322. //pos.transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913"));
  1323. //camPos.lon = uroTruncate(camPos.lon);
  1324. //camPos.lat = uroTruncate(camPos.lat);
  1325. //camChanged |= uroAddCurrentCamWatchData(listIdx, camPos.lat, camPos.lon, camObj.type, camObj.azymuth, camObj.speed, camObj.validated, W.location.code);
  1326. }
  1327. else if(obj.validated == false)
  1328. {
  1329.  
  1330. }
  1331. }
  1332. }
  1333. else
  1334. {
  1335. uroAddLog('request failed (status != 200)');
  1336. }
  1337. }
  1338. catch(err)
  1339. {
  1340. uroAddLog('segment load request failed (exception '+err+' caught)');
  1341. }
  1342. return changed;
  1343. }
  1344. function uroGetCurrentSegWatchListObjects()
  1345. {
  1346. var segChanged = false;
  1347. var segsChanged = new Array();
  1348. var segsDeleted = new Array();
  1349. for(var idx=0;idx<uroSegWatchObjects.length;idx++)
  1350. {
  1351. segObj = uroSegWatchObjects[idx];
  1352. if((segObj.loaded == false) && ((segObj.server == W.location.code) || (segObj.server == '??')))
  1353. {
  1354. var segLat = (segObj.watch.top + segObj.watch.bottom) / 2;
  1355. var segLon = (segObj.watch.right + segObj.watch.left) / 2;
  1356. if(typeof W.model.segments.objects[segObj.fid] == 'object')
  1357. {
  1358. if(W.model.segments.objects[segObj.fid].state != "Delete")
  1359. {
  1360. wazeObj = W.model.segments.objects[segObj.fid];
  1361. 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);
  1362. }
  1363. else
  1364. {
  1365. segChanged |= uroRetrieveSegments(segLat, segLon);
  1366. }
  1367. }
  1368. else
  1369. {
  1370. segChanged |= uroRetrieveSegments(segLat, segLon);
  1371. }
  1372. }
  1373. }
  1374. if(segChanged)
  1375. {
  1376. for(var idx=0;idx<uroSegWatchObjects.length;idx++)
  1377. {
  1378. if(uroSegDataChanged(idx))
  1379. {
  1380. segsChanged.push(uroSegWatchObjects[idx]);
  1381. }
  1382. }
  1383. }
  1384.  
  1385. for(var idx=0;idx<uroSegWatchObjects.length;idx++)
  1386. {
  1387. segObj = uroSegWatchObjects[idx];
  1388. if((segObj.loaded == false) && (segObj.server == W.location.code))
  1389. {
  1390. segsDeleted.push(segObj);
  1391. }
  1392. }
  1393.  
  1394. if((segsChanged.length > 0) || (segsDeleted.length > 0))
  1395. {
  1396. var alertStr = 'Segment WatchList Alert!!!\r\n';
  1397. for(var idx=0;idx<segsChanged.length;idx++)
  1398. {
  1399. alertStr += 'Segment ID '+segsChanged[idx].fid+' in group "'+uroFindCWLGroupByIdx(segsChanged[idx].groupID)+'" has been changed\r\n';
  1400. }
  1401. for(var idx=0;idx<segsDeleted.length;idx++)
  1402. {
  1403. alertStr += 'Segment ID '+segsDeleted[idx].fid+' in group "'+uroFindCWLGroupByIdx(segsDeleted[idx].groupID)+'" has been deleted\r\n';
  1404. }
  1405. alert(alertStr);
  1406. }
  1407. }
  1408.  
  1409. // Places Functions
  1410. function uroPlaceWatchObjCheckProps(left, right, bottom, top, name, imageCount, residential, updatedOn)
  1411. {
  1412. if(left != null) left = uroTruncate(uroTypeCast(left));
  1413. if(right != null) right = uroTruncate(uroTypeCast(right));
  1414. if(bottom != null) bottom = uroTruncate(uroTypeCast(bottom));
  1415. if(top != null) top = uroTruncate(uroTypeCast(top));
  1416. if(imageCount != null) imageCount = uroTypeCast(imageCount);
  1417. if(typeof residential == "string") residential = (residential == "true");
  1418. if(updatedOn != null) updatedOn = uroTypeCast(updatedOn);
  1419.  
  1420. this.left = left;
  1421. this.right = right;
  1422. this.bottom = bottom;
  1423. this.top = top;
  1424. this.name = name;
  1425. this.imageCount = imageCount;
  1426. this.residential = residential;
  1427. this.updatedOn = updatedOn;
  1428. }
  1429. function uroPlaceWatchObj(persistent, fid, left, right, bottom, top, imageCount, name, residential, updatedOn, groupID, server)
  1430. {
  1431. groupID = uroTypeCast(groupID);
  1432. if(typeof persistent == "string") persistent = (persistent == "true");
  1433.  
  1434. this.fid = fid;
  1435. this.persistent = persistent;
  1436. this.loaded = false;
  1437. this.server = server;
  1438. this.groupID = groupID;
  1439. this.watch = new uroPlaceWatchObjCheckProps(left, right, bottom, top, name, imageCount, residential, updatedOn);
  1440. this.current = new uroPlaceWatchObjCheckProps(null, null, null, null, null, null, null, null);
  1441. }
  1442. function uroPlaceDataChanged(idx)
  1443. {
  1444. placeObj = uroPlaceWatchObjects[idx];
  1445. if(placeObj.loaded == false) return false;
  1446. if(placeObj.current.left != placeObj.watch.left) return true;
  1447. if(placeObj.current.right != placeObj.watch.right) return true;
  1448. if(placeObj.current.bottom != placeObj.watch.bottom) return true;
  1449. if(placeObj.current.top != placeObj.watch.top) return true;
  1450. if(placeObj.current.name != placeObj.watch.name) return true;
  1451. if(placeObj.current.imageCount != placeObj.watch.imageCount) return true;
  1452. if(placeObj.current.residential != placeObj.watch.residential) return true;
  1453. if(placeObj.current.updatedOn != placeObj.watch.updatedOn) return true;
  1454. return false;
  1455. }
  1456. function uroIsPlaceOnWatchList(fid)
  1457. {
  1458. for(var loop=0;loop<uroPlaceWatchObjects.length;loop++)
  1459. {
  1460. if(uroPlaceWatchObjects[loop].fid == fid) return loop;
  1461. }
  1462. return -1;
  1463. }
  1464. function uroClearPlaceWatchList()
  1465. {
  1466. if(confirm('Removing all places from the OWL cannot be undone\nAre you sure you want to do this?') == true)
  1467. {
  1468. uroPlaceWatchObjects = new Array();
  1469. uroOWLUpdateHTML();
  1470. }
  1471. }
  1472.  
  1473.  
  1474.  
  1475. function uroTruncate(val)
  1476. {
  1477. if(val == null) return val;
  1478. if(val < 0) return Math.ceil(val);
  1479. return Math.floor(val);
  1480. }
  1481. function uroHighlightCWLEntry()
  1482. {
  1483. this.style.backgroundColor = '#FFFFAA';
  1484. return false;
  1485. }
  1486. function uroUnhighlightCWLEntry()
  1487. {
  1488. var camidx = this.id.substr(8);
  1489. var changed = uroCamDataChanged(camidx);
  1490. var deleted = (uroCamWatchObjects[camidx].loaded == false);
  1491.  
  1492. if(uroCamWatchObjects[camidx].server != W.location.code)
  1493. {
  1494. if(uroCamWatchObjects[camidx].server == '??') this.style.backgroundColor = '#A0A0A0';
  1495. else this.style.backgroundColor = '#AAFFAA';
  1496. }
  1497. else if(changed) this.style.backgroundColor = '#AAAAFF';
  1498. else if(deleted) this.style.backgroundColor = '#FFAAAA';
  1499. else this.style.backgroundColor = '#FFFFFF';
  1500. return false;
  1501. }
  1502. function uroCWLIconHighlight()
  1503. {
  1504. iconType = this.id.substr(11,1);
  1505. this.src = uroIcons[iconType][0];
  1506. return false;
  1507. }
  1508. function uroCWLIconLowlight()
  1509. {
  1510. iconType = this.id.substr(11,1);
  1511. this.src = uroIcons[iconType][1];
  1512. return false;
  1513. }
  1514. function uroRemoveFromCWL()
  1515. {
  1516. uroShownFID = uroCamWatchObjects[this.id.substr(18)].fid;
  1517. uroRemoveCamFromWatchList();
  1518. }
  1519. function uroSetCamGroups()
  1520. {
  1521. for(var camidx=0;camidx<uroCamWatchObjects.length;camidx++)
  1522. {
  1523. camObj = uroCamWatchObjects[camidx];
  1524. camGroup = parseInt(uroGetElmValue("_uroGroupSelect-"+camidx));
  1525. camObj.groupID = camGroup;
  1526. }
  1527. }
  1528. function uroPopulateCWLGroupSelect()
  1529. {
  1530. var selector = document.getElementById('_uroCWLGroupSelect');
  1531. while(selector.options.length > 0)
  1532. {
  1533. selector.options.remove(0);
  1534. }
  1535. for(var loop=0;loop<uroCWLGroups.length;loop++)
  1536. {
  1537. var groupObj = uroCWLGroups[loop];
  1538. if(groupObj.groupID != -1)
  1539. {
  1540. selector.options.add(new Option(groupObj.groupName,groupObj.groupID));
  1541. }
  1542. }
  1543. }
  1544. function uroGetNextCWLGroupID()
  1545. {
  1546. var nextID = 1;
  1547. for(var loop=0;loop<uroCWLGroups.length;loop++)
  1548. {
  1549. if(uroCWLGroups[loop].groupID >= nextID)
  1550. {
  1551. nextID = uroCWLGroups[loop].groupID + 1;
  1552. }
  1553. }
  1554. return nextID;
  1555. }
  1556. function uroFindCWLGroupByName(groupName)
  1557. {
  1558. var groupID = -1;
  1559. for(var loop=0;loop<uroCWLGroups.length;loop++)
  1560. {
  1561. if((uroCWLGroups[loop].groupName == groupName) && (uroCWLGroups[loop].groupID != -1))
  1562. {
  1563. groupID = uroCWLGroups[loop].groupID;
  1564. break;
  1565. }
  1566. }
  1567. return groupID;
  1568. }
  1569. function uroFindCWLGroupByIdx(groupIdx)
  1570. {
  1571. var groupName = '';
  1572. for(var loop=0;loop<uroCWLGroups.length;loop++)
  1573. {
  1574. if(uroCWLGroups[loop].groupID == groupIdx)
  1575. {
  1576. groupName = uroCWLGroups[loop].groupName;
  1577. break;
  1578. }
  1579. }
  1580. return groupName;
  1581. }
  1582. function uroAddCWLGroup()
  1583. {
  1584. var groupID = uroGetNextCWLGroupID();
  1585. var groupName = uroGetElmValue('_uroCWLGroupEntry');
  1586. if(uroFindCWLGroupByName(groupName) == -1)
  1587. {
  1588. uroCWLGroups.push(new uroOWLGroupObj(groupID,groupName,false));
  1589. uroPopulateCWLGroupSelect();
  1590. }
  1591. }
  1592. function uroRemoveCWLGroup()
  1593. {
  1594. var selector = document.getElementById('_uroCWLGroupSelect');
  1595. var groupID = parseInt(selector.selectedOptions[0].value);
  1596. if(groupID == 0) return false; // prevent deletion of the default group
  1597. for(var loop=0;loop<uroCamWatchObjects.length;loop++)
  1598. {
  1599. var cwObj = uroCamWatchObjects[loop];
  1600. if(cwObj.groupID == groupID)
  1601. {
  1602. cwObj.groupID = 0;
  1603. }
  1604. }
  1605. for(var loop=0;loop<uroCWLGroups.length;loop++)
  1606. {
  1607. var groupObj = uroCWLGroups[loop];
  1608. if(groupObj.groupID == groupID)
  1609. {
  1610. groupObj.groupID = -1;
  1611. }
  1612. }
  1613. uroOWLUpdateHTML();
  1614. }
  1615. function uroAssignCameraToGroup()
  1616. {
  1617. var camidx = this.id.substr(13);
  1618. var selector = document.getElementById('_uroCWLGroupSelect');
  1619. uroCamWatchObjects[camidx].groupID = parseInt(selector.selectedOptions[0].value);
  1620. uroOWLUpdateHTML();
  1621. return false;
  1622. }
  1623. function uroAddBtnEvl(btnID, evlType, evlFunction)
  1624. {
  1625. btnObj = document.getElementById(btnID);
  1626. if(btnObj != null)
  1627. {
  1628. btnObj.addEventListener(evlType, evlFunction, true);
  1629. }
  1630. }
  1631. function uroCWLGroupCollapseExpand()
  1632. {
  1633. var groupidx = this.id.substr(18);
  1634. if(uroCWLGroups[groupidx].groupCollapsed == true) uroCWLGroups[groupidx].groupCollapsed = false;
  1635. else uroCWLGroups[groupidx].groupCollapsed = true;
  1636. uroOWLUpdateHTML();
  1637. return false;
  1638. }
  1639. function uroOWLUpdateHTML()
  1640. {
  1641. var camTypes = new Array("","","Speed", "Dummy", "Red Light");
  1642. var selectedGroup = 0;
  1643. iHTML = '';
  1644. if(document.getElementById('_uroCWLGroupSelect') != null)
  1645. {
  1646. selectedGroup = document.getElementById('_uroCWLGroupSelect').selectedIndex;
  1647. }
  1648.  
  1649. iHTML = '<br><b>Camera Watchlist:</b><br><br>';
  1650. iHTML += '<div id="_uroCWLCamList" style="height:65%;overflow:auto;">';
  1651. for(var groupidx=0;groupidx<uroCWLGroups.length;groupidx++)
  1652. {
  1653. var groupObj = uroCWLGroups[groupidx];
  1654. iHTML += '<div id="_uroCWLGroup-'+groupidx+'">';
  1655. if(groupObj.groupCollapsed == true)
  1656. {
  1657. iHTML += '<img src="'+uroIcons[0][1]+'" id="_uroCWLGroupState-'+groupidx+'">';
  1658. }
  1659. else
  1660. {
  1661. iHTML += '<img src="'+uroIcons[0][0]+'" id="_uroCWLGroupState-'+groupidx+'">';
  1662. }
  1663. iHTML += '<b>'+groupObj.groupName+'</b><br>';
  1664. groupObj.groupCount = 0;
  1665. for(var camidx=0;camidx<uroCamWatchObjects.length;camidx++)
  1666. {
  1667. camObj = uroCamWatchObjects[camidx];
  1668. if(camObj.groupID == groupObj.groupID)
  1669. {
  1670. groupObj.groupCount++;
  1671. var changed = uroCamDataChanged(camidx);
  1672. var deleted = (camObj.loaded == false);
  1673. iHTML += '<div id="_uroCWL-'+camidx+'" style="padding:3px;border-width:2px;border-style:solid;border-color:#FFFFFF;background-color:';
  1674. if(camObj.server != W.location.code)
  1675. {
  1676. if(camObj.server == '??') iHTML += '#A0A0A0;';
  1677. else iHTML += '#AAFFAA;';
  1678. }
  1679. else if(changed) iHTML += '#AAAAFF;';
  1680. else if(deleted) iHTML += '#FFAAAA;';
  1681. else iHTML += '#FFFFFF;';
  1682. if(groupObj.groupCollapsed == true) iHTML += 'display:none;">';
  1683. else iHTML += 'display:block;">';
  1684.  
  1685. iHTML += 'ID: '+camObj.fid;
  1686. iHTML += ' ('+camObj.server+')';
  1687. iHTML += ' Type: '+camTypes[camObj.watch.type];
  1688. if(camObj.server != W.location.code)
  1689. {
  1690. if(camObj.server == '??')
  1691. {
  1692. iHTML += '<br><i>Unknown server</i>';
  1693. }
  1694. else
  1695. {
  1696. iHTML += '<br><i>Not on this server</i>';
  1697. }
  1698. }
  1699. else if(deleted)
  1700. {
  1701. iHTML += '<br>DELETED';
  1702. }
  1703. else if(changed)
  1704. {
  1705. if(camObj.current.type != camObj.watch.type)
  1706. {
  1707. iHTML += '<br>&nbsp;&nbsp;Type changed';
  1708. iHTML += ' ('+camObj.watch.type+' to '+camObj.current.type+')';
  1709. }
  1710. if(camObj.current.azymuth != camObj.watch.azymuth)
  1711. {
  1712. iHTML += '<br>&nbsp;&nbsp;Azimuth changed';
  1713. iHTML += ' ('+camObj.watch.azymuth+' to '+camObj.current.azymuth+')';
  1714. }
  1715. if(camObj.current.speed != camObj.watch.speed)
  1716. {
  1717. iHTML += '<br>&nbsp;&nbsp;Speed changed';
  1718. iHTML += ' ('+camObj.watch.speed+' to '+camObj.current.speed+')';
  1719. }
  1720. if(camObj.current.validated != camObj.watch.validated)
  1721. {
  1722. iHTML += '<br>&nbsp;&nbsp;Approval state changed';
  1723. iHTML += ' ('+camObj.watch.validated+' to '+camObj.current.validated+')';
  1724. }
  1725. if(camObj.current.lat != camObj.watch.lat)
  1726. {
  1727. iHTML += '<br>&nbsp;&nbsp;Latitude changed';
  1728. iHTML += ' ('+camObj.watch.lat+' to '+camObj.current.lat+')';
  1729. }
  1730. if(camObj.current.lon != camObj.watch.lon)
  1731. {
  1732. iHTML += '<br>&nbsp;&nbsp;Longitude changed';
  1733. iHTML += ' ('+camObj.watch.lon+' to '+camObj.current.lon+')';
  1734. }
  1735. }
  1736. if(camObj.server == W.location.code)
  1737. {
  1738. if(deleted == false)
  1739. {
  1740. iHTML += '&nbsp;<img id="_uroCWLIcon1-'+camidx+'" src="'+uroIcons[1][1]+'">';
  1741. }
  1742. iHTML += '&nbsp;<img id="_uroCWLIcon2-'+camidx+'" src="'+uroIcons[2][1]+'">';
  1743. }
  1744. iHTML += '</div>';
  1745. }
  1746. }
  1747. iHTML += '</div>';
  1748. }
  1749. iHTML += '</div><div id="_uroCWLControls">';
  1750. iHTML += '<hr>Group control:<br>';
  1751. iHTML += '<select id="_uroCWLGroupSelect" style="width:40%;height:22px;"></select>&nbsp;<input type="button" id="_btnCWLGroupDel" value="Delete group"><br>';
  1752. iHTML += '<input type="text" id="_uroCWLGroupEntry" style="width:40%;height:22px;">&nbsp;<input type="button" id="_btnCWLGroupAdd" value="Add group">';
  1753. iHTML += '<br><input type="button" id="_btnRescanCamWatchList" value="Refresh Camera Data"><br><br>';
  1754. iHTML += '<b>Remove cameras from OWL:</b><br>';
  1755. iHTML += '<input type="button" id="_btnRemoveDeletedCameras" value="Deleted">&nbsp;&nbsp;';
  1756. iHTML += '<input type="button" id="_btnRemoveUnknownServerCameras" value="Unknown Server">&nbsp;&nbsp;';
  1757. iHTML += '<input type="button" id="_btnClearCamWatchList" value="ALL Cameras">';
  1758. iHTML += '</div>';
  1759. uroOWL.innerHTML = iHTML;
  1760. for(var camidx=0;camidx<uroCamWatchObjects.length;camidx++)
  1761. {
  1762. document.getElementById("_uroCWL-"+camidx).onmouseover = uroHighlightCWLEntry;
  1763. document.getElementById("_uroCWL-"+camidx).onmouseleave = uroUnhighlightCWLEntry;
  1764.  
  1765. if(uroCamWatchObjects[camidx].server == W.location.code)
  1766. {
  1767. var icon1 = document.getElementById("_uroCWLIcon1-"+camidx);
  1768. var icon2 = document.getElementById("_uroCWLIcon2-"+camidx);
  1769. if(icon1 != null)
  1770. {
  1771. icon1.onmouseover = uroCWLIconHighlight;
  1772. icon1.onmouseleave = uroCWLIconLowlight;
  1773. icon1.onclick = uroAssignCameraToGroup;
  1774. }
  1775. if(icon2 != null)
  1776. {
  1777. icon2.onmouseover = uroCWLIconHighlight;
  1778. icon2.onmouseleave = uroCWLIconLowlight;
  1779. icon2.onclick = uroGotoCam;
  1780. }
  1781. }
  1782. }
  1783. uroAddBtnEvl('_btnClearCamWatchList', 'click', uroClearCamWatchList);
  1784. uroAddBtnEvl('_btnRemoveDeletedCameras', 'click', uroClearDeletedCameras);
  1785. uroAddBtnEvl('_btnRemoveUnknownServerCameras', 'click', uroClearUnknownServerCameras);
  1786. uroAddBtnEvl('_btnRescanCamWatchList', 'click', uroRescanCamWatchList);
  1787. uroAddBtnEvl('_btnCWLGroupDel', 'click', uroRemoveCWLGroup);
  1788. uroAddBtnEvl('_btnCWLGroupAdd', 'click', uroAddCWLGroup);
  1789. if(document.getElementById('_uroCWLGroupSelect') != null)
  1790. {
  1791. uroAddLog('populating CWL group list');
  1792. uroPopulateCWLGroupSelect();
  1793. var selector = document.getElementById('_uroCWLGroupSelect');
  1794. if(selectedGroup >= selector.length)
  1795. {
  1796. selectedGroup = 0;
  1797. }
  1798. selector.selectedIndex = selectedGroup;
  1799. }
  1800.  
  1801. for(var groupidx=0;groupidx<uroCWLGroups.length;groupidx++)
  1802. {
  1803. if(uroCWLGroups[groupidx].groupCount == 0)
  1804. {
  1805. uroSetStyleDisplay('_uroCWLGroup-'+groupidx,'none');
  1806. }
  1807. else
  1808. {
  1809. uroSetOnClick('_uroCWLGroupState-'+groupidx,uroCWLGroupCollapseExpand);
  1810. }
  1811. }
  1812. }
  1813.  
  1814. // --------------------------------------------------------------------------------------------------------------------
  1815. // END OF WATCHLIST STUFF
  1816. // --------------------------------------------------------------------------------------------------------------------
  1817.  
  1818.  
  1819. function uroIsOnIgnoreList(fid)
  1820. {
  1821. if(sessionStorage.UROverview_FID_IgnoreList.indexOf('fid:'+fid) == -1) return false;
  1822. else return true;
  1823. }
  1824.  
  1825. function uroEnableIgnoreListControls()
  1826. {
  1827. var btnState = "visible";
  1828. if(sessionStorage.UROverview_FID_IgnoreList == '')
  1829. {
  1830. btnState = "hidden";
  1831. }
  1832. document.getElementById('_btnUndoLastHide').style.visibility = btnState;
  1833. document.getElementById('_btnClearSessionHides').style.visibility = btnState;
  1834. uroFilterItems();
  1835. }
  1836.  
  1837. function uroAddToIgnoreList()
  1838. {
  1839. if(!uroIsOnIgnoreList(uroShownFID))
  1840. {
  1841. sessionStorage.UROverview_FID_IgnoreList += 'fid:'+uroShownFID;
  1842. uroAddLog('added fid '+uroShownFID+' to ignore list');
  1843. uroAddLog(sessionStorage.UROverview_FID_IgnoreList);
  1844. uroDiv.style.visibility = 'hidden';
  1845. uroEnableIgnoreListControls();
  1846. W.map.events.register("mousemove", null, uroFilterItemsOnMove);
  1847. }
  1848. return false;
  1849. }
  1850.  
  1851. function uroRemoveFromIgnoreList(fid)
  1852. {
  1853. var ignorelist = sessionStorage.UROverview_FID_IgnoreList;
  1854. var fidpos = ignorelist.indexOf('fid:'+fid);
  1855. if(fidpos != -1)
  1856. {
  1857. var preFID = ignorelist.slice(0,fidpos);
  1858. ignorelist = ignorelist.slice(fidpos+1);
  1859. fidpos = ignorelist.indexOf('fid:');
  1860. if(fidpos == -1) ignorelist = '';
  1861. else ignorelist = ignorelist.slice(fidpos);
  1862. sessionStorage.UROverview_FID_IgnoreList = preFID + ignorelist;
  1863. uroAddLog('removed fid '+fid+' from ignore list');
  1864. uroAddLog(sessionStorage.UROverview_FID_IgnoreList);
  1865. uroEnableIgnoreListControls();
  1866. }
  1867. }
  1868.  
  1869. function uroRemoveLastAddedIgnore()
  1870. {
  1871. var ignorelist = sessionStorage.UROverview_FID_IgnoreList;
  1872. var fidpos = ignorelist.lastIndexOf('fid:');
  1873. if(fidpos != -1)
  1874. {
  1875. ignorelist = ignorelist.slice(0,fidpos);
  1876. sessionStorage.UROverview_FID_IgnoreList = ignorelist;
  1877. uroAddLog('removed last fid from ignore list');
  1878. uroAddLog(sessionStorage.UROverview_FID_IgnoreList);
  1879. uroEnableIgnoreListControls();
  1880. }
  1881. }
  1882.  
  1883. function uroRemoveAllIgnores()
  1884. {
  1885. sessionStorage.UROverview_FID_IgnoreList = '';
  1886. uroEnableIgnoreListControls();
  1887. }
  1888.  
  1889.  
  1890. function uroKeywordPresent(desc, keyword)
  1891. {
  1892. if(uroGetCBChecked('_cbCaseInsensitive') == true) re = RegExp(keyword,'i');
  1893. else re = RegExp(keyword);
  1894. if(desc.search(re) == -1) return false;
  1895. else return true;
  1896. }
  1897.  
  1898.  
  1899. function uroClickify(desc)
  1900. {
  1901. var linkStartPos = desc.indexOf('http://');
  1902. if(linkStartPos == -1) linkStartPos = desc.indexOf('https://');
  1903. if(linkStartPos != -1)
  1904. {
  1905. var descPreLink = desc.slice(0,linkStartPos);
  1906. var descURL = desc.slice(linkStartPos);
  1907. var linkEndPos = descURL.indexOf(' ');
  1908. var descPostLink = '';
  1909. if(linkEndPos != -1)
  1910. {
  1911. descPostLink = descURL.slice(linkEndPos);
  1912. descURL = descURL.slice(0,linkEndPos);
  1913. }
  1914. var linkTarget = '';
  1915. if(descURL.indexOf('cryosphere') != -1) linkTarget = '_cryosphere';
  1916. else if(descURL.indexOf('waze.com') != -1) linkTarget = '_wazeUR';
  1917. desc = descPreLink + '<a target="'+linkTarget+'" href="'+descURL+'">here</a>' + descPostLink;
  1918. }
  1919. return desc;
  1920. }
  1921.  
  1922.  
  1923. function uroRefreshUpdateRequestSessions()
  1924. {
  1925. for (var urID in W.model.mapUpdateRequests.objects)
  1926. {
  1927. var reqPos = uroRequestedURSessionIDs.indexOf(urID);
  1928. var pendPos = uroPendingURSessionIDs.indexOf(urID);
  1929. if(W.model.updateRequestSessions.objects[urID] == null)
  1930. {
  1931. if((reqPos == -1) && (pendPos == -1))
  1932. {
  1933. uroPendingURSessionIDs.push(urID);
  1934. }
  1935. }
  1936. else
  1937. {
  1938. if(reqPos != -1)
  1939. {
  1940. uroRequestedURSessionIDs.splice(reqPos,1);
  1941. }
  1942. if(pendPos != -1)
  1943. {
  1944. uroPendingURSessionIDs.splice(pendPos,1);
  1945. }
  1946. }
  1947. }
  1948.  
  1949. var idList = [];
  1950. while((idList.length < 500) && (uroPendingURSessionIDs.length))
  1951. {
  1952. var id = uroPendingURSessionIDs.pop();
  1953. idList.push(id);
  1954. uroRequestedURSessionIDs.push(id);
  1955. }
  1956. if(idList.length > 0)
  1957. {
  1958. uroAddLog('grabbing updateRequestSessions with IDs '+idList);
  1959. W.model.updateRequestSessions.get(idList);
  1960. }
  1961.  
  1962. if((uroPendingURSessionIDs.length) || (uroRequestedURSessionIDs.length))
  1963. {
  1964. setTimeout(uroRefreshUpdateRequestSessions,10);
  1965. }
  1966. }
  1967.  
  1968. function uroURHasMyComments(fid)
  1969. {
  1970. var nComments = W.model.updateRequestSessions.objects[fid].comments.length;
  1971. if(nComments == 0) return false;
  1972.  
  1973. for(var cidx=0; cidx<nComments; cidx++)
  1974. {
  1975. if(W.model.updateRequestSessions.objects[fid].comments[cidx].userID == uroUserID) return true;
  1976. }
  1977. return false;
  1978. }
  1979.  
  1980. function uroACMObj(urID, customType, hasMyComments, nComments)
  1981. {
  1982. this.urID = urID;
  1983. this.customType = customType;
  1984. this.hasMyComments = hasMyComments;
  1985. this.nComments = nComments;
  1986. }
  1987.  
  1988. function uroAddCustomMarkers(urID, customType, hasMyComments, nComments)
  1989. {
  1990. var useCustomMarker = false;
  1991.  
  1992. if(customType == 0) useCustomMarker = (uroGetCBChecked('_cbCustomRoadworksMarkers'));
  1993. else if(customType == 1) useCustomMarker = (uroGetCBChecked('_cbCustomConstructionMarkers'));
  1994. else if(customType == 2) useCustomMarker = (uroGetCBChecked('_cbCustomClosuresMarkers'));
  1995. else if(customType == 3) useCustomMarker = (uroGetCBChecked('_cbCustomEventsMarkers'));
  1996. else if(customType == 4) useCustomMarker = (uroGetCBChecked('_cbCustomNotesMarkers'));
  1997. if(!useCustomMarker) customType = -1;
  1998. uroCustomMarkerList.push(new uroACMObj(urID, customType, hasMyComments, nComments));
  1999. }
  2000.  
  2001. function uroRenderCustomMarkers()
  2002. {
  2003. var markersToAdd = uroCustomMarkerList.length;
  2004. var useDefaultConvoMarker = false;
  2005. var addCommentCount = false;
  2006.  
  2007. if((uroGetCBChecked('_cbNativeConvoMarkers')) && (uroBetaEditor == false)) useDefaultConvoMarker = true;
  2008. if((uroGetCBChecked('_cbNativeBetaConvoMarkers')) && (uroBetaEditor == true)) useDefaultConvoMarker = true;
  2009. if(uroGetCBChecked('_cbCommentCount')) addCommentCount = true;
  2010. var divElem = document.getElementById(W.map.updateRequestLayer.id);
  2011. if(divElem.childNodes.length > 0)
  2012. {
  2013. for(var objIdx = 0; objIdx < uroCustomMarkerList.length; objIdx++)
  2014. {
  2015. var urID = uroCustomMarkerList[objIdx].urID;
  2016. var customType = uroCustomMarkerList[objIdx].customType;
  2017. var hasMyComments = uroCustomMarkerList[objIdx].hasMyComments;
  2018. var nComments = uroCustomMarkerList[objIdx].nComments;
  2019. var divHTML = '';
  2020. if(customType != -1)
  2021. {
  2022. divHTML += '<span id="customMarker_'+urID+'" style="position:absolute;pointer-events:none;">';
  2023. customType = uroGetCustomMarkerIdx(customType);
  2024. if(W.model.updateRequestSessions.objects[urID] != undefined)
  2025. {
  2026. if(W.model.updateRequestSessions.objects[urID].open == false) customType += 1;
  2027. }
  2028. divHTML += '<img src="'+uroIcons[customType][0]+'">';
  2029. divHTML += '</span>';
  2030. }
  2031. if(nComments > 0)
  2032. {
  2033. if(addCommentCount)
  2034. {
  2035. divHTML += '<span style="position:absolute;top:-9px;left:-11px;pointer-events:none;">';
  2036. divHTML += '<img src="'+uroMarkers[0]+'">';
  2037. divHTML += '</span>';
  2038. divHTML += '<span style="position:absolute;top:-6px;left:-';
  2039. if(nComments < 10) divHTML += '0';
  2040. else if(nComments < 100) divHTML += '3';
  2041. else divHTML += '6';
  2042. divHTML += 'px;font-size:11px;;pointer-events:none;">'+nComments+'</span>';
  2043. }
  2044.  
  2045. if(useDefaultConvoMarker == false)
  2046. {
  2047. divHTML += '<span style="position:absolute;top:-9px;left:18px;pointer-events:none;">';
  2048. if(hasMyComments) divHTML += '<img src="'+uroMarkers[2]+'">';
  2049. else divHTML += '<img src="'+uroMarkers[1]+'">';
  2050. divHTML += '</span>';
  2051. W.map.updateRequestLayer.markers[urID].icon.imageDiv.classList.remove("has-comments")
  2052. }
  2053. else
  2054. {
  2055. W.map.updateRequestLayer.markers[urID].icon.imageDiv.classList.add("has-comments")
  2056. }
  2057. }
  2058. W.map.updateRequestLayer.markers[urID].icon.imageDiv.innerHTML = divHTML;
  2059. }
  2060. }
  2061. }
  2062.  
  2063.  
  2064. function uroChangeCustomMarkers(urID,isHighlighted,customType)
  2065. {
  2066. if(document.getElementById('customMarker_'+urID) != null)
  2067. {
  2068. if(W.model.updateRequestSessions.objects[urID].open == false) customType += 1;
  2069.  
  2070. if(isHighlighted == true)
  2071. {
  2072. document.getElementById('customMarker_'+urID).innerHTML = '<img src="'+uroIcons[customType][1]+'">';
  2073. }
  2074. else
  2075. {
  2076. document.getElementById('customMarker_'+urID).innerHTML = '<img src="'+uroIcons[customType][0]+'">';
  2077. }
  2078. }
  2079. }
  2080.  
  2081. function uroFilterPlaces()
  2082. {
  2083. if(uroFilterPreamble() == false) return;
  2084. if(uroPlaceSelected == true) return;
  2085. if(uroGetCBChecked('_cbDisablePlacesFiltering') == true) return;
  2086. var filterCats = [];
  2087. for(var i=0; i<W.Config.venues.categories.length; i++)
  2088. {
  2089. parentCategory = W.Config.venues.categories[i];
  2090. if(uroGetCBChecked('_cbPlacesFilter-'+parentCategory) == true)
  2091. {
  2092. filterCats.push(parentCategory);
  2093. for(var ii=0; ii<W.Config.venues.subcategories[parentCategory].length; ii++)
  2094. {
  2095. subCategory = W.Config.venues.subcategories[parentCategory][ii];
  2096. filterCats.push(subCategory);
  2097. }
  2098. }
  2099. else
  2100. {
  2101. for(var ii=0; ii<W.Config.venues.subcategories[parentCategory].length; ii++)
  2102. {
  2103. subCategory = W.Config.venues.subcategories[parentCategory][ii];
  2104. if(uroGetCBChecked('_cbPlacesFilter-'+subCategory) == true)
  2105. {
  2106. filterCats.push(subCategory);
  2107. }
  2108. }
  2109. }
  2110. }
  2111.  
  2112. for(var v=0; v<W.map.landmarkLayer.features.length; v++)
  2113. {
  2114. placeStyle = 'visible';
  2115. lmObj = W.map.landmarkLayer.features[v];
  2116. // when an area place is selected, the drag points for editing the place outline now get added as objects into W.map.landmarkLayer.features,
  2117. // however none of these objects have the .model property - we must therefore check each entry in features[] to see if it has .model before
  2118. // attempting to filter it...
  2119. if(lmObj.model != undefined)
  2120. {
  2121. editDate = lmObj.model.attributes.updatedOn;
  2122. if(editDate == undefined)
  2123. {
  2124. // where a place has never been edited since its creation, use the creation date instead...
  2125. editDate = lmObj.model.attributes.createdOn;
  2126. }
  2127. if(editDate != undefined)
  2128. {
  2129. editDaysAgo = uroDateToDays(editDate);
  2130. if(uroGetCBChecked('_cbPlaceFilterEditedLessThan'))
  2131. {
  2132. if(editDaysAgo < document.getElementById('_inputFilterPlaceEditMinDays').value)
  2133. {
  2134. placeStyle = 'hidden';
  2135. }
  2136. }
  2137. if(uroGetCBChecked('_cbPlaceFilterEditedMoreThan'))
  2138. {
  2139. if(editDaysAgo > document.getElementById('_inputFilterPlaceEditMaxDays').value)
  2140. {
  2141. placeStyle = 'hidden';
  2142. }
  2143. }
  2144. }
  2145. if(placeStyle == 'visible')
  2146. {
  2147. lockLevel = lmObj.model.attributes.lockRank;
  2148. if ((uroGetCBChecked('_cbHidePlacesL0')) && (lockLevel == 0)) placeStyle = 'hidden';
  2149. if ((uroGetCBChecked('_cbHidePlacesL1')) && (lockLevel == 1)) placeStyle = 'hidden';
  2150. if ((uroGetCBChecked('_cbHidePlacesL2')) && (lockLevel == 2)) placeStyle = 'hidden';
  2151. if ((uroGetCBChecked('_cbHidePlacesL3')) && (lockLevel == 3)) placeStyle = 'hidden';
  2152. if ((uroGetCBChecked('_cbHidePlacesL4')) && (lockLevel == 4)) placeStyle = 'hidden';
  2153. if ((uroGetCBChecked('_cbHidePlacesL5')) && (lockLevel == 5)) placeStyle = 'hidden';
  2154. }
  2155. if(placeStyle == 'visible')
  2156. {
  2157. nPhotos = 0;
  2158. for(var loop=0; loop<lmObj.model.attributes.images.length; loop++)
  2159. {
  2160. if(lmObj.model.attributes.images[loop].attributes.approved) nPhotos++;
  2161. }
  2162. if((uroGetCBChecked('_cbHideNoPhotoPlaces')) && (nPhotos == 0)) placeStyle = 'hidden';
  2163. if((uroGetCBChecked('_cbHidePhotoPlaces')) && (nPhotos != 0)) placeStyle = 'hidden';
  2164. }
  2165. if(placeStyle == 'visible')
  2166. {
  2167. if((lmObj.model.attributes.residential == true) && (uroGetCBChecked('_cbFilterPrivatePlaces') == true))
  2168. {
  2169. placeStyle = 'hidden';
  2170. }
  2171. else
  2172. {
  2173. for(var cat=0; cat<filterCats.length; cat++)
  2174. {
  2175. if(lmObj.model.attributes.categories.contains(filterCats[cat]))
  2176. {
  2177. placeStyle = 'hidden';
  2178. break;
  2179. }
  2180. }
  2181. }
  2182. }
  2183. }
  2184. if(uroGetCBChecked('_cbInvertPlacesFilter') == true)
  2185. {
  2186. if(placeStyle == 'hidden') placeStyle = 'visible';
  2187. else placeStyle = 'hidden';
  2188. }
  2189. geoID = W.map.landmarkLayer.features[v].geometry.id;
  2190. // area places...
  2191. if(document.getElementById(uroPlacesRoot).getElementsByTagName('path')[geoID] != null)
  2192. {
  2193. document.getElementById(uroPlacesRoot).getElementsByTagName('path')[geoID].style.visibility = placeStyle;
  2194. }
  2195. // point places...
  2196. if(document.getElementById(uroPlacesRoot).getElementsByTagName('circle')[geoID] != null)
  2197. {
  2198. document.getElementById(uroPlacesRoot).getElementsByTagName('circle')[geoID].style.visibility = placeStyle;
  2199. }
  2200.  
  2201. }
  2202.  
  2203. for(var pu in W.map.placeUpdatesLayer.markers)
  2204. {
  2205. puObj = W.map.placeUpdatesLayer.markers[pu];
  2206. if(W.map.placeUpdatesLayer.getVisibility() == true)
  2207. {
  2208. placeStyle = 'visible';
  2209. if(uroGetCBChecked('_cbFilterUneditablePlaceUpdates') == true)
  2210. {
  2211. if(puObj.model.attributes.permissions == 0)
  2212. {
  2213. placeStyle = 'hidden';
  2214. }
  2215. if(W.model.loginManager.isLoggedIn())
  2216. {
  2217. if(W.model.loginManager.user.rank < puObj.model.attributes.lockRank)
  2218. {
  2219. placeStyle = 'hidden';
  2220. }
  2221. }
  2222. }
  2223. if(uroGetCBChecked('_cbFilterLockRankedPlaceUpdates') == true)
  2224. {
  2225. if(puObj.model.attributes.lockRank != 0)
  2226. {
  2227. placeStyle = 'hidden';
  2228. }
  2229. }
  2230. if(uroGetCBChecked("_cbFilterFlaggedPUR") == true)
  2231. {
  2232. if(puObj.icon.imageDiv.className.indexOf('flag') != -1)
  2233. {
  2234. placeStyle = 'hidden';
  2235. }
  2236. }
  2237. if(uroGetCBChecked("_cbFilterNewPlacePUR") == true)
  2238. {
  2239. if(puObj.icon.imageDiv.className.indexOf('add_venue') != -1)
  2240. {
  2241. placeStyle = 'hidden';
  2242. }
  2243. }
  2244. if(uroGetCBChecked("_cbFilterUpdatedDetailsPUR") == true)
  2245. {
  2246. if((puObj.icon.imageDiv.className.indexOf('update_venue') != -1) || (puObj.icon.imageDiv.className.indexOf('multiple') != -1))
  2247. {
  2248. placeStyle = 'hidden';
  2249. }
  2250. }
  2251. if(uroGetCBChecked("_cbFilterNewPhotoPUR") == true)
  2252. {
  2253. if(puObj.icon.imageDiv.className.indexOf('add_image') != -1)
  2254. {
  2255. placeStyle = 'hidden';
  2256. }
  2257. }
  2258. if(uroGetCBChecked('_cbInvertPURFilters') == true)
  2259. {
  2260. if(placeStyle == 'hidden') placeStyle = 'visible';
  2261. else placeStyle = 'hidden';
  2262. }
  2263. if(uroGetCBChecked('_cbEnablePURMinAgeFilter') == true)
  2264. {
  2265. if(uroGetPURAge(puObj.model) < uroGetElmValue('_inputPURFilterMinDays')) placeStyle = 'hidden';
  2266. }
  2267. if(uroGetCBChecked('_cbEnablePURMaxAgeFilter') == true)
  2268. {
  2269. if(uroGetPURAge(puObj.model) > uroGetElmValue('_inputPURFilterMaxDays')) placeStyle = 'hidden';
  2270. }
  2271. var purSeverity = puObj._getSeverity();
  2272. if((uroGetCBChecked('_cbPURFilterHighSeverity')) && (purSeverity == "high")) placeStyle = 'hidden';
  2273. if((uroGetCBChecked('_cbPURFilterMediumSeverity')) && (purSeverity == "medium")) placeStyle = 'hidden';
  2274. if((uroGetCBChecked('_cbPURFilterLowSeverity')) && (purSeverity == "low")) placeStyle = 'hidden';
  2275. puObj.icon.imageDiv.style.visibility = placeStyle;
  2276. if(uroGetCBChecked('_cbLeavePURGeos') == false)
  2277. {
  2278. if(puObj.model != undefined)
  2279. {
  2280. if(puObj.model.geometry != undefined)
  2281. {
  2282. puGeo = document.getElementById(puObj.model.geometry.id);
  2283. if(puGeo != null)
  2284. {
  2285. puGeo.style.visibility = placeStyle;
  2286. }
  2287. }
  2288. }
  2289. }
  2290. }
  2291. }
  2292. }
  2293.  
  2294. function uroFilterCameras()
  2295. {
  2296. if(uroFilterPreamble() == false) return;
  2297. var camLayer = document.getElementById(uroRootContainer+'_svgRoot');
  2298. if(camLayer == null)
  2299. {
  2300. if(uroNullCamLayer == false)
  2301. {
  2302. uroAddLog('caught null camLayer');
  2303. uroNullCamLayer = true;
  2304. }
  2305. return;
  2306. }
  2307. uroNullCamLayer = false;
  2308. if(uroMouseIsDown == false) W.map.camerasLayer.redraw();
  2309. for (var uroCamObj in W.model.cameras.objects)
  2310. {
  2311. var uroCam = W.model.cameras.objects[uroCamObj];
  2312. var uroCamStyle = 'visible';
  2313. if(W.model.users.objects[uroCam.attributes.createdBy] != null)
  2314. {
  2315. var uroCamCreator = W.model.users.objects[uroCam.attributes.createdBy].userName;
  2316. var uroCamCreatorRank = W.model.users.objects[uroCam.attributes.createdBy].rank;
  2317. }
  2318. else
  2319. {
  2320. var uroCamCreator = '';
  2321. var uroCamCreatorRank = -1;
  2322. }
  2323. if(W.model.users.objects[uroCam.attributes.updatedBy] != null)
  2324. {
  2325. var uroCamUpdater = W.model.users.objects[uroCam.attributes.updatedBy].userName;
  2326. var uroCamUpdaterRank = W.model.users.objects[uroCam.attributes.updatedBy].rank;
  2327. }
  2328. else
  2329. {
  2330. var uroCamUpdater = '';
  2331. var uroCamUpdaterRank = -1;
  2332. }
  2333.  
  2334. var uroCamApproved = uroCam.attributes.validated;
  2335. var uroCamType = uroCam.attributes.type;
  2336.  
  2337.  
  2338. if(uroGetCBChecked('_cbShowOnlyMyCams') == true)
  2339. {
  2340. if((uroUserID != uroCam.attributes.createdBy)&&(uroUserID != uroCam.attributes.updatedBy)) uroCamStyle = 'hidden';
  2341. }
  2342.  
  2343. if((uroGetCBChecked('_cbShowWorldCams') == false) || (uroGetCBChecked('_cbShowUSACams') == false) || (uroGetCBChecked('_cbShowNonWorldCams') == false))
  2344. {
  2345. var posWorld = uroCamCreator.indexOf('world_');
  2346. var posUSA = uroCamCreator.indexOf('usa_');
  2347.  
  2348. if((uroGetCBChecked('_cbShowWorldCams') == false) && (posWorld == 0)) uroCamStyle = 'hidden';
  2349. if((uroGetCBChecked('_cbShowUSACams') == false) && (posUSA == 0)) uroCamStyle = 'hidden';
  2350. if((uroGetCBChecked('_cbShowNonWorldCams') == false) && (posWorld != 0) && (posUSA != 0)) uroCamStyle = 'hidden';
  2351. }
  2352.  
  2353. if((uroGetCBChecked('_cbShowApprovedCams') == false) || (uroGetCBChecked('_cbShowNonApprovedCams') == false))
  2354. {
  2355. if((uroGetCBChecked('_cbShowApprovedCams') == false) && (uroCamApproved == true)) uroCamStyle = 'hidden';
  2356. if((uroGetCBChecked('_cbShowNonApprovedCams') == false) && (uroCamApproved == false)) uroCamStyle = 'hidden';
  2357. }
  2358.  
  2359. if((uroGetCBChecked('_cbShowNonApprovedCams') == true) && (uroCamApproved == false))
  2360. {
  2361. if(((uroGetCBChecked('_cbShowOlderCreatedNonApproved') == true)) && (uroGetCameraAge(uroCam,1) <= uroGetElmValue('_inputCameraMinCreatedDays'))) uroCamStyle = 'hidden';
  2362. if(((uroGetCBChecked('_cbShowOlderUpdatedNonApproved') == true)) && (uroGetCameraAge(uroCam,0) <= uroGetElmValue('_inputCameraMinUpdatedDays'))) uroCamStyle = 'hidden';
  2363. }
  2364.  
  2365. if((uroGetCBChecked('_cbShowSpeedCams') == false) || (uroGetCBChecked('_cbShowRedLightCams') == false) || (uroGetCBChecked('_cbShowDummyCams') == false))
  2366. {
  2367. if((uroGetCBChecked('_cbShowSpeedCams') == false) && (uroCamType == 2)) uroCamStyle = 'hidden';
  2368. if((uroGetCBChecked('_cbShowRedLightCams') == false) && (uroCamType == 4)) uroCamStyle = 'hidden';
  2369. if((uroGetCBChecked('_cbShowDummyCams') == false) && (uroCamType == 3)) uroCamStyle = 'hidden';
  2370. }
  2371.  
  2372. if(uroGetCBChecked('_cbShowSpeedCams') == true)
  2373. {
  2374. if((uroGetCBChecked('_cbShowIfMPHSpeedSet') == false) && (uroIsCameraSpeedValid(uroCam) == 1)) uroCamStyle = 'hidden';
  2375. if((uroGetCBChecked('_cbShowIfNoSpeedSet') == false) && (uroIsCameraSpeedValid(uroCam) == 0)) uroCamStyle = 'hidden';
  2376. if((uroGetCBChecked('_cbShowIfKPHSpeedSet') == false) && (uroIsCameraSpeedValid(uroCam) == -1)) uroCamStyle = 'hidden';
  2377. }
  2378.  
  2379. if(uroGetCBChecked('_cbHideCreatedByMe') == true)
  2380. {
  2381. if(uroUserID == uroCam.attributes.createdBy) uroCamStyle = 'hidden';
  2382. }
  2383. if((uroGetCBChecked('_cbHideCreatedByRank0') == true) && (uroCamCreatorRank == 0)) uroCamStyle = 'hidden';
  2384. if((uroGetCBChecked('_cbHideCreatedByRank1') == true) && (uroCamCreatorRank == 1)) uroCamStyle = 'hidden';
  2385. if((uroGetCBChecked('_cbHideCreatedByRank2') == true) && (uroCamCreatorRank == 2)) uroCamStyle = 'hidden';
  2386. if((uroGetCBChecked('_cbHideCreatedByRank3') == true) && (uroCamCreatorRank == 3)) uroCamStyle = 'hidden';
  2387. if((uroGetCBChecked('_cbHideCreatedByRank4') == true) && (uroCamCreatorRank == 4)) uroCamStyle = 'hidden';
  2388. if((uroGetCBChecked('_cbHideCreatedByRank5') == true) && (uroCamCreatorRank == 5)) uroCamStyle = 'hidden';
  2389.  
  2390. if(uroGetCBChecked('_cbHideUpdatedByMe') == true)
  2391. {
  2392. if(uroUserID == uroCam.attributes.updatedBy) uroCamStyle = 'hidden';
  2393. }
  2394. if((uroGetCBChecked('_cbHideUpdatedByRank0') == true) && (uroCamUpdaterRank == 0)) uroCamStyle = 'hidden';
  2395. if((uroGetCBChecked('_cbHideUpdatedByRank1') == true) && (uroCamUpdaterRank == 1)) uroCamStyle = 'hidden';
  2396. if((uroGetCBChecked('_cbHideUpdatedByRank2') == true) && (uroCamUpdaterRank == 2)) uroCamStyle = 'hidden';
  2397. if((uroGetCBChecked('_cbHideUpdatedByRank3') == true) && (uroCamUpdaterRank == 3)) uroCamStyle = 'hidden';
  2398. if((uroGetCBChecked('_cbHideUpdatedByRank4') == true) && (uroCamUpdaterRank == 4)) uroCamStyle = 'hidden';
  2399. if((uroGetCBChecked('_cbHideUpdatedByRank5') == true) && (uroCamUpdaterRank == 5)) uroCamStyle = 'hidden';
  2400.  
  2401. if((uroGetCBChecked('_cbHideCWLCams') == true) && (uroIsCamOnWatchList(uroCam.attributes.id) != -1)) uroCamStyle = 'hidden';
  2402.  
  2403. var uroCamGeometryID = uroCam.geometry.id;
  2404. if(camLayer.getElementById(uroCamGeometryID) != null)
  2405. {
  2406. var camX = parseInt(camLayer.getElementById(uroCamGeometryID).getAttribute('x'));
  2407. if(uroCamStyle == "hidden")
  2408. {
  2409. camLayer.getElementById(uroCamGeometryID).remove();
  2410. }
  2411. }
  2412. }
  2413. }
  2414.  
  2415. function uroFilterURs_onObjectsChanged()
  2416. {
  2417. if(uroBackfilling == false)
  2418. {
  2419. uroURBackfill();
  2420. uroFilterURs();
  2421. }
  2422. }
  2423. function uroFilterURs_onObjectsAdded()
  2424. {
  2425. if(uroBackfilling == false)
  2426. {
  2427. uroURBackfill();
  2428. uroFilterURs();
  2429. }
  2430. }
  2431. function uroFilterURs_onObjectsRemoved()
  2432. {
  2433. if(uroBackfilling == false)
  2434. {
  2435. uroURBackfill();
  2436. uroFilterURs();
  2437. }
  2438. }
  2439.  
  2440. function uroURBackfill_GetData(lon, lat, blockSize)
  2441. {
  2442. lon = parseFloat(lon);
  2443. lat = parseFloat(lat);
  2444. blockSize = parseFloat(blockSize);
  2445. uroAddLog('Backfill square '+lon+','+lat);
  2446. var xmlReq = new XMLHttpRequest();
  2447. var tURL = 'https://' + document.location.host;
  2448. tURL += Waze.Config.api_base;
  2449. tURL += '/Features?language=en&mapUpdateRequestFilter=0';
  2450. if(uroPracticeMode == true) tURL += '&sandbox=true';
  2451. tURL += '&bbox='+(lon)+','+(lat)+','+(lon + blockSize)+','+(lat + blockSize);
  2452. xmlReq.open('GET',tURL,false);
  2453. try
  2454. {
  2455. xmlReq.send();
  2456. uroAddLog('response '+xmlReq.status+' received');
  2457. if (xmlReq.status === 200)
  2458. {
  2459. var tResp = JSON.parse(xmlReq.responseText);
  2460. var urCount = tResp.mapUpdateRequests.objects.length;
  2461. uroAddLog(urCount+' URs loaded for backfill processing');
  2462. if(urCount == 500)
  2463. {
  2464. uroAddLog('WARNING - backfill data may have been pre-filtered by server');
  2465. }
  2466.  
  2467. var backfilled = 0;
  2468. for(var i=0; i<urCount; i++)
  2469. {
  2470. var urID = tResp.mapUpdateRequests.objects[i].id;
  2471. if(W.model.mapUpdateRequests.objects[urID] == undefined)
  2472. {
  2473. var newUR = require('Waze/Feature/Vector/UpdateRequest');
  2474. var tUR = new newUR(tResp.mapUpdateRequests.objects[i]);
  2475. var tPoint = new OpenLayers.Geometry.Point();
  2476. tPoint.x = tResp.mapUpdateRequests.objects[i].geometry.coordinates[0];
  2477. tPoint.y = tResp.mapUpdateRequests.objects[i].geometry.coordinates[1];
  2478. tPoint.transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913"));
  2479. tUR.geometry = tPoint;
  2480. W.model.mapUpdateRequests.put(tUR);
  2481. backfilled++;
  2482. }
  2483. }
  2484.  
  2485. uroAddLog(backfilled+' URs backfilled');
  2486. }
  2487. else
  2488. {
  2489. uroAddLog('request failed (status != 200)');
  2490. }
  2491. }
  2492. catch(err)
  2493. {
  2494. uroAddLog('UR backfill request failed (exception '+err+' caught)');
  2495. }
  2496. }
  2497. function uroURBackfill()
  2498. {
  2499. if(uroGetCBChecked('_cbURBackfill') == false)
  2500. {
  2501. return;
  2502. }
  2503. var nativeURCount = Object.keys(W.model.mapUpdateRequests.objects).length;
  2504. if(nativeURCount < 500)
  2505. {
  2506. return;
  2507. }
  2508.  
  2509. uroAddLog('exactly 500 URs loaded, possible server-side filtering requiring backfill...');
  2510. var subSize = 0.1;
  2511. var vpWidth = W.map.getExtent().getWidth();
  2512. var vpHeight = W.map.getExtent().getHeight();
  2513. var vpCentre = W.map.getCenter();
  2514. var vpLL = new OpenLayers.LonLat();
  2515. var vpUR = new OpenLayers.LonLat();
  2516. vpLL.lon = vpCentre.lon - (vpWidth / 2);
  2517. vpLL.lat = vpCentre.lat - (vpHeight / 2);
  2518. vpUR.lon = vpCentre.lon + (vpWidth / 2);
  2519. vpUR.lat = vpCentre.lat + (vpHeight / 2);
  2520. vpLL = vpLL.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326"));
  2521. vpUR = vpUR.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326"));
  2522. vpLL.lon -= (subSize / 2);
  2523. vpLL.lat -= (subSize / 2);
  2524. vpUR.lon += (subSize / 2);
  2525. vpUR.lat += (subSize / 2);
  2526. vpLL.lon = +vpLL.lon.toFixed(1);
  2527. vpLL.lat = +vpLL.lat.toFixed(1);
  2528. vpUR.lon = +vpUR.lon.toFixed(1);
  2529. vpUR.lat = +vpUR.lat.toFixed(1);
  2530. uroBackfilling = true;
  2531. for(var bfLat = vpLL.lat; bfLat <= vpUR.lat; bfLat += subSize)
  2532. {
  2533. for(var bfLon = vpLL.lon; bfLon <= vpUR.lon; bfLon += subSize)
  2534. {
  2535. uroURBackfill_GetData(bfLon, bfLat, subSize);
  2536. }
  2537. }
  2538. uroBackfilling = false;
  2539. uroFilterURs();
  2540. }
  2541.  
  2542.  
  2543. function uroFilterURs()
  2544. {
  2545. if(uroFilterPreamble() == false) return;
  2546. uroRefreshUpdateRequestSessions();
  2547.  
  2548. var selectorResolver = document.getElementById('_selectURResolverID');
  2549. var selectorCommentUser = document.getElementById('_selectURUserID');
  2550. if(uroGetCBChecked('_cbURResolverIDFilter') == false)
  2551. {
  2552. while(selectorResolver.options.length > 0)
  2553. {
  2554. selectorResolver.options.remove(0);
  2555. }
  2556. }
  2557. if(uroGetCBChecked('_cbURUserIDFilter') == false)
  2558. {
  2559. while(selectorCommentUser.options.length > 0)
  2560. {
  2561. selectorCommentUser.options.remove(0);
  2562. }
  2563. }
  2564. if(Object.keys(W.model.updateRequestSessions.objects).length == 0)
  2565. {
  2566. return;
  2567. }
  2568.  
  2569. var commenterUser = null;
  2570. if(uroGetCBChecked('_cbURUserIDFilter') == true)
  2571. {
  2572. if(selectorCommentUser.options.length == 0)
  2573. {
  2574. uroUpdateUserList();
  2575. }
  2576. if(selectorCommentUser.selectedOptions[0] != undefined)
  2577. {
  2578. commenterUser = parseInt(selectorCommentUser.selectedOptions[0].value);
  2579. }
  2580. }
  2581. var resolverUser = null;
  2582. if(uroGetCBChecked('_cbURResolverIDFilter') == true)
  2583. {
  2584. if(selectorResolver.options.length == 0)
  2585. {
  2586. uroUpdateResolverList();
  2587. }
  2588. if(selectorResolver.selectedOptions[0] != undefined)
  2589. {
  2590. resolverUser = parseInt(selectorResolver.selectedOptions[0].value);
  2591. }
  2592. }
  2593. uroCustomMarkerList = [];
  2594. for (var urobj in W.model.mapUpdateRequests.objects)
  2595. {
  2596. var ureq = W.model.mapUpdateRequests.objects[urobj];
  2597. var urStyle = 'visible';
  2598. var cryosphere_link = false;
  2599. var wazeauto_ur = false;
  2600. var ukroadworks_ur = false;
  2601. var construction_ur = false;
  2602. var closure_ur = false;
  2603. var event_ur = false;
  2604. var note_ur = false;
  2605. var hasMyComments = false;
  2606. var nComments = 0;
  2607. var commentDaysOld = -1;
  2608. var desc = '';
  2609. if(ureq.attributes.description != null) desc = ureq.attributes.description.replace(/<\/?[^>]+(>|$)/g, "");
  2610. var ureqID = null;
  2611. if(ureq.fid == null) ureqID = ureq.attributes.id;
  2612. else ureqID = ureq.fid;
  2613.  
  2614. var customType = uroGetCustomType(ureqID);
  2615. if(customType == 0) ukroadworks_ur = true;
  2616. else if(customType == 1) construction_ur = true;
  2617. else if(customType == 2) closure_ur = true;
  2618. else if(customType == 3) event_ur = true;
  2619. else if(customType == 4) note_ur = true;
  2620. // check UR against current session ignore list...
  2621. if(uroIsOnIgnoreList(ureqID)) urStyle = 'hidden';
  2622.  
  2623. // check against closed/not identified filtering if enabled...
  2624. if(uroGetCBChecked('_cbFilterSolved') == true)
  2625. {
  2626. if(ureq.attributes.resolution == 0) urStyle = 'hidden';
  2627. }
  2628. if(uroGetCBChecked('_cbFilterUnidentified') == true)
  2629. {
  2630. if(ureq.attributes.resolution == 1) urStyle = 'hidden';
  2631. }
  2632. if((ureq.attributes.resolvedOn != null) && (uroGetCBChecked('_cbFilterClosedUR') == true))
  2633. {
  2634. urStyle = 'hidden';
  2635. }
  2636.  
  2637. if((ureq.attributes.resolvedOn == null) && (uroGetCBChecked('_cbFilterOpenUR') == true))
  2638. {
  2639. urStyle = 'hidden';
  2640. }
  2641.  
  2642. if(urStyle == 'visible')
  2643. {
  2644. // check UR against keyword filtering if enabled...
  2645. if(uroGetCBChecked('_cbURDescriptionMustBePresent') == true)
  2646. {
  2647. if(desc == '') urStyle = 'hidden';
  2648. }
  2649. if(uroGetCBChecked('_cbURDescriptionMustBeAbsent') == true)
  2650. {
  2651. if(desc != '') urStyle = 'hidden';
  2652. }
  2653. if(uroGetCBChecked('_cbEnableKeywordMustBePresent') == true)
  2654. {
  2655. if(!uroKeywordPresent(desc,uroGetElmValue('_textKeywordPresent'))) urStyle = 'hidden';
  2656. }
  2657. if(uroGetCBChecked('_cbEnableKeywordMustBeAbsent') == true)
  2658. {
  2659. if(uroKeywordPresent(desc,uroGetElmValue('_textKeywordAbsent'))) urStyle = 'hidden';
  2660. }
  2661. }
  2662.  
  2663. if(urStyle == 'visible')
  2664. {
  2665. // do age-based filtering if enabled
  2666. if(uroGetCBChecked('_cbEnableMinAgeFilter') == true)
  2667. {
  2668. if(uroGetURAge(ureq,0) < uroGetElmValue('_inputFilterMinDays')) urStyle = 'hidden';
  2669. }
  2670. if(uroGetCBChecked('_cbEnableMaxAgeFilter') == true)
  2671. {
  2672. if(uroGetURAge(ureq,0) > uroGetElmValue('_inputFilterMaxDays')) urStyle = 'hidden';
  2673. }
  2674. }
  2675. if(urStyle == 'visible')
  2676. {
  2677. if(resolverUser != null)
  2678. {
  2679. if(ureq.attributes.resolvedBy != resolverUser) urStyle = 'hidden';
  2680. }
  2681. }
  2682. if(urStyle == 'visible')
  2683. {
  2684. // do comments/following filtering
  2685. if(W.model.updateRequestSessions.objects[ureqID] != null)
  2686. {
  2687. nComments = W.model.updateRequestSessions.objects[ureqID].comments.length;
  2688. var commentDaysOld = -1;
  2689. if(uroGetCBChecked('_cbEnableMinCommentsFilter') == true)
  2690. {
  2691. if(nComments < uroGetElmValue('_inputFilterMinComments')) urStyle = 'hidden';
  2692. }
  2693. if(uroGetCBChecked('_cbEnableMaxCommentsFilter') == true)
  2694. {
  2695. if(nComments > uroGetElmValue('_inputFilterMaxComments')) urStyle = 'hidden';
  2696. }
  2697. if(nComments > 0)
  2698. {
  2699. var reporterIsLastCommenter = false;
  2700. if(W.model.updateRequestSessions.objects[ureqID].comments[nComments-1].userID == -1) reporterIsLastCommenter = true;
  2701. if(uroGetCBChecked('_cbHideIfReporterLastCommenter') == true)
  2702. {
  2703. if(reporterIsLastCommenter == true) urStyle = 'hidden';
  2704. }
  2705. else if(uroGetCBChecked('_cbHideIfReporterNotLastCommenter') == true)
  2706. {
  2707. if(reporterIsLastCommenter == false) urStyle = 'hidden';
  2708. }
  2709. hasMyComments = uroURHasMyComments(ureqID);
  2710. if(hasMyComments == false)
  2711. {
  2712. if(uroGetCBChecked('_cbHideAnyComments') == true) urStyle = 'hidden';
  2713. if(uroGetCBChecked('_cbHideIfNotLastCommenter') == true) urStyle = 'hidden';
  2714. }
  2715. else
  2716. {
  2717. if(uroGetCBChecked('_cbHideMyComments') == true) urStyle = 'hidden';
  2718. var userIsLastCommenter = false;
  2719. if(W.model.updateRequestSessions.objects[ureqID].comments[nComments-1].userID == uroUserID) userIsLastCommenter = true;
  2720. if(uroGetCBChecked('_cbHideIfLastCommenter') == true)
  2721. {
  2722. if(userIsLastCommenter == true) urStyle = 'hidden';
  2723. }
  2724. else if(uroGetCBChecked('_cbHideIfNotLastCommenter') == true)
  2725. {
  2726. if(userIsLastCommenter == false) urStyle = 'hidden';
  2727. }
  2728. }
  2729. commentDaysOld = uroGetCommentAge(W.model.updateRequestSessions.objects[ureqID].comments[nComments-1]);
  2730. if((uroGetCBChecked('_cbEnableCommentAgeFilter') == true) && (commentDaysOld != -1))
  2731. {
  2732. if(uroGetElmValue('_inputFilterCommentDays') < commentDaysOld) urStyle = 'hidden';
  2733. }
  2734. if((uroGetCBChecked('_cbEnableCommentAgeFilter2') == true) && (commentDaysOld != -1))
  2735. {
  2736. if(uroGetElmValue('_inputFilterCommentDays2') > commentDaysOld) urStyle = 'hidden';
  2737. }
  2738.  
  2739. if((commenterUser != null) && (urStyle != 'hidden'))
  2740. {
  2741. urStyle = 'hidden';
  2742. for(var cidx=0; cidx<nComments; cidx++)
  2743. {
  2744. if(W.model.updateRequestSessions.objects[ureqID].comments[cidx].userID == commenterUser)
  2745. {
  2746. urStyle = 'visible';
  2747. break;
  2748. }
  2749. }
  2750. }
  2751. }
  2752. else
  2753. {
  2754. if(uroGetCBChecked('_cbURUserIDFilter') == true)
  2755. {
  2756. urStyle = 'hidden';
  2757. }
  2758. }
  2759. if(W.model.updateRequestSessions.objects[ureqID].isFollowing == true)
  2760. {
  2761. if(uroGetCBChecked('_cbHideMyFollowed') == true) urStyle = 'hidden';
  2762. }
  2763. else
  2764. {
  2765. if(uroGetCBChecked('_cbHideMyUnfollowed') == true) urStyle = 'hidden';
  2766. }
  2767. }
  2768. }
  2769.  
  2770. if(urStyle == 'visible')
  2771. {
  2772. // Test for Waze automatic URs before any others - these always (?) get inserted as General Error URs,
  2773. // so we can't filter them by type...
  2774. if(desc.indexOf('Waze Automatic:') != -1)
  2775. {
  2776. wazeauto_ur = true;
  2777. }
  2778. if(wazeauto_ur == true)
  2779. {
  2780. if(uroGetCBChecked('_cbFilterWazeAuto') == true) urStyle = 'hidden';
  2781. }
  2782.  
  2783. else if(ukroadworks_ur == true)
  2784. {
  2785. if(uroGetCBChecked('_cbFilterRoadworks') == true) urStyle = 'hidden';
  2786. }
  2787. else if(construction_ur == true)
  2788. {
  2789. if(uroGetCBChecked('_cbFilterConstruction') == true) urStyle = 'hidden';
  2790. }
  2791. else if(closure_ur == true)
  2792. {
  2793. if(uroGetCBChecked('_cbFilterClosure') == true) urStyle = 'hidden';
  2794. }
  2795. else if(event_ur == true)
  2796. {
  2797. if(uroGetCBChecked('_cbFilterEvent') == true) urStyle = 'hidden';
  2798. }
  2799. else if(note_ur == true)
  2800. {
  2801. if(uroGetCBChecked('_cbFilterNote') == true) urStyle = 'hidden';
  2802. }
  2803.  
  2804. else if(ureq.attributes.type == 6)
  2805. {
  2806. if(uroGetCBChecked('_cbFilterIncorrectTurn') == true) urStyle = 'hidden';
  2807. }
  2808. else if(ureq.attributes.type == 7)
  2809. {
  2810. if (uroGetCBChecked('_cbFilterIncorrectAddress') == true) urStyle = 'hidden';
  2811. }
  2812. else if(ureq.attributes.type == 8)
  2813. {
  2814. if(uroGetCBChecked('_cbFilterIncorrectRoute') == true) urStyle = 'hidden';
  2815. }
  2816. else if(ureq.attributes.type == 9)
  2817. {
  2818. if(uroGetCBChecked('_cbFilterMissingRoundabout') == true) urStyle = 'hidden';
  2819. }
  2820. else if(ureq.attributes.type == 10)
  2821. {
  2822. if(uroGetCBChecked('_cbFilterGeneralError') == true) urStyle = 'hidden';
  2823. }
  2824. else if(ureq.attributes.type == 11)
  2825. {
  2826. if(uroGetCBChecked('_cbFilterTurnNotAllowed') == true) urStyle = 'hidden';
  2827. }
  2828. else if(ureq.attributes.type == 12)
  2829. {
  2830. if(uroGetCBChecked('_cbFilterIncorrectJunction') == true) urStyle = 'hidden';
  2831. }
  2832. else if(ureq.attributes.type == 13)
  2833. {
  2834. if(uroGetCBChecked('_cbFilterMissingBridgeOverpass') == true) urStyle = 'hidden';
  2835. }
  2836. else if(ureq.attributes.type == 14)
  2837. {
  2838. if(uroGetCBChecked('_cbFilterWrongDrivingDirection') == true) urStyle = 'hidden';
  2839. }
  2840. else if(ureq.attributes.type == 15)
  2841. {
  2842. if(uroGetCBChecked('_cbFilterMissingExit') == true) urStyle = 'hidden';
  2843. }
  2844. else if(ureq.attributes.type == 16)
  2845. {
  2846. if(uroGetCBChecked('_cbFilterMissingRoad') == true) urStyle = 'hidden';
  2847. }
  2848. else if(ureq.attributes.type == 18)
  2849. {
  2850. if(uroGetCBChecked('_cbFilterMissingLandmark') == true) urStyle = 'hidden';
  2851. }
  2852. else if(ureq.attributes.type == 19)
  2853. {
  2854. if(uroGetCBChecked('_cbFilterBlockedRoad') == true) urStyle = 'hidden';
  2855. }
  2856. else if(uroGetCBChecked('_cbFilterUndefined') == true) urStyle = 'hidden';
  2857. if(uroGetCBChecked('_cbInvertURFilter') == true)
  2858. {
  2859. if(urStyle == 'hidden') urStyle = 'visible';
  2860. else urStyle = 'hidden';
  2861. }
  2862. }
  2863.  
  2864. // filtering override for tagged URs
  2865. if(uroGetCBChecked('_cbNoFilterForTaggedURs') == true)
  2866. {
  2867. if(ukroadworks_ur == true)
  2868. {
  2869. if(uroGetCBChecked('_cbFilterRoadworks') == false) urStyle = 'visible';
  2870. }
  2871. else if(construction_ur == true)
  2872. {
  2873. if(uroGetCBChecked('_cbFilterConstruction') == false) urStyle = 'visible';
  2874. }
  2875. else if(closure_ur == true)
  2876. {
  2877. if(uroGetCBChecked('_cbFilterClosure') == false) urStyle = 'visible';
  2878. }
  2879. else if(event_ur == true)
  2880. {
  2881. if(uroGetCBChecked('_cbFilterEvent') == false) urStyle = 'visible';
  2882. }
  2883. else if(note_ur == true)
  2884. {
  2885. if(uroGetCBChecked('_cbFilterNote') == false) urStyle = 'visible';
  2886. }
  2887. }
  2888. W.map.updateRequestLayer.markers[urobj].icon.imageDiv.style.visibility = urStyle;
  2889. if(urStyle != 'hidden')
  2890. {
  2891. var customMarkerType = -1;
  2892. if(ukroadworks_ur == true) customMarkerType = 0;
  2893. if(construction_ur == true) customMarkerType = 1;
  2894. if(closure_ur == true) customMarkerType = 2;
  2895. if(event_ur == true) customMarkerType = 3;
  2896. if(note_ur == true) customMarkerType = 4;
  2897. uroAddCustomMarkers(ureqID,customMarkerType, hasMyComments, nComments);
  2898. }
  2899. }
  2900. uroRenderCustomMarkers();
  2901. }
  2902.  
  2903.  
  2904. function uroFilterProblems()
  2905. {
  2906. if(uroFilterPreamble() == false) return;
  2907. if((uroGetCBChecked('_cbMPNotClosedUserIDFilter') == false) && (uroGetCBChecked('_cbMPClosedUserIDFilter') == false))
  2908. {
  2909. var selector = document.getElementById('_selectMPUserID');
  2910. while(selector.options.length > 0)
  2911. {
  2912. selector.options.remove(0);
  2913. }
  2914. }
  2915.  
  2916. var solverUser = null;
  2917. if((uroGetCBChecked('_cbMPNotClosedUserIDFilter') == true) || (uroGetCBChecked('_cbMPClosedUserIDFilter') == true))
  2918. {
  2919. var selector = document.getElementById('_selectMPUserID');
  2920. if(selector.options.length == 0)
  2921. {
  2922. uroUpdateMPSolverList();
  2923. }
  2924. if(selector.selectedOptions[0] != undefined)
  2925. {
  2926. solverUser = parseInt(selector.selectedOptions[0].value);
  2927. }
  2928. }
  2929.  
  2930. for (var urobj in W.model.problems.objects)
  2931. {
  2932. var problem = W.model.problems.objects[urobj];
  2933. var problemStyle = 'visible';
  2934.  
  2935. // check problem against current session ignore list...
  2936. if(uroIsOnIgnoreList(problem.attributes.id)) problemStyle = 'hidden';
  2937.  
  2938. // check against closed/not identified filtering if enabled...
  2939. var problem_marker_img = '';
  2940. if(problem.geometry.id != null)
  2941. {
  2942. if(document.getElementById(problem.geometry.id) != null)
  2943. {
  2944. problem_marker_img = document.getElementById(problem.geometry.id).href.baseVal;
  2945. if(uroGetCBChecked('_cbMPFilterSolved') == true)
  2946. {
  2947. if(problem_marker_img.indexOf('_solved') != -1) problemStyle = 'hidden';
  2948. }
  2949. if(uroGetCBChecked('_cbMPFilterUnidentified') == true)
  2950. {
  2951. if(problem_marker_img.indexOf('_rejected') != -1) problemStyle = 'hidden';
  2952. }
  2953. }
  2954. }
  2955. if(uroGetCBChecked('_cbMPFilterClosed') == true)
  2956. {
  2957. if(problem.attributes.open == false)
  2958. {
  2959. problemStyle = 'hidden';
  2960. }
  2961. }
  2962. if(problemStyle == 'visible')
  2963. {
  2964. if(solverUser != null)
  2965. {
  2966. if((uroGetCBChecked('_cbMPNotClosedUserIDFilter') == true) && (problem.attributes.resolvedBy == solverUser)) problemStyle = 'hidden';
  2967. if((uroGetCBChecked('_cbMPClosedUserIDFilter') == true) && (problem.attributes.resolvedBy != solverUser)) problemStyle = 'hidden';
  2968. }
  2969. }
  2970. if(problemStyle == 'visible')
  2971. {
  2972. var problemType = null;
  2973. if(uroDOMHasTurnProblems)
  2974. {
  2975. problemType = problem.attributes.problemType;
  2976. }
  2977. else
  2978. {
  2979. problemType = problem.attributes.subType;
  2980. }
  2981. if(problemType == 101)
  2982. {
  2983. if(uroGetCBChecked('_cbMPFilterDrivingDirectionMismatch') == true) problemStyle = 'hidden';
  2984. }
  2985. else if(problemType == 102)
  2986. {
  2987. if(uroGetCBChecked('_cbMPFilterMissingJunction') == true) problemStyle = 'hidden';
  2988. }
  2989. else if(problemType == 103)
  2990. {
  2991. if(uroGetCBChecked('_cbMPFilterMissingRoad') == true) problemStyle = 'hidden';
  2992. }
  2993. else if(problemType == 104)
  2994. {
  2995. if(uroGetCBChecked('_cbMPFilterCrossroadsJunctionMissing') == true) problemStyle = 'hidden';
  2996. }
  2997. else if(problemType == 105)
  2998. {
  2999. if(uroGetCBChecked('_cbMPFilterRoadTypeMismatch') == true) problemStyle = 'hidden';
  3000. }
  3001. else if(problemType == 106)
  3002. {
  3003. if(uroGetCBChecked('_cbMPFilterRestrictedTurn') == true) problemStyle = 'hidden';
  3004. }
  3005. else if(problemType == 200)
  3006. {
  3007. if(uroGetCBChecked('_cbMPFilterTurnProblem') == true) problemStyle = 'hidden';
  3008. }
  3009. else if(uroGetCBChecked('_cbMPFilterUnknownProblem') == true) problemStyle = 'hidden';
  3010. if(uroGetCBChecked('_cbMPFilterReopenedProblem') == true)
  3011. {
  3012. if((problem.attributes.open == true) && (problem.attributes.resolvedOn != null))
  3013. {
  3014. problemStyle = 'hidden';
  3015. }
  3016. }
  3017. if(uroGetCBChecked('_cbInvertMPFilter') == true)
  3018. {
  3019. if(problemStyle == 'hidden') problemStyle = 'visible';
  3020. else problemStyle = 'hidden';
  3021. }
  3022. if(problem.attributes.weight <= 3)
  3023. {
  3024. if(uroGetCBChecked('_cbMPFilterLowSeverity') == true) problemStyle = 'hidden';
  3025. }
  3026. else if(problem.attributes.weight <= 7)
  3027. {
  3028. if(uroGetCBChecked('_cbMPFilterMediumSeverity') == true) problemStyle = 'hidden';
  3029. }
  3030. else if(uroGetCBChecked('_cbMPFilterHighSeverity') == true) problemStyle = 'hidden';
  3031. }
  3032. W.map.problemLayer.markers[urobj].icon.imageDiv.style.visibility = problemStyle;
  3033. }
  3034.  
  3035. if(uroDOMHasTurnProblems)
  3036. {
  3037. for (var urobj in W.model.turnProblems.objects)
  3038. {
  3039. var problem = W.model.turnProblems.objects[urobj];
  3040. var problemStyle = 'visible';
  3041.  
  3042. // check problem against current session ignore list...
  3043. if(uroIsOnIgnoreList(problem.attributes.id)) problemStyle = 'hidden';
  3044.  
  3045. // check against closed/not identified filtering if enabled...
  3046. var problem_marker_img = '';
  3047. if(problem.geometry.id != null)
  3048. {
  3049. if(document.getElementById(problem.geometry.id) != null)
  3050. {
  3051. problem_marker_img = document.getElementById(problem.geometry.id).href.baseVal;
  3052. if(uroGetCBChecked('_cbMPFilterSolved') == true)
  3053. {
  3054. if(problem_marker_img.indexOf('_solved') != -1) problemStyle = 'hidden';
  3055. }
  3056. if(uroGetCBChecked('_cbMPFilterUnidentified') == true)
  3057. {
  3058. if(problem_marker_img.indexOf('_rejected') != -1) problemStyle = 'hidden';
  3059. }
  3060. }
  3061. }
  3062.  
  3063. if(uroGetCBChecked('_cbMPFilterClosed') == true)
  3064. {
  3065. if(problem.attributes.open == false)
  3066. {
  3067. problemStyle = 'hidden';
  3068. }
  3069. }
  3070. if(problemStyle == 'visible')
  3071. {
  3072. if(uroGetCBChecked('_cbMPFilterTurnProblem') == true) problemStyle = 'hidden';
  3073. if(uroGetCBChecked('_cbMPFilterReopenedProblem') == true)
  3074. {
  3075. if((problem.attributes.open == true) && (problem.attributes.resolvedOn != null))
  3076. {
  3077. problemStyle = 'hidden';
  3078. }
  3079. }
  3080. if(uroGetCBChecked('_cbInvertMPFilter') == true)
  3081. {
  3082. if(problemStyle == 'hidden') problemStyle = 'visible';
  3083. else problemStyle = 'hidden';
  3084. }
  3085. }
  3086. W.map.problemLayer.markers[urobj].icon.imageDiv.style.visibility = problemStyle;
  3087. }
  3088. }
  3089. }
  3090.  
  3091. function uroToHex(decValue,digits)
  3092. {
  3093. var modifier = 1;
  3094. for(var i=0; i<digits; i++)
  3095. {
  3096. modifier *= 16;
  3097. }
  3098. decValue = parseInt(decValue);
  3099. decValue += modifier;
  3100. var retval = decValue.toString(16);
  3101. retval = retval.substr(-digits);
  3102. retval = retval.toUpperCase();
  3103. return retval;
  3104. }
  3105.  
  3106. function uroFilterPreamble()
  3107. {
  3108. var mapviewport = document.getElementsByClassName("olMapViewport")[0];
  3109. if(mapviewport == null)
  3110. {
  3111. if(uroNullMapViewport == false)
  3112. {
  3113. uroAddLog('caught null mapviewport');
  3114. uroNullMapViewport = true;
  3115. }
  3116. return false;
  3117. }
  3118. uroNullMapViewport = false;
  3119. if(uroGetCBChecked('_cbWhiteBackground'))
  3120. {
  3121. var customColour = '#' + uroToHex(uroGetElmValue('_inputCustomBackgroundRed'),2);
  3122. customColour += uroToHex(uroGetElmValue('_inputCustomBackgroundGreen'),2);
  3123. customColour += uroToHex(uroGetElmValue('_inputCustomBackgroundBlue'),2);
  3124. mapviewport.style.backgroundColor = customColour;
  3125. }
  3126. else
  3127. {
  3128. mapviewport.style.backgroundColor = "#C2C2C2";
  3129. }
  3130. if(uroGetCBChecked('_cbHideAMLayer'))
  3131. {
  3132. W.map.managedAreasLayer.setOpacity(0);
  3133. }
  3134. else
  3135. {
  3136. W.map.managedAreasLayer.setOpacity(1);
  3137. }
  3138. return true;
  3139. }
  3140.  
  3141. function uroFilterItems_URTabClick()
  3142. {
  3143. uroFilterURs();
  3144. }
  3145. function uroFilterItems_MPTabClick()
  3146. {
  3147. uroFilterProblems();
  3148. }
  3149. function uroFilterItems_PlacesTabClick()
  3150. {
  3151. uroFilterPlaces();
  3152. }
  3153. function uroFilterItems_CamerasTabClick()
  3154. {
  3155. uroFilterCameras();
  3156. }
  3157. function uroFilterItems_MiscTabClick()
  3158. {
  3159. uroFilterItems();
  3160. }
  3161.  
  3162. function uroFilterItems()
  3163. {
  3164. uroFilterProblems();
  3165. uroFilterPlaces();
  3166. uroFilterCameras();
  3167. uroFilterURs();
  3168. }
  3169. function uroFilterItemsOnMove()
  3170. {
  3171. W.map.events.unregister('mousemove',null,uroFilterItemsOnMove);
  3172. uroFilterItems();
  3173. }
  3174.  
  3175.  
  3176. function uroDeleteObject()
  3177. {
  3178. uroAddLog('delete camera ID '+uroShownFID);
  3179. if(W.model.cameras.objects[uroShownFID] == null)
  3180. {
  3181. uroAddLog('camera object not found...');
  3182. return false;
  3183. }
  3184.  
  3185. uroRemoveCamFromWatchList();
  3186.  
  3187. var actionObj = require('Waze/Action/DeleteObject');
  3188. deleteAction = new actionObj(W.model.cameras.objects[uroShownFID], null);
  3189. W.model.actionManager.add(deleteAction);
  3190. uroExitPopup();
  3191. return false;
  3192. }
  3193.  
  3194.  
  3195. function uroGetUserNameAndRank(userID)
  3196. {
  3197. var userName;
  3198. var userLevel;
  3199. if(W.model.users.objects[userID] != undefined)
  3200. {
  3201. userName = W.model.users.objects[userID].userName;
  3202. userLevel = W.model.users.objects[userID].rank + 1;
  3203. }
  3204. else
  3205. {
  3206. userName = userID;
  3207. userLevel = '?';
  3208. }
  3209. return userName + ' (' + userLevel + ')';
  3210. }
  3211.  
  3212.  
  3213. function uroCheckCommentsForKeyword(idSrc, keyword)
  3214. {
  3215. var ursObj = W.model.updateRequestSessions.objects[idSrc];
  3216. if(typeof(ursObj) == 'undefined') return false;
  3217. if(ursObj.comments.length == 0) return false;
  3218. for(var idx=0; idx<ursObj.comments.length; idx++)
  3219. {
  3220. if(ursObj.comments[idx].text.indexOf(keyword) != -1)
  3221. {
  3222. return true;
  3223. }
  3224. }
  3225. return false;
  3226. }
  3227.  
  3228.  
  3229. function uroGetCustomMarkerIdx(customType)
  3230. {
  3231. if(customType == 0) return 3;
  3232. if(customType == 1) return 3;
  3233. if(customType == 2) return 5;
  3234. if(customType == 3) return 7;
  3235. if(customType == 4) return 9;
  3236. return -1;
  3237. }
  3238.  
  3239. function uroGetCustomType(idSrc)
  3240. {
  3241. var ureq = W.model.mapUpdateRequests.objects[idSrc];
  3242. var desc = '';
  3243. if(ureq.attributes.description != null)
  3244. {
  3245. desc = ureq.attributes.description;
  3246. if(desc.indexOf('[ROADWORKS]') != -1) return 0;
  3247. if(desc.indexOf('[CONSTRUCTION]') != -1) return 1;
  3248. if(desc.indexOf('[CLOSURE]') != -1) return 2;
  3249. if(desc.indexOf('[EVENT]') != -1) return 3;
  3250. if(desc.indexOf('[NOTE]') != -1) return 4;
  3251. }
  3252. if(uroCheckCommentsForKeyword(idSrc,'[ROADWORKS]')) return 0;
  3253. if(uroCheckCommentsForKeyword(idSrc,'[CONSTRUCTION]')) return 1;
  3254. if(uroCheckCommentsForKeyword(idSrc,'[CLOSURE]')) return 2;
  3255. if(uroCheckCommentsForKeyword(idSrc,'[EVENT]')) return 3;
  3256. if(uroCheckCommentsForKeyword(idSrc,'[NOTE]')) return 4;
  3257.  
  3258. return -1;
  3259. }
  3260.  
  3261.  
  3262. function uroFormatRestriction(restObj)
  3263. {
  3264. var retval = '<tr>';
  3265. retval += '<td style="text-align:center;">';
  3266. if((restObj.days & 1) == 1) retval += 'S';
  3267. else retval += '-';
  3268. retval += '</td><td style="text-align:center;">';
  3269. if((restObj.days & 2) == 2) retval += 'M';
  3270. else retval += '-';
  3271. retval += '</td><td style="text-align:center;">';
  3272. if((restObj.days & 4) == 4) retval += 'T';
  3273. else retval += '-';
  3274. retval += '</td><td style="text-align:center;">';
  3275. if((restObj.days & 8) == 8) retval += 'W';
  3276. else retval += '-';
  3277. retval += '</td><td style="text-align:center;">';
  3278. if((restObj.days & 16) == 16) retval += 'T';
  3279. else retval += '-';
  3280. retval += '</td><td style="text-align:center;">';
  3281. if((restObj.days & 32) == 32) retval += 'F';
  3282. else retval += '-';
  3283. retval += '</td><td style="text-align:center;">';
  3284. if((restObj.days & 64) == 64) retval += 'S';
  3285. else retval += '-';
  3286. retval += '</td><td>';
  3287. if(restObj.fromDate == null) retval += 'All dates';
  3288. else retval += restObj.fromDate+' to '+restObj.toDate;
  3289. retval += '</td><td>';
  3290.  
  3291. if(restObj.allDay == true) retval += 'All day';
  3292. else retval += restObj.fromTime+' to '+restObj.toTime;
  3293. retval += '</td><td>';
  3294. if(restObj.allVehicleTypes == restObj.vehicleTypes) retval += 'All vehicles';
  3295. else retval += 'Some vehicles';
  3296. retval += '</td><td>';
  3297. var desc = restObj.description.replace(/<\/?[^>]+(>|$)/g, "");
  3298. desc = uroClickify(desc);
  3299. retval += desc;
  3300. retval += '</td></tr>';
  3301. return retval;
  3302. }
  3303.  
  3304. function uroHidePopup()
  3305. {
  3306. uroDiv.style.visibility = 'hidden';
  3307. uroPopupShown = false;
  3308. uroPopupTimer = -2;
  3309. uroShownFID = -1;
  3310. }
  3311.  
  3312. function uroRecentreSessionOnUR()
  3313. {
  3314. W.map.updateRequestLayer.markers[uroShownFID].icon.imageDiv.click();
  3315. W.map.moveTo(W.map.updateRequestLayer.markers[uroShownFID].lonlat, 5);
  3316. uroHidePopup();
  3317. return false;
  3318. }
  3319.  
  3320. function uroRecentreSessionOnMP()
  3321. {
  3322. W.map.problemLayer.markers[uroShownFID].icon.imageDiv.click();
  3323. W.map.moveTo(W.map.problemLayer.markers[uroShownFID].lonlat, 5);
  3324. uroHidePopup();
  3325. return false;
  3326. }
  3327.  
  3328. function uroRecentreSessionOnPUR()
  3329. {
  3330. W.map.placeUpdatesLayer.markers[uroShownFID].icon.imageDiv.click()
  3331. W.map.moveTo(W.map.placeUpdatesLayer.markers[uroShownFID].lonlat, 5);
  3332. uroHidePopup();
  3333. return false;
  3334. }
  3335.  
  3336.  
  3337. function uroParsePxString(pxString)
  3338. {
  3339. return parseInt(pxString.split("px")[0]);
  3340. }
  3341.  
  3342. function uroStackListObj(fid,x,y)
  3343. {
  3344. this.fid = fid;
  3345. this.x = uroTypeCast(x);
  3346. this.y = uroTypeCast(y);
  3347. }
  3348.  
  3349. function uroRestackMarkers()
  3350. {
  3351. if(uroStackList.length == 0) return;
  3352.  
  3353. if(uroStackType == 1) markerCollection = W.map.updateRequestLayer.markers;
  3354. else if(uroStackType == 2) markerCollection = W.map.problemLayer.markers;
  3355. else if(uroStackType == 3) markerCollection = W.map.placeUpdatesLayer.markers;
  3356.  
  3357. for(var idx=0; idx<uroStackList.length; idx++)
  3358. {
  3359. var orig_x = uroStackList[idx].x + 'px';
  3360. var orig_y = uroStackList[idx].y + 'px';
  3361. var fid = uroStackList[idx].fid;
  3362. if(markerCollection[fid] != undefined)
  3363. {
  3364. markerCollection[fid].icon.imageDiv.style.left = orig_x;
  3365. markerCollection[fid].icon.imageDiv.style.top = orig_y;
  3366. }
  3367. }
  3368. uroStackList = new Array();
  3369. uroUnstackedMasterID = null;
  3370. uroStackType = null;
  3371. }
  3372.  
  3373. function uroIsIDAlreadyUnstacked(idSrc)
  3374. {
  3375. if(uroStackList.length == 0) return false;
  3376. for(var idx=0; idx<uroStackList.length; idx++)
  3377. {
  3378. if(uroStackList[idx].fid == idSrc) return true;
  3379. }
  3380. return false;
  3381. }
  3382.  
  3383. function uroCheckStacking(stackType, masterID, unstackedX, unstackedY)
  3384. {
  3385. if(W.map.getZoom() < uroGetElmValue('_inputUnstackZoomLevel')) return;
  3386. if(uroIsIDAlreadyUnstacked(masterID) == true) return;
  3387. uroAddLog('checking for marker stack, type '+stackType+'...');
  3388. var stackList = new Array();
  3389. var threshSquared = uroGetElmValue('_inputUnstackSensitivity');
  3390. threshSquared *= threshSquared;
  3391. if(stackType == 1) markerCollection = W.map.updateRequestLayer.markers;
  3392. else if(stackType == 2) markerCollection = W.map.problemLayer.markers;
  3393. else if(stackType == 3) markerCollection = W.map.placeUpdatesLayer.markers;
  3394. for(var marker in markerCollection)
  3395. {
  3396. testMarkerObj = markerCollection[marker];
  3397. if(testMarkerObj.icon.imageDiv.style.visibility != 'hidden')
  3398. {
  3399. if(testMarkerObj.id != masterID)
  3400. {
  3401. var xdiff = unstackedX - uroParsePxString(markerCollection[testMarkerObj.id].icon.imageDiv.style.left);
  3402. var ydiff = unstackedY - uroParsePxString(markerCollection[testMarkerObj.id].icon.imageDiv.style.top);
  3403. var distSquared = ((xdiff * xdiff) + (ydiff * ydiff));
  3404. if(distSquared < threshSquared)
  3405. {
  3406. stackList.push(testMarkerObj.id);
  3407. }
  3408. }
  3409. }
  3410. }
  3411. if(stackList.length > 0)
  3412. {
  3413. uroAddLog('markers are stacked!');
  3414. if(uroUnstackedMasterID != masterID)
  3415. {
  3416. uroAddLog('unstacked ID mismatch, relocating markers...');
  3417. uroRestackMarkers();
  3418. uroStackType = stackType;
  3419. uroUnstackedMasterID = masterID;
  3420. uroStackList = new Array();
  3421.  
  3422. // push the highlighted marker onto the stacklist so uroIsIDAlreadyUnstacked() will return true
  3423. uroStackList.push(new uroStackListObj(masterID,unstackedX,unstackedY));
  3424. for(var shoveIdx=0; shoveIdx < stackList.length; shoveIdx++)
  3425. {
  3426. var fid = stackList[shoveIdx];
  3427. var x = uroParsePxString(markerCollection[fid].icon.imageDiv.style.left);
  3428. var y = uroParsePxString(markerCollection[fid].icon.imageDiv.style.top);
  3429. // store the unstacked marker positions so they can be reinstated later
  3430. uroStackList.push(new uroStackListObj(fid,x,y));
  3431. unstackedX += 10;
  3432. unstackedY -= 30;
  3433. markerCollection[fid].icon.imageDiv.style.left = unstackedX + 'px';
  3434. markerCollection[fid].icon.imageDiv.style.top = unstackedY + 'px';
  3435. }
  3436. // hide other markers to prevent confusion with the unstacked markers
  3437. for(var marker in markerCollection)
  3438. {
  3439. var toHideID = markerCollection[marker].id;
  3440. if(uroIsIDAlreadyUnstacked(toHideID) == false)
  3441. {
  3442. markerCollection[toHideID].icon.imageDiv.style.visibility = 'hidden';
  3443. }
  3444. }
  3445. }
  3446. }
  3447. else
  3448. {
  3449. uroRestackMarkers();
  3450. }
  3451. }
  3452.  
  3453. function uroNewLookHighlightedItemsCheck(e)
  3454. {
  3455. if((uroMouseIsDown) && (e.buttons == 0))
  3456. {
  3457. uroAddLog('trapped erroneous mousedown state');
  3458. uroMouseIsDown = false;
  3459. }
  3460. if(uroMouseIsDown)
  3461. {
  3462. return;
  3463. }
  3464. if(W.geometryEditing.activeEditor != null)
  3465. {
  3466. uroHidePopup();
  3467. return;
  3468. }
  3469.  
  3470. if(OpenLayers == null)
  3471. {
  3472. if(uroNullOpenLayers == false)
  3473. {
  3474. uroAddLog('caught null OpenLayers');
  3475. uroNullOpenLayers = true;
  3476. }
  3477. return;
  3478. }
  3479. uroNullOpenLayers = false;
  3480.  
  3481. var rc = document.getElementById(uroRootContainer);
  3482. if(rc == null)
  3483. {
  3484. if(uroNullRootContainer == false)
  3485. {
  3486. uroAddLog('caught null rootContainer');
  3487. uroNullRootContainer = true
  3488. }
  3489. return;
  3490. }
  3491. uroNullRootContainer = false;
  3492. if(W.map.updateRequestLayer == null)
  3493. {
  3494. if(uroNullURLayer == false)
  3495. {
  3496. uroAddLog('caught null UR layer');
  3497. uroNullURLayer = true;
  3498. }
  3499. return;
  3500. }
  3501. uroNullURLayer = false;
  3502.  
  3503. if(W.map.problemLayer == null)
  3504. {
  3505. if(uroNullProblemLayer == false)
  3506. {
  3507. uroAddLog('caught null problem layer');
  3508. uroNullProblemLayer = true;
  3509. }
  3510. return;
  3511. }
  3512. uroNullProblemLayer = false;
  3513.  
  3514. var mouseX = e.pageX - document.getElementById('map').getBoundingClientRect().left;
  3515. var mouseY = e.pageY - document.getElementById('map').getBoundingClientRect().top;
  3516. var currentItems = rc.getElementsByTagName('g');
  3517.  
  3518. var result = '';
  3519. var rw;
  3520. var rh;
  3521. var popup_loc = new OpenLayers.LonLat(0,0);
  3522. var objHasIgnoreLink = false;
  3523. var objHasDeleteLink = false;
  3524.  
  3525. var popupXOffset = uroParsePxString(window.getComputedStyle(document.getElementById('sidebar')).getPropertyValue("width"));
  3526. var popupYOffset = document.getElementsByClassName('waze-header')[0].clientHeight;
  3527. var uroPopupX = mouseX + popupXOffset;
  3528. var uroPopupY = mouseY + popupYOffset;
  3529. var objHasIgnoreLink = false;
  3530. var objHasDeleteLink = false;
  3531. var objHasAddWatchLink = false;
  3532. var objHasRemoveWatchLink = false;
  3533. var objHasUpdateWatchLink = false;
  3534. var objHasRecentreSessionLink = false;
  3535. var newPopupType = null;
  3536.  
  3537. // popup for segment restrictions
  3538. if(uroGetCBChecked('_cbInhibitSegPopup') == false)
  3539. {
  3540. for(var slIdx=0; slIdx < W.map.segmentLayer.features.length; slIdx++)
  3541. {
  3542. if(W.map.segmentLayer.features[slIdx].renderIntent == 'highlight')
  3543. {
  3544. var doPopUp = false;
  3545. if(W.map.segmentLayer.features[slIdx].fid == null) segObj = W.map.segmentLayer.features[slIdx].model;
  3546. else segObj = W.map.segmentLayer.features[slIdx];
  3547. result += '<table cellpadding=4 border=1">';
  3548. if(segObj.attributes.fwdRestrictions.length > 0)
  3549. {
  3550. doPopUp = true;
  3551. result += '<tr><td colspan=11><b>A-B restrictions:</b></td></tr>';
  3552. for(var idx = 0; idx < segObj.attributes.fwdRestrictions.length; idx++)
  3553. {
  3554. restObj = segObj.attributes.fwdRestrictions[idx];
  3555. result += uroFormatRestriction(restObj);
  3556. }
  3557. }
  3558. if (segObj.attributes.revRestrictions.length > 0)
  3559. {
  3560. doPopUp = true;
  3561. result += '<tr><td colspan=11><b>B-A restrictions:</b></td></tr>';
  3562. for(var idx = 0; idx < segObj.attributes.revRestrictions.length; idx++)
  3563. {
  3564. restObj = segObj.attributes.revRestrictions[idx];
  3565. result += uroFormatRestriction(restObj);
  3566. }
  3567. }
  3568. result += '</table>';
  3569. if(doPopUp == true)
  3570. {
  3571. if(segObj.attributes.id == null) uroFID = segObj.id;
  3572. else uroFID = segObj.attributes.id;
  3573. newPopupType = 'segment_restriction';
  3574. }
  3575. break;
  3576. }
  3577. }
  3578. }
  3579.  
  3580. // popup for restricted turns
  3581. /*
  3582. if(newPopupType == null)
  3583. {
  3584. var idSrc = null;
  3585.  
  3586. //if(uroGetCBChecked('_cbInhibitTurnsPopup') == false)
  3587. {
  3588. if(W.map.layers[uroTurnsLayerIdx].markers.length > 0)
  3589. {
  3590. for(var marker in W.map.layers[uroTurnsLayerIdx].markers)
  3591. {
  3592. markerObj = W.map.layers[uroTurnsLayerIdx].markers[marker];
  3593. markerImg = window.getComputedStyle(markerObj.icon.imageDiv.childNodes[0]).getPropertyValue("background-image");
  3594. markerPos = window.getComputedStyle(markerObj.icon.imageDiv.childNodes[0]).getPropertyValue("background-position");
  3595. markerPos = markerPos.split(' ');
  3596. markerPos = parseInt(markerPos[1].substr(0,markerPos[1].length-2));
  3597.  
  3598. var hovered = false;
  3599. if(markerImg.indexOf('turns-s32af5d033c.png') != -1)
  3600. {
  3601. if(markerPos == -235)
  3602. {
  3603. hovered = true;
  3604. }
  3605. }
  3606. if(hovered == true)
  3607. {
  3608. uroAddLog('hover over turn marker '+marker);
  3609. break;
  3610. }
  3611. }
  3612. }
  3613. }
  3614. }
  3615. */
  3616. // popup for landmarks
  3617. if((newPopupType == null) && (uroGetCBChecked('_cbInhibitLandmarkPopup') == false))
  3618. {
  3619. uroPlaceSelected = false;
  3620. for(var llFeatureIdx=0; llFeatureIdx < W.map.landmarkLayer.features.length; llFeatureIdx++)
  3621. {
  3622. var renderIntent = W.map.landmarkLayer.features[llFeatureIdx].renderIntent;
  3623. if(renderIntent == 'highlight')
  3624. {
  3625. if(W.map.landmarkLayer.features[llFeatureIdx].fid == null) venueObj = W.map.landmarkLayer.features[llFeatureIdx].model;
  3626. else venueObj = W.map.landmarkLayer.features[llFeatureIdx];
  3627. if(venueObj.geometry.id.indexOf('.Point_') != -1)
  3628. {
  3629. // override popup placement for point places
  3630. var placeXY = W.map.getPixelFromLonLat(venueObj.geometry.toLonLat());
  3631. uroPopupX = placeXY.x + popupXOffset + 10;
  3632. uroPopupY = placeXY.y + popupYOffset + 40;
  3633. }
  3634. result += '<b>';
  3635. if(venueObj.attributes.name == '') result += 'Unnamed landmark';
  3636. else result += venueObj.attributes.name;
  3637. result += '</b><br>';
  3638. for(var idx = 0; idx < venueObj.attributes.categories.length; idx++)
  3639. {
  3640. result += I18n.translations[I18n.locale].venues.categories[venueObj.attributes.categories[idx]] + '<br>';
  3641. }
  3642. if(venueObj.attributes.residential == true)
  3643. {
  3644. result += '<i>Private Place</i>';
  3645. }
  3646.  
  3647. newPopupType = 'venue';
  3648. if(venueObj.attributes.id == null) uroFID = venueObj.id;
  3649. else uroFID = venueObj.attributes.id;
  3650. break;
  3651. }
  3652. else if(renderIntent == 'select')
  3653. {
  3654. uroPlaceSelected = true;
  3655. }
  3656. }
  3657. }
  3658.  
  3659. // look for URs, place updates and problems
  3660. if(newPopupType == null)
  3661. {
  3662. var idSrc = null;
  3663. var divIdx = -1;
  3664. var isUR = false;
  3665. var isProblem = false;
  3666. var isTurnProb = false;
  3667. var isPlaceUpdate = false;
  3668.  
  3669. if(uroGetCBChecked('_cbInhibitURPopup') == false)
  3670. {
  3671. var hovered = false;
  3672. for(var marker in W.map.updateRequestLayer.markers)
  3673. {
  3674. markerObj = W.map.updateRequestLayer.markers[marker];
  3675. markerImg = markerObj.icon.$div.css('background-image');
  3676. markerPos = markerObj.icon.$div.css('background-position');
  3677. markerPos = markerPos.split(' ');
  3678. markerPos = parseInt(markerPos[1].substr(0,markerPos[1].length-2));
  3679. var urIDSrc = markerObj.id;
  3680. if(markerImg.indexOf('problems-s8f369ca968.png') != -1)
  3681. {
  3682. if((markerPos == -403) || (markerPos == -483) || (markerPos == -563) || (markerPos == -643))
  3683. {
  3684. hovered = true;
  3685. uroAddLog('UR image type 1');
  3686. }
  3687. }
  3688. else if(markerImg.indexOf('problems-se224ab677e.png') != -1)
  3689. {
  3690. if((markerPos == -40) || (markerPos == -160) || (markerPos == -200) || (markerPos == -240))
  3691. {
  3692. hovered = true;
  3693. uroAddLog('UR image type 2');
  3694. }
  3695. }
  3696. else
  3697. {
  3698. if(markerPos > -200)
  3699. {
  3700. hovered = true;
  3701. uroAddLog('UR image type 3');
  3702. }
  3703. }
  3704. if(hovered == true)
  3705. {
  3706. isUR = true;
  3707. newPopupType = 'ur';
  3708. uroAddLog('hover over UR ID '+urIDSrc);
  3709. var unstackedX = uroParsePxString(W.map.updateRequestLayer.markers[urIDSrc].icon.imageDiv.style.left);
  3710. var unstackedY = uroParsePxString(W.map.updateRequestLayer.markers[urIDSrc].icon.imageDiv.style.top);
  3711. // override popup base position
  3712. uroPopupX = unstackedX + popupXOffset + 20;
  3713. uroPopupY = unstackedY + popupYOffset + 40;
  3714. uroPopupX -= uroParsePxString(W.map.segmentLayer.div.style.left);
  3715. uroPopupY -= uroParsePxString(W.map.segmentLayer.div.style.top);
  3716. // check for stacking...
  3717. if(uroShownFID != idSrc)
  3718. {
  3719. uroCheckStacking(1,urIDSrc, unstackedX, unstackedY);
  3720. }
  3721. if(urIDSrc != uroCustomMarkerFID)
  3722. {
  3723. if(uroCustomMarkerFID != null)
  3724. {
  3725. var customIdx = uroGetCustomMarkerIdx(uroGetCustomType(uroCustomMarkerFID));
  3726. uroChangeCustomMarkers(uroCustomMarkerFID,false,customIdx);
  3727. uroCustomMarkerFID = null;
  3728. }
  3729. var customIdx = uroGetCustomMarkerIdx(uroGetCustomType(urIDSrc));
  3730. if(customIdx != -1)
  3731. {
  3732. uroCustomMarkerFID = urIDSrc;
  3733. uroChangeCustomMarkers(urIDSrc,hovered,customIdx);
  3734. }
  3735. }
  3736. idSrc = urIDSrc;
  3737. break;
  3738. }
  3739. }
  3740. if((hovered == false) && (uroStackType == 1))
  3741. {
  3742. uroRestackMarkers();
  3743. uroFilterURs();
  3744. }
  3745. if((idSrc == null) && (uroCustomMarkerFID != null))
  3746. {
  3747. var customIdx = uroGetCustomMarkerIdx(uroGetCustomType(uroCustomMarkerFID));
  3748. uroChangeCustomMarkers(uroCustomMarkerFID,false, customIdx);
  3749. uroCustomMarkerFID = null;
  3750. }
  3751. }
  3752.  
  3753. if((newPopupType == null) && (uroGetCBChecked('_cbInhibitPUPopup') == false))
  3754. {
  3755. var hovered = false;
  3756. for(var marker in W.map.placeUpdatesLayer.markers)
  3757. {
  3758. markerObj = W.map.placeUpdatesLayer.markers[marker];
  3759. markerImg = markerObj.icon.$div.css('background-image');
  3760. markerPos = markerObj.icon.$div.css('background-position');
  3761. markerPos = markerPos.split(' ');
  3762. markerPos = parseInt(markerPos[1].substr(0,markerPos[1].length-2));
  3763. if(markerImg.indexOf('placeUpdates-sb30471988c.png') != -1)
  3764. {
  3765. // absolute offsets: 0 = new place, -120 = flagged, -240 = new photo, -360 = updated details
  3766. // relative offsets: 0 = green, -40 = highlighted, -80 = default
  3767. if(((markerPos + 40) % 120) == 0)
  3768. {
  3769. hovered = true;
  3770. uroAddLog('PUR marker type 1');
  3771. }
  3772. }
  3773. //else if(markerImg.indexOf('placeUpdates-s1adde76ab2.png') != -1)
  3774. else if(markerImg.indexOf('placeUpdates-s2e8d9c5ce4.png') != -1)
  3775. {
  3776. if
  3777. (
  3778. (markerObj.icon.$div.css("filter") == "brightness(110%)") ||
  3779. (markerObj.icon.$div.css("webkit-filter") == "brightness(1.1)")
  3780. )
  3781. {
  3782. hovered = true;
  3783. uroAddLog('PUR marker type 2');
  3784. }
  3785. }
  3786. if(hovered == true)
  3787. {
  3788. var idSrc = markerObj.id;
  3789. var unstackedX = uroParsePxString(W.map.placeUpdatesLayer.markers[idSrc].icon.imageDiv.style.left);
  3790. var unstackedY = uroParsePxString(W.map.placeUpdatesLayer.markers[idSrc].icon.imageDiv.style.top);
  3791. // override popup base position
  3792. uroPopupX = unstackedX + popupXOffset + 20;
  3793. uroPopupY = unstackedY + popupYOffset + 40;
  3794. uroPopupX -= uroParsePxString(W.map.segmentLayer.div.style.left);
  3795. uroPopupY -= uroParsePxString(W.map.segmentLayer.div.style.top);
  3796.  
  3797. if(uroShownFID != idSrc)
  3798. {
  3799. // check for stacking...
  3800. uroCheckStacking(3,idSrc, unstackedX, unstackedY);
  3801. }
  3802. isPlaceUpdate = true;
  3803. newPopupType = 'pur';
  3804. uroAddLog('hover over placeUpdate ID '+idSrc);
  3805. break;
  3806. }
  3807. }
  3808. if((hovered == false) && (uroStackType == 3))
  3809. {
  3810. uroRestackMarkers();
  3811. uroFilterPlaces();
  3812. }
  3813. }
  3814.  
  3815. if((newPopupType == null) && (uroGetCBChecked('_cbInhibitMPPopup') == false))
  3816. {
  3817. var hovered = false;
  3818. for(var marker in W.map.problemLayer.markers)
  3819. {
  3820. markerObj = W.map.problemLayer.markers[marker];
  3821. markerImg = markerObj.icon.$div.css('background-image');
  3822. markerPos = markerObj.icon.$div.css('background-position');
  3823. markerPos = markerPos.split(' ');
  3824. markerPos = parseInt(markerPos[1].substr(0,markerPos[1].length-2));
  3825. if(markerImg.indexOf('problems-s8f369ca968.png') != -1)
  3826. {
  3827. if((markerPos == -65) || (markerPos == -145) || (markerPos == -225) || (markerPos == -305))
  3828. {
  3829. hovered = true;
  3830. uroAddLog('Problem image type 1');
  3831. }
  3832. }
  3833. else if(markerImg.indexOf('problems-se224ab677e.png') != -1)
  3834. {
  3835. if((markerPos == -320) || (markerPos == -560) || (markerPos == -520) || (markerPos == -440))
  3836. {
  3837. hovered = true;
  3838. uroAddLog('Problem image type 2');
  3839. }
  3840. }
  3841. else
  3842. {
  3843. if(markerPos > -200)
  3844. {
  3845. hovered = true;
  3846. uroAddLog('Problem image type 3');
  3847. }
  3848. }
  3849. if(hovered == true)
  3850. {
  3851. var idSrc = null;
  3852. if(markerObj.model.fid == null) idSrc = markerObj.id;
  3853. else idSrc = markerObj.model.fid;
  3854.  
  3855. var unstackedX = uroParsePxString(W.map.problemLayer.markers[idSrc].icon.imageDiv.style.left);
  3856. var unstackedY = uroParsePxString(W.map.problemLayer.markers[idSrc].icon.imageDiv.style.top);
  3857. // override popup base position
  3858. uroPopupX = unstackedX + popupXOffset + 20;
  3859. uroPopupY = unstackedY + popupYOffset + 40;
  3860. uroPopupX -= uroParsePxString(W.map.segmentLayer.div.style.left);
  3861. uroPopupY -= uroParsePxString(W.map.segmentLayer.div.style.top);
  3862. // check for stacking...
  3863. if(uroShownFID != idSrc)
  3864. {
  3865. uroCheckStacking(2,idSrc, unstackedX, unstackedY);
  3866. }
  3867. isProblem = true;
  3868. newPopupType = 'map_problem';
  3869. uroAddLog('hover over problem ID '+idSrc);
  3870.  
  3871. break;
  3872. }
  3873. }
  3874. if((hovered == false) && (uroStackType == 2))
  3875. {
  3876. uroRestackMarkers();
  3877. uroFilterProblems();
  3878. }
  3879. }
  3880.  
  3881. if (idSrc != null)
  3882. {
  3883. var ureq = null;
  3884. if(isUR) ureq = W.model.mapUpdateRequests.objects[idSrc];
  3885. else if(isProblem)
  3886. {
  3887. ureq = W.model.problems.objects[idSrc];
  3888. if(ureq == undefined)
  3889. {
  3890. if(uroDOMHasTurnProblems)
  3891. {
  3892. var ureq = W.model.turnProblems.objects[idSrc];
  3893. if(ureq != undefined) isTurnProb = true;
  3894. }
  3895. }
  3896. }
  3897. else if(isPlaceUpdate) ureq = W.map.placeUpdatesLayer.markers[idSrc].model;
  3898.  
  3899. var ureqID = null;
  3900. if(ureq.fid != null) ureqID = ureq.fid;
  3901. else if(ureq.id != null) ureqID = ureq.id;
  3902. else if(ureq.attributes.id != null) ureqID = ureq.attributes.id;
  3903. uroFID = ureqID;
  3904. }
  3905. else
  3906. {
  3907. uroFID = -1;
  3908. }
  3909.  
  3910. if((uroFID != uroShownFID) && (uroFID != -1))
  3911. {
  3912. if(isUR)
  3913. {
  3914. uroAddLog('building popup for UR '+idSrc);
  3915. result = '<b>Update Request ('+idSrc+'): ' + I18n.translations[I18n.locale].update_requests.types[ureq.attributes.type] + '</b><br>';
  3916. if(ureq.attributes.description != null)
  3917. {
  3918. var desc = ureq.attributes.description.replace(/<\/?[^>]+(>|$)/g, "");
  3919. if(desc != "null")
  3920. {
  3921. desc = uroClickify(desc);
  3922. result += desc + '<br>';
  3923. }
  3924. }
  3925.  
  3926. var uroDaysOld = uroGetURAge(ureq,0);
  3927. if(uroDaysOld != -1)
  3928. {
  3929. result += '<i>Submitted ' + uroParseDaysAgo(uroDaysOld) + ' ';
  3930. if(ureq.attributes.guestUserName != null)
  3931. {
  3932. result += 'via Livemap';
  3933. if(ureq.attributes.guestUserName != '')
  3934. {
  3935. result += ' by '+ureq.attributes.guestUserName.replace(/<\/?[^>]+(>|$)/g, "");
  3936. }
  3937. }
  3938. result += '</i>';
  3939. }
  3940. if(ureq.attributes.resolvedOn != null)
  3941. {
  3942. var uroDaysResolved = uroGetURAge(ureq,1);
  3943. if(uroDaysResolved != -1)
  3944. {
  3945. result += '<br><i>Closed (';
  3946. if(ureq.attributes.resolution == 0) result += 'solved';
  3947. else if(ureq.attributes.resolution == 1) result += 'not identified';
  3948. else result += 'unknown';
  3949. result += ') ' + uroParseDaysAgo(uroDaysResolved) + ' ';
  3950. if(ureq.attributes.resolvedBy != null)
  3951. {
  3952. result += ' by '+uroGetUserNameAndRank(ureq.attributes.resolvedBy);
  3953. }
  3954. result += '</i>';
  3955. }
  3956. }
  3957. if(W.model.updateRequestSessions.objects[ureqID] != null)
  3958. {
  3959. var hasMyComments = uroURHasMyComments(ureqID);
  3960. var nComments = W.model.updateRequestSessions.objects[ureqID].comments.length;
  3961. result += '<br>' + nComments + ' comment';
  3962. if(nComments != 1) result += 's';
  3963. if((hasMyComments == false) && (nComments > 0)) result += ' (none by me)';
  3964. if(nComments > 0)
  3965. {
  3966. var commentDaysOld = uroGetCommentAge(W.model.updateRequestSessions.objects[ureqID].comments[nComments-1]);
  3967. if(commentDaysOld != -1)
  3968. {
  3969. result += ', last update '+uroParseDaysAgo(commentDaysOld);
  3970. }
  3971. }
  3972. }
  3973. }
  3974. else if(isProblem)
  3975. {
  3976. uroAddLog('building popup for problem '+idSrc);
  3977. if(isTurnProb) result = '<b>Turn Problem ('+idSrc+'): ' + I18n.translations[I18n.locale].problems.types["turn"].title;
  3978. else
  3979. {
  3980. result = '<b>Map Problem ('+idSrc+'): ';
  3981. var problemType = null;
  3982. if(uroDOMHasTurnProblems)
  3983. {
  3984. problemType = ureq.attributes.problemType;
  3985. }
  3986. else
  3987. {
  3988. problemType = ureq.attributes.subType;
  3989. }
  3990. if(I18n.translations[I18n.locale].problems.types[problemType] == undefined) result += 'Unknown problem type ('+problemType+')';
  3991. else result += I18n.translations[I18n.locale].problems.types[problemType].title;
  3992. }
  3993. result += '</b><br>';
  3994. if(ureq.attributes.resolvedOn != null)
  3995. {
  3996. var uroDaysResolved = uroGetURAge(ureq,1);
  3997. if(uroDaysResolved != -1)
  3998. {
  3999. result += '<br><i>Closed ' + uroParseDaysAgo(uroDaysResolved) + ' ';
  4000. if(ureq.attributes.resolvedBy != null)
  4001. {
  4002. result += ' by '+uroGetUserNameAndRank(ureq.attributes.resolvedBy);
  4003. }
  4004. if((ureq.attributes.open == true) && (ureq.attributes.resolvedOn != null))
  4005. {
  4006. result += '<br>Reopened by Waze';
  4007. }
  4008. result += '</i>';
  4009. }
  4010. }
  4011. }
  4012. else if(isPlaceUpdate)
  4013. {
  4014. uroAddLog('building popup for placeUpdate '+idSrc);
  4015. result = '<b>';
  4016. if(ureq.attributes.name == '') result += 'Unnamed landmark';
  4017. else result += ureq.attributes.name;
  4018. result += '</b><br>';
  4019. for(var idx = 0; idx < ureq.attributes.categories.length; idx++)
  4020. {
  4021. result += I18n.translations[I18n.locale].venues.categories[ureq.attributes.categories[idx]];
  4022. }
  4023. if(ureq.attributes.residential == true)
  4024. {
  4025. result += '<br><i>Private Place</i>';
  4026. }
  4027.  
  4028. var daysOld = uroGetPURAge(ureq);
  4029. if(daysOld != -1)
  4030. {
  4031. result += '<br><i>Submitted '+uroParseDaysAgo(daysOld)+'</i>';
  4032. }
  4033. }
  4034.  
  4035. // add "open new WME tab" link
  4036. var urPos=new OpenLayers.LonLat();
  4037. if(isPlaceUpdate)
  4038. {
  4039. urPos=ureq.geometry.bounds.centerLonLat.clone();
  4040. }
  4041. else
  4042. {
  4043. urPos.lon=ureq.geometry.x;
  4044. urPos.lat=ureq.geometry.y;
  4045. }
  4046. urPos.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326"));
  4047. var urLink = document.location.href;
  4048. urLayers = '&layers='+W.map.mapState.getLayerVisibilityBitmask();
  4049. urLink = urLink.substr(0,urLink.indexOf('?zoom'));
  4050. urLink += '?zoom=5&lat='+urPos.lat+'&lon='+urPos.lon+urLayers;
  4051. if(isUR) urLink += '&mapUpdateRequest='+idSrc;
  4052. else if(isTurnProb) urLink += '&showturn='+idSrc+'&endshow';
  4053. else if(isProblem) urLink += '&mapProblem='+idSrc;
  4054. else if(isPlaceUpdate) urLink += '&showpur='+idSrc+'&endshow';
  4055. result += '<hr><ul><li><a href="'+urLink+'" target="_urTab">Open in new tab</a> - ';
  4056. //result += '<a href="'+urLink+'">open in current tab</a>';
  4057. result += '<a href="#" id="_recentreSession">centre in current tab</a>';
  4058. objHasRecentreSessionLink = true;
  4059.  
  4060. // add "open new livemap tab" link
  4061. var lmLink = null;
  4062. if(document.getElementsByClassName("waze-header-menu").length == 0)
  4063. {
  4064. uroAddLog('Livemap link in livemap element');
  4065. lmLink = document.getElementById('livemap').href;
  4066. }
  4067. else
  4068. {
  4069. uroAddLog('Livemap link in header menu, locating...');
  4070. var menuItems = document.getElementsByClassName("waze-header-menu")[0];
  4071. for(var miloop = 0; miloop<menuItems.childElementCount; miloop++)
  4072. {
  4073. if(menuItems.children[miloop].innerHTML.indexOf('livemap') != -1)
  4074. {
  4075. uroAddLog('found link in menu entry '+miloop);
  4076. lmLink = menuItems.children[miloop].getElementsByTagName('a')[0].href;
  4077. uroAddLog(lmLink);
  4078. }
  4079. }
  4080. }
  4081. if(lmLink != null)
  4082. {
  4083. var zpos = lmLink.indexOf('?');
  4084. if(zpos > -1) lmLink = lmLink.substr(0,zpos);
  4085. lmLink += '?zoom=17&lat='+urPos.lat+'&lon='+urPos.lon+'&layers=BTTTT';
  4086. result += '<li><a href="'+lmLink+'" target="_lmTab">Open in new livemap tab</a>';
  4087. }
  4088. if(!isPlaceUpdate)
  4089. {
  4090. // add "ignore for this session" link
  4091. result += '<li><a href="#" id="_addtoignore">Hide for this session</a></ul>';
  4092. objHasIgnoreLink = true;
  4093. }
  4094. }
  4095. }
  4096. // look for cameras
  4097. if((newPopupType == null) && (uroGetCBChecked('_cbInhibitCamPopup') == false))
  4098. {
  4099. for(var clFeatureIdx = 0; clFeatureIdx < W.map.camerasLayer.features.length; clFeatureIdx++)
  4100. {
  4101. if(W.map.camerasLayer.features[clFeatureIdx].renderIntent == 'highlight')
  4102. {
  4103. if(W.map.camerasLayer.features[clFeatureIdx].fid == null) ureq = W.map.camerasLayer.features[clFeatureIdx].model;
  4104. else ureq = W.map.camerasLayer.features[clFeatureIdx];
  4105.  
  4106. var ureqID = null;
  4107. if(ureq.fid == null) ureqID = ureq.attributes.id;
  4108. else ureqID = ureq.fid;
  4109. // test isSelected() so that we only do overview data on cameras that are being hovered over
  4110. if(ureq.isSelected() == false)
  4111. {
  4112. // override popup base position
  4113. var markerXY = W.map.getPixelFromLonLat(ureq.geometry.toLonLat());
  4114. uroPopupX = markerXY.x + popupXOffset + 20;
  4115. uroPopupY = markerXY.y + popupYOffset + 60;
  4116.  
  4117. newPopupType = 'camera';
  4118. uroFID = ureqID;
  4119. uroAddLog('generating popup for camera '+uroFID);
  4120. result += '<b>Camera: ' + ureq.TYPES[ureq.attributes.type] + '</b><br>';
  4121. result += 'ID: '+uroFID+'<br>';
  4122. result += 'Created by ';
  4123. if(W.model.users.get(ureq.attributes.createdBy) != null)
  4124. {
  4125. userID = ureq.attributes.createdBy;
  4126. result += uroGetUserNameAndRank(userID);
  4127. }
  4128. else result += 'unknown';
  4129. result += ', ';
  4130. var camAge = uroGetCameraAge(ureq,1);
  4131. if(camAge != -1)
  4132. {
  4133. result += uroParseDaysAgo(camAge);
  4134. }
  4135. else result += 'unknown days ago';
  4136.  
  4137. result += '<br>Updated by ';
  4138. if(W.model.users.get(ureq.attributes.updatedBy) != null)
  4139. {
  4140. userID = ureq.attributes.updatedBy;
  4141. userName = W.model.users.objects[userID].userName;
  4142. userLevel = W.model.users.objects[userID].rank + 1;
  4143. result += userName + ' (' + userLevel + ')';
  4144. }
  4145. else result += 'unknown';
  4146. result += ', ';
  4147. var camAge = uroGetCameraAge(ureq,0);
  4148. if(camAge != -1)
  4149. {
  4150. result += uroParseDaysAgo(camAge);
  4151. }
  4152. else result += 'unknown days ago';
  4153. result += '<br>Speed data: ';
  4154. if(ureq.attributes.speed != null)
  4155. {
  4156. result += ureq.attributes.speed + 'km/h';
  4157. var speedInMPH = Math.round(ureq.attributes.speed / 1.609);
  4158. result += ' (' + speedInMPH + 'mph';
  4159. if((speedInMPH % 10) != 0) result += ' - not valid?';
  4160. result += ')</i>';
  4161. }
  4162. else result += 'unknown';
  4163.  
  4164. var uid = W.model.loginManager.getLoggedInUser().id;
  4165. result += '<hr><ul>';
  4166. if(uroIsCamOnWatchList(uroFID) != -1)
  4167. {
  4168. result += '<li><a href="#" id="_updatewatchlist">Update watchlist entry</a>';
  4169. result += '<li><a href="#" id="_removefromwatchlist">Remove from watchlist</a>';
  4170. objHasUpdateWatchLink = true;
  4171. objHasRemoveWatchLink = true;
  4172. }
  4173. else
  4174. {
  4175. result += '<li><a href="#" id="_addtowatchlist">Add to watchlist</a>';
  4176. objHasAddWatchLink = true;
  4177. }
  4178.  
  4179. if(ureq.attributes.permissions != 0)
  4180. {
  4181. result += '<li><a href="#" id="_deleteobject">Delete Camera</a>';
  4182. objHasDeleteLink = true;
  4183. }
  4184. result += '</ul>';
  4185. }
  4186. break;
  4187. }
  4188. }
  4189. }
  4190. if(newPopupType != null)
  4191. {
  4192. if((uroFID != uroShownFID) || (newPopupType != uroShownPopupType))
  4193. {
  4194. if(uroFID != uroShownFID) uroAddLog('FID mismatch, show popup: '+uroFID+'/'+uroShownFID);
  4195. else uroAddLog('Popup type mismatch: '+newPopupType+'/'+uroShownPopupType);
  4196. uroShownFID = uroFID;
  4197. uroShownPopupType = newPopupType;
  4198. uroPopupShown = false;
  4199. }
  4200.  
  4201. if(uroPopupShown == false)
  4202. {
  4203. uroAddLog('display popup at '+uroPopupX+','+uroPopupY);
  4204. uroPopupShown = true;
  4205. uroDiv.innerHTML = result;
  4206. if((uroFID != -1) && (objHasIgnoreLink == true))
  4207. {
  4208. uroAddEventListener('_addtoignore','click', uroAddToIgnoreList, true);
  4209. }
  4210. if(objHasDeleteLink == true)
  4211. {
  4212. uroAddEventListener('_deleteobject','click', uroDeleteObject, true);
  4213. }
  4214. if(objHasRemoveWatchLink == true)
  4215. {
  4216. uroAddEventListener('_removefromwatchlist','click', uroRemoveCamFromWatchList, true);
  4217. }
  4218. if(objHasAddWatchLink == true)
  4219. {
  4220. uroAddEventListener('_addtowatchlist','click', uroAddCamToWatchList, true);
  4221. }
  4222. if(objHasUpdateWatchLink == true)
  4223. {
  4224. uroAddEventListener('_updatewatchlist','click', uroUpdateCamWatchList, true);
  4225. }
  4226. if(objHasRecentreSessionLink == true)
  4227. {
  4228. if(isUR) uroAddEventListener('_recentreSession','click', uroRecentreSessionOnUR, true);
  4229. else if((isProblem)||(isTurnProb)) uroAddEventListener('_recentreSession','click', uroRecentreSessionOnMP, true);
  4230. else if(isPlaceUpdate) uroAddEventListener('_recentreSession','click', uroRecentreSessionOnPUR, true);
  4231. }
  4232. rw = parseInt(uroDiv.clientWidth);
  4233. rh = parseInt(uroDiv.clientHeight);
  4234.  
  4235. if(rw > (window.innerWidth / 2)) rw = (window.innerWidth / 2);
  4236. if(rh > (window.innerHeight / 2)) rh = (window.innerHeight / 2);
  4237.  
  4238. if((uroPopupX + rw) > window.innerWidth)
  4239. {
  4240. uroPopupX -= (rw + 40);
  4241. if(uroPopupX < 0) uroPopupX = 0;
  4242. }
  4243. if((uroPopupY + rh) > window.innerHeight)
  4244. {
  4245. uroPopupY -= (rh + 10);
  4246. if(uroPopupY < 0) uroPopupY = 0;
  4247. }
  4248.  
  4249. uroDiv.style.top = uroPopupY+'px';
  4250. uroDiv.style.left = uroPopupX+'px';
  4251. uroDiv.clientWidth = rw+'px';
  4252. uroDiv.clientHeight = rh+'px';
  4253. uroDiv.style.visibility = 'visible';
  4254. }
  4255. uroPopupTimer = -1;
  4256. }
  4257. else
  4258. {
  4259. if(uroPopupTimer == -1)
  4260. {
  4261. uroPopupTimer = 2;
  4262. }
  4263. }
  4264. if(uroPopupTimer > 0)
  4265. {
  4266. if(uroMouseInPopup == false)
  4267. {
  4268. uroPopupTimer--;
  4269. }
  4270. }
  4271. if(uroPopupTimer == 0)
  4272. {
  4273. uroHidePopup();
  4274. }
  4275. }
  4276.  
  4277. function uroRestyleWMETabs()
  4278. {
  4279. var navTabs = document.getElementById(uroUserTabId).children[1].children;
  4280. for(var loop = 0; loop<navTabs.length; loop++)
  4281. {
  4282. navTabs[loop].children[0].style.padding = "4px";
  4283. }
  4284. setTimeout(uroRestyleWMETabs,1000);
  4285. }
  4286.  
  4287. function uroExclusiveCB()
  4288. {
  4289. cbChecked = uroGetCBChecked(this.id);
  4290. if(cbChecked == true)
  4291. {
  4292. if(this.id == '_cbHideMyComments') uroGetCBChecked('_cbHideAnyComments') = false;
  4293. if(this.id == '_cbHideAnyComments') uroGetCBChecked('_cbHideMyComments') = false;
  4294. if(this.id == '_cbHideIfLastCommenter') uroGetCBChecked('_cbHideIfNotLastCommenter') = false;
  4295. if(this.id == '_cbHideIfNotLastCommenter') uroGetCBChecked('_cbHideIfLastCommenter') = false;
  4296. if(this.id == '_cbHideIfReporterLastCommenter') uroGetCBChecked('_cbHideIfReporterNotLastCommenter') = false;
  4297. if(this.id == '_cbHideIfReporterNotLastCommenter') uroGetCBChecked('_cbHideIfReporterLastCommenter') = false;
  4298. }
  4299. }
  4300.  
  4301.  
  4302. function uroGetAMs(e)
  4303. {
  4304. var amList = '';
  4305. if(W.map.managedAreasLayer.getVisibility() == true)
  4306. {
  4307. var mouseX = e.pageX - document.getElementById('map').getBoundingClientRect().left;
  4308. var mouseY = e.pageY - document.getElementById('map').getBoundingClientRect().top - document.getElementById('toolbar').clientHeight;
  4309. var mousePixel = new OL.Pixel(mouseX, mouseY);
  4310. var mousePoint = W.map.getLonLatFromPixel(mousePixel).toPoint();
  4311.  
  4312. for(var amObj in W.model.managedAreas.objects)
  4313. {
  4314. if(W.model.managedAreas.objects[amObj].geometry.containsPoint(mousePoint))
  4315. {
  4316. if(amList != '') amList += ', ';
  4317. amList += uroGetUserNameAndRank(W.model.managedAreas.objects[amObj].userID);
  4318. }
  4319. }
  4320. if(amList == '')
  4321. {
  4322. amList = 'none';
  4323. }
  4324. amList = "<b>Area Managers:</b> "+amList;
  4325. }
  4326. document.getElementById("uroAMList").innerHTML = amList;
  4327. }
  4328.  
  4329.  
  4330. function uroMouseDown(e)
  4331. {
  4332. uroMouseIsDown = true;
  4333. }
  4334.  
  4335. function uroMouseUp(e)
  4336. {
  4337. uroMouseIsDown = false;
  4338. }
  4339.  
  4340. function uroUREvent_onObjectsChanged()
  4341. {
  4342. }
  4343.  
  4344. function uroUREvent_onObjectsAdded()
  4345. {
  4346. if(uroGetCBChecked('_cbURResolverIDFilter') == true)
  4347. {
  4348. uroUpdateResolverList();
  4349. }
  4350. uroFilterURs();
  4351. }
  4352.  
  4353. function uroUREvent_onObjectsRemoved()
  4354. {
  4355. }
  4356.  
  4357. function uroGetSelectedURCommentCount()
  4358. {
  4359. if(W.model.updateRequestSessions.objects[uroSelectedURID] != undefined)
  4360. {
  4361. var cachedCommentCount = W.model.updateRequestSessions.objects[uroSelectedURID].comments.length;
  4362. uroAddLog(uroSelectedURID+':'+cachedCommentCount+' '+uroExpectedCommentCount);
  4363. // if there aren't the same number of cached comments as there are comments in the UR dialog list, initiate
  4364. // a refresh of the comment data...
  4365. if(cachedCommentCount != uroExpectedCommentCount)
  4366. {
  4367. if(uroPendingCommentDataRefresh == true)
  4368. {
  4369. uroAddLog('updateRequestSessions refresh required for UR '+uroSelectedURID);
  4370. var idList = [];
  4371. idList.push(uroSelectedURID);
  4372. // need to delete the existing cache object first, as .get() is only capable of creating new objects,
  4373. // it doesn't seem able to update an existing object with new data
  4374. W.model.updateRequestSessions.remove(W.model.updateRequestSessions.objects[uroSelectedURID]);
  4375. W.model.updateRequestSessions.get(idList);
  4376. // the call to .get() initiates a XMLHttpRequest for the data, so we now need to switch modes - the
  4377. // refresh process has started so we're no longer pending, but we are now waiting for the XMLHttpRequest
  4378. // to return something...
  4379. uroPendingCommentDataRefresh = false;
  4380. uroWaitingCommentDataRefresh = true;
  4381. }
  4382. }
  4383. else
  4384. {
  4385. // if the WME session is loaded with a UR already selected, such that WME has opened the UR dialog as part
  4386. // of the session startup process, adding new comments to the UR cause the cached data to be updated immediately.
  4387. // This prevents URO+ from switching into waiting mode in the above block of code, so we have to instead do
  4388. // it here by comparing the cached count against the expected count following the Send click event.
  4389. if(cachedCommentCount >= uroExpectedCommentCount)
  4390. {
  4391. uroPendingCommentDataRefresh = false;
  4392. uroWaitingCommentDataRefresh = true;
  4393. uroExpectedCommentCount = null;
  4394. }
  4395. // once the cached data has been updated, refilter the URs so that the new comment count is taken into account
  4396. // immediately for filtering and display purposes
  4397. if(uroWaitingCommentDataRefresh == true)
  4398. {
  4399. uroWaitingCommentDataRefresh = false;
  4400. uroFilterURs();
  4401. uroAddLog('refresh complete');
  4402. }
  4403. }
  4404. }
  4405. }
  4406.  
  4407. function uroAddedComment()
  4408. {
  4409. // when the user clicks the Send button to submit a new UR comment, this event handler fires before the new comment is
  4410. // posted to the server and thus also before the comment list gets updated in the UR dialog. So we take the current
  4411. // comment count and, if the new comment edit box isn't empty, increment it by 1 to get the expected count. Then we
  4412. // set the pending flag true to initiate a session refresh on the next 100ms tick
  4413. uroExpectedCommentCount = W.map.panelRegion.currentView.conversationView.conversation.comments.length;
  4414. if(document.getElementsByClassName('new-comment-text')[0].value != '')
  4415. {
  4416. uroExpectedCommentCount++;
  4417. uroAddLog('new comment added to UR '+uroSelectedURID+', cache refresh required...');
  4418. uroPendingCommentDataRefresh = true;
  4419. }
  4420. else
  4421. {
  4422. uroPendingCommentDataRefresh = false;
  4423. }
  4424. }
  4425.  
  4426. function uroTenthSecondTick()
  4427. {
  4428. if(uroSetupListeners)
  4429. {
  4430. if((loginManager.isLoggedIn()) || (uroPracticeMode == true))
  4431. {
  4432. uroSetupListeners = false;
  4433. if(uroPracticeMode == true)
  4434. {
  4435. document.getElementsByClassName("sandbox")[0].style.display = "none";
  4436. }
  4437.  
  4438. // filter markers when the marker objects are modified (this happens whenever WME needs to load fresh marker data
  4439. // due to having panned/zoomed the map beyond the extents of the previously loaded data)
  4440. W.model.mapUpdateRequests.events.register("objectschanged", null, uroFilterURs_onObjectsChanged);
  4441. W.model.mapUpdateRequests.events.register("objectsadded", null, uroFilterURs_onObjectsAdded);
  4442. W.model.mapUpdateRequests.events.register("objectsremoved", null, uroFilterURs_onObjectsRemoved);
  4443.  
  4444. W.model.updateRequestSessions.events.register("objectschanged", null, uroUREvent_onObjectsChanged);
  4445. W.model.updateRequestSessions.events.register("objectsadded", null, uroUREvent_onObjectsAdded);
  4446. W.model.updateRequestSessions.events.register("objectsremoved", null, uroUREvent_onObjectsRemoved);
  4447.  
  4448. W.model.cameras.events.register("objectschanged", null, uroFilterCameras);
  4449. W.model.cameras.events.register("objectsadded", null, uroFilterCameras);
  4450. W.model.cameras.events.register("objectsremoved", null, uroFilterCameras);
  4451. W.model.problems.events.register("objectschanged", null, uroFilterProblems);
  4452. W.model.problems.events.register("objectsadded", null, uroFilterProblems);
  4453. W.model.problems.events.register("objectsremoved", null, uroFilterProblems);
  4454. W.model.venues.events.register("objectschanged", null, uroFilterPlaces);
  4455. W.model.venues.events.register("objectsadded", null, uroFilterPlaces);
  4456. W.model.venues.events.register("objectsremoved", null, uroFilterPlaces);
  4457.  
  4458. var userTabs = document.getElementById(uroUserTabId);
  4459. if(uroPracticeMode == false)
  4460. {
  4461. var navTabs = uroTimbonesGetElementsByClassName('nav-tabs', userTabs)[0];
  4462. var tabContent = uroTimbonesGetElementsByClassName('tab-content', userTabs)[0];
  4463. newtabUR = document.createElement('li');
  4464. newtabUR.innerHTML = '<a href="#sidepanel-uroverview" data-toggle="tab">URO+</a>';
  4465. navTabs.appendChild(newtabUR);
  4466. }
  4467. uroControls.id = "sidepanel-uroverview";
  4468. uroControls.className = "tab-pane";
  4469. if(uroPracticeMode == false)
  4470. {
  4471. tabContent.appendChild(uroControls);
  4472. }
  4473. else
  4474. {
  4475. userTabs.appendChild(uroControls);
  4476. }
  4477.  
  4478. uroAddEventListener('_btnUndoLastHide',"click", uroRemoveLastAddedIgnore, true);
  4479. uroAddEventListener('_btnClearSessionHides',"click", uroRemoveAllIgnores, true);
  4480. uroEnableIgnoreListControls();
  4481.  
  4482. uroAddEventListener('_btnClearCamWatchList',"click", uroClearCamWatchList, true);
  4483. uroAddEventListener('_btnSettingsToText',"click", uroSettingsToText, true);
  4484. uroAddEventListener('_btnTextToSettings',"click", uroTextToSettings, true);
  4485. uroAddEventListener('_btnClearSettingsText',"click", uroClearSettingsText, true);
  4486.  
  4487. uroSetOnClick("_linkSelectUserRequests",uroShowURTab);
  4488. uroSetOnClick("_linkSelectMapProblems",uroShowMPTab);
  4489. uroSetOnClick("_linkSelectPlaces",uroShowPlacesTab);
  4490. uroSetOnClick("_linkSelectCameras",uroShowCameraTab);
  4491. uroSetOnClick("_linkSelectMisc",uroShowMiscTab);
  4492. uroSetOnClick("_linkSelectOWL",uroShowOWLTab);
  4493.  
  4494. uroSetOnClick('_cbHideMyComments',uroExclusiveCB);
  4495. uroSetOnClick('_cbHideAnyComments',uroExclusiveCB);
  4496. uroSetOnClick('_cbHideIfLastCommenter',uroExclusiveCB);
  4497. uroSetOnClick('_cbHideIfNotLastCommenter',uroExclusiveCB);
  4498. uroSetOnClick('_cbHideIfReporterLastCommenter',uroExclusiveCB);
  4499. uroSetOnClick('_cbHideIfReporterNotLastCommenter',uroExclusiveCB);
  4500.  
  4501. var dbgMode = "none";
  4502. if(uroShowDebugOutput)
  4503. {
  4504. dbgMode = "inline";
  4505. }
  4506. document.getElementById('_uroDebugMode').style.display = dbgMode;
  4507. uroAddEventListener('_uroVersion',"click", uroToggleDebug, true);
  4508.  
  4509. uroAddLog('finalise onload');
  4510. uroLoadSettings();
  4511. uroNewLookCheckDetailsRequest();
  4512.  
  4513. if(uroGetCBChecked('_cbEnableDTE'))
  4514. {
  4515. if(dteControlsIdx != -1)
  4516. {
  4517. dteSetNewTabLength();
  4518. }
  4519. else
  4520. {
  4521. uroAddLog('ERROR - archive panel not found!');
  4522. uroSetStyleDisplay(uroUserTabId,'');
  4523. }
  4524. }
  4525.  
  4526. if(uroGetCBChecked('_cbEnableSRS'))
  4527. {
  4528. selectionManager.events.register("selectionchanged", null, srsCheckSidePanel);
  4529. uroAddLog('added SRS event handler');
  4530. }
  4531.  
  4532. // filter markers as and when the map is moved
  4533. W.map.events.register("moveend", null, uroFilterItems);
  4534. W.map.events.register("mousemove", null, uroGetAMs);
  4535. W.map.events.register("mousemove", null, uroNewLookHighlightedItemsCheck);
  4536. W.map.events.registerPriority("mousedown", null, uroMouseDown);
  4537.  
  4538. // trap mousedown on Streetview marker drag
  4539. document.getElementsByClassName('street-view-control')[0].onmousedown = uroMouseDown;
  4540. W.map.events.register("mouseup", null, uroMouseUp);
  4541. uroSetStyles(uroCtrlURs);
  4542. uroSetStyles(uroCtrlMPs);
  4543. uroSetStyles(uroCtrlPlaces);
  4544. uroSetStyles(uroCtrlCameras);
  4545. uroSetStyles(uroCtrlMisc);
  4546. uroSetStyles(uroOWL);
  4547.  
  4548. uroShowURTab();
  4549. uroRestyleWMETabs();
  4550. uroUserID = loginManager.getLoggedInUser().id;
  4551. uroFilterItems();
  4552. //uroAreaNameTest();
  4553. }
  4554. }
  4555. else
  4556. {
  4557. var mousePos;
  4558. if(uroBetaEditor)
  4559. {
  4560. mousePos = document.getElementsByClassName('mouse-position')[0].innerHTML;
  4561. }
  4562. else
  4563. {
  4564. mousePos = document.getElementsByClassName('olControlMousePosition')[0].innerHTML;
  4565. }
  4566. if((mousePos == '00.00000, 00.00000') && (uroMouseInPopup == false) && (uroPopupShown == true))
  4567. {
  4568. uroHidePopup();
  4569. }
  4570.  
  4571. //uroReplaceAreaNames();
  4572. // test for the opening or closing of the UR editing dialog
  4573. var URDialogIsOpen = (document.getElementsByClassName('new-comment-form').length == 1);
  4574. if(URDialogIsOpen)
  4575. {
  4576. var thisSelectedURID = W.map.panelRegion.currentView.conversationView.conversation.getID();
  4577. if(thisSelectedURID != uroSelectedURID)
  4578. {
  4579. // if the user selects a new UR whilst the editing dialog is still open, treat it in the
  4580. // same way as if the user had selected that UR with the dialog closed
  4581. uroURDialogIsOpen = false;
  4582. }
  4583. if(uroURDialogIsOpen == false)
  4584. {
  4585. // user is editing a new UR
  4586. uroSelectedURID = thisSelectedURID;
  4587. document.getElementsByClassName('new-comment-form')[0].getElementsByClassName('btn')[0].addEventListener("click", uroAddedComment, false);
  4588. uroAddLog('user is editing UR '+uroSelectedURID);
  4589. uroExpectedCommentCount = W.model.updateRequestSessions.objects[uroSelectedURID].comments.length;
  4590. }
  4591. }
  4592. else if(uroURDialogIsOpen == true)
  4593. {
  4594. // dialog was open and has now been closed
  4595. uroSelectedURID = null;
  4596. }
  4597. uroURDialogIsOpen = URDialogIsOpen;
  4598.  
  4599. if(((uroPendingCommentDataRefresh == true) || (uroWaitingCommentDataRefresh == true)) && (uroSelectedURID != null))
  4600. {
  4601. uroAddLog('check completion of comment data refresh for UR '+uroSelectedURID+' ('+uroPendingCommentDataRefresh+','+uroWaitingCommentDataRefresh+')');
  4602. uroGetSelectedURCommentCount();
  4603. }
  4604. var selectedTotal = W.selectionManager.selectedItems.length;
  4605. if((selectedTotal > 0) && (document.getElementById('_uroDivOWLBtns') == null))
  4606. {
  4607. var selectedClass = W.selectionManager.selectedItems[0].model.CLASS_NAME;
  4608. var displayAddToOWLBtn = false;
  4609. var displayUpdateOWLBtn = false;
  4610. var displayRemoveFromOWLBtn = false;
  4611. var selectedSegments = false;
  4612. var selectedLandmarks = false;
  4613. // WME only seems to allow multi-object selections for segments, so testing the class of the first object in the
  4614. // selection list tells us the class of any other objects in the list too...
  4615. if(selectedClass == "Waze.Feature.Vector.Segment")
  4616. {
  4617. selectedSegments = true;
  4618. for(var loop=0; loop<selectedTotal; loop++)
  4619. {
  4620. var fid = W.selectionManager.selectedItems[loop].model.attributes.id;
  4621. var idx = uroIsSegOnWatchList(fid);
  4622. if(idx == -1)
  4623. {
  4624. displayAddToOWLBtn = true;
  4625. }
  4626. else
  4627. {
  4628. if(uroSegDataChanged(idx))
  4629. {
  4630. displayUpdateOWLBtn = true;
  4631. }
  4632. displayRemoveFromOWLBtn = true;
  4633. }
  4634. }
  4635. }
  4636. else if(selectedClass == "Waze.Feature.Vector.Landmark")
  4637. {
  4638. selectedLandmarks = true;
  4639. for(var loop=0; loop<selectedTotal; loop++)
  4640. {
  4641. var fid = W.selectionManager.selectedItems[loop].model.attributes.id;
  4642. var idx = uroIsPlaceOnWatchList(fid);
  4643. if(idx == -1)
  4644. {
  4645. displayAddToOWLBtn = true;
  4646. }
  4647. else
  4648. {
  4649. if(uroPlaceDataChanged(idx))
  4650. {
  4651. displayUpdateOWLBtn = true;
  4652. }
  4653. displayRemoveFromOWLBtn = true;
  4654. }
  4655. }
  4656. }
  4657. var btnHTML = '<div id="_uroDivOWLBtns">';
  4658. if((displayAddToOWLBtn == true) && (displayUpdateOWLBtn == false))
  4659. {
  4660. btnHTML += '<button class="btn btn-default" id="_btnAddUpdateOWL">Add to OWL</button>';
  4661. }
  4662. else if((displayUpdateOWLBtn == true) && (displayAddToOWLBtn == false))
  4663. {
  4664. btnHTML += '<button class="btn btn-default" id="_btnAddUpdateOWL">Update OWL</button>';
  4665. }
  4666. else if((displayAddToOWLBtn == true) && (displayUpdateOWLBtn == true))
  4667. {
  4668. btnHTML += '<button class="btn btn-default" id="_btnAddUpdateOWL">Add to & Update OWL</button>';
  4669. }
  4670. if(displayRemoveFromOWLBtn == true)
  4671. {
  4672. btnHTML += '<button class="btn btn-default" id="_btnRemoveOWL">Remove from OWL</button>';
  4673. }
  4674. btnHTML += '</div>';
  4675. /*
  4676. // once we get around to enabling these again, remember that altering the inner HTML of the
  4677. // segment-edit-general panel when the selected segment is part of a roundabout then disables
  4678. // the onclick handler for the select roundabout button...
  4679. //
  4680. // also remember that the current WME beta has yet another different side panel arrangement
  4681. if(selectedSegments == true)
  4682. {
  4683. document.getElementById("segment-edit-general").innerHTML += btnHTML;
  4684. }
  4685. else if(selectedLandmarks == true)
  4686. {
  4687. document.getElementById("landmark-edit-general").innerHTML += btnHTML;
  4688. }
  4689. if((displayAddToOWLBtn == true)||(displayUpdateOWLBtn == true))
  4690. {
  4691. if(selectedSegments == true)
  4692. {
  4693. uroAddEventListener('_btnAddUpdateOWL','click', uroAddUpdateSegWatchList, true);
  4694. }
  4695. else
  4696. {
  4697. uroAddEventListener('_btnAddUpdateOWL','click', uroAddUpdatePlaceWatchList, true);
  4698. }
  4699. }
  4700. if(displayRemoveFromOWLBtn == true)
  4701. {
  4702. if(selectedSegments == true)
  4703. {
  4704. uroAddEventListener('_btnRemoveOWL','click', uroRemoveSegFromWatchList, true);
  4705. }
  4706. else
  4707. {
  4708. uroAddEventListener('_btnRemoveOWL','click', uroRemovePlaceFromWatchList, true);
  4709. }
  4710. }
  4711. */
  4712. }
  4713. }
  4714. }
  4715.  
  4716. function uroToggleURCtrls()
  4717. {
  4718. uroCtrlsHidden = !uroCtrlsHidden;
  4719. if (!uroCtrlsHidden)
  4720. {
  4721. document.getElementById('_hideUCCtrl').innerHTML = "hide";
  4722. if(uroCurrentTab == 1) uroShowURTab();
  4723. else if(uroCurrentTab == 2) uroShowMPTab();
  4724. else if(uroCurrentTab == 3) uroShowPlacesTab();
  4725. else if(uroCurrentTab == 4) uroShowCameraTab();
  4726. else if(uroCurrentTab == 5) uroShowOWLTab();
  4727. else if(uroCurrentTab == 6) uroShowMiscTab();
  4728. }
  4729. else
  4730. {
  4731. document.getElementById('_hideUCCtrl').innerHTML = "show";
  4732. uroSetStyleDisplay('uroCtrlURs','none');
  4733. uroSetStyleDisplay('uroCtrlMPs','none');
  4734. uroSetStyleDisplay('uroCtrlCameras','none');
  4735. uroSetStyleDisplay('uroCtrlMisc','none');
  4736. uroSetStyleDisplay('uroOWL','none');
  4737. }
  4738.  
  4739. return false;
  4740. }
  4741.  
  4742. function uroActiveTab(_id)
  4743. {
  4744. var e = document.getElementById(_id);
  4745. e.style.backgroundColor = "aliceblue";
  4746. e.style.borderTop = "1px solid";
  4747. e.style.borderLeft = "1px solid";
  4748. e.style.borderRight = "1px solid";
  4749. e.style.borderBottom = "0px solid";
  4750. }
  4751.  
  4752. function uroInactiveTab(_id)
  4753. {
  4754. var e = document.getElementById(_id);
  4755. e.style.backgroundColor = "white";
  4756. e.style.borderTop = "0px solid";
  4757. e.style.borderLeft = "0px solid";
  4758. e.style.borderRight = "0px solid";
  4759. e.style.borderBottom = "1px solid";
  4760. }
  4761.  
  4762.  
  4763. function uroInactiveAllTabs()
  4764. {
  4765. uroInactiveTab("_tabSelectCameras");
  4766. uroInactiveTab("_tabSelectMapProblems");
  4767. uroInactiveTab("_tabSelectMisc");
  4768. uroInactiveTab("_tabSelectUserRequests");
  4769. uroInactiveTab("_tabSelectCWL");
  4770. uroInactiveTab("_tabSelectPlaces");
  4771. if(!uroCtrlsHidden)
  4772. {
  4773. uroSetStyleDisplay('uroCtrlURs','none');
  4774. uroSetStyleDisplay('uroCtrlMPs','none');
  4775. uroSetStyleDisplay('uroCtrlCameras','none');
  4776. uroSetStyleDisplay('uroCtrlMisc','none');
  4777. uroSetStyleDisplay('uroOWL','none');
  4778. uroSetStyleDisplay('uroCtrlPlaces','none');
  4779. }
  4780. }
  4781.  
  4782. function uroShowURTab()
  4783. {
  4784. uroInactiveAllTabs();
  4785. uroActiveTab("_tabSelectUserRequests");
  4786. uroCurrentTab = 1;
  4787. if(!uroCtrlsHidden) uroSetStyleDisplay('uroCtrlURs','block');
  4788. return false;
  4789. }
  4790.  
  4791.  
  4792. function uroShowMPTab()
  4793. {
  4794. uroInactiveAllTabs();
  4795. uroActiveTab("_tabSelectMapProblems");
  4796. uroCurrentTab = 2;
  4797. if(!uroCtrlsHidden) uroSetStyleDisplay('uroCtrlMPs','block');
  4798. return false;
  4799. }
  4800.  
  4801. function uroShowPlacesTab()
  4802. {
  4803. uroInactiveAllTabs();
  4804. uroActiveTab("_tabSelectPlaces");
  4805. uroCurrentTab = 3;
  4806. if(!uroCtrlsHidden) uroSetStyleDisplay('uroCtrlPlaces','block');
  4807. return false;
  4808. }
  4809.  
  4810. function uroShowCameraTab()
  4811. {
  4812. uroInactiveAllTabs();
  4813. uroActiveTab("_tabSelectCameras");
  4814. uroCurrentTab = 4;
  4815. if(!uroCtrlsHidden) uroSetStyleDisplay('uroCtrlCameras','block');
  4816. return false;
  4817. }
  4818.  
  4819. function uroShowOWLTab()
  4820. {
  4821. uroInactiveAllTabs();
  4822. uroActiveTab("_tabSelectCWL");
  4823. uroCurrentTab = 5;
  4824. if(!uroCtrlsHidden) uroSetStyleDisplay('uroOWL','block');
  4825. uroOWLUpdateHTML();
  4826. return false;
  4827. }
  4828. function uroShowMiscTab()
  4829. {
  4830. uroInactiveAllTabs();
  4831. uroActiveTab("_tabSelectMisc");
  4832. uroCurrentTab = 6;
  4833. if(!uroCtrlsHidden) uroSetStyleDisplay('uroCtrlMisc','block');
  4834. return false;
  4835. }
  4836.  
  4837.  
  4838.  
  4839. function uroTimbonesGetElementsByClassName(classname, node) {
  4840. if(!node) node = document.getElementsByTagName("body")[0];
  4841. var a = [];
  4842. var re = new RegExp('\\b' + classname + '\\b');
  4843. var els = node.getElementsByTagName("*");
  4844. for (var i=0,j=els.length; i<j; i++)
  4845. if (re.test(els[i].className)) a.push(els[i]);
  4846. return a;
  4847. }
  4848.  
  4849. function uroNewLookCheckDetailsRequest()
  4850. {
  4851. var thisurl = document.location.href;
  4852. var doRetry = true;
  4853. endmarkerpos = thisurl.indexOf('&endshow');
  4854.  
  4855. showmarkerpos = thisurl.indexOf('&showturn=');
  4856. if((endmarkerpos != -1) && (showmarkerpos != -1))
  4857. {
  4858. showmarkerpos += 10;
  4859. uroAddLog('showturn tab opened');
  4860. var urID = thisurl.substr(showmarkerpos,endmarkerpos-showmarkerpos);
  4861. uroAddLog(' turn problem ID = '+urID);
  4862.  
  4863. try
  4864. {
  4865. W.map.problemLayer.markers[urID].icon.imageDiv.click();
  4866. doRetry = false;
  4867. }
  4868. catch(err)
  4869. {
  4870. uroAddLog('problems not fully loaded, retrying...');
  4871. }
  4872.  
  4873. if(doRetry) setTimeout(uroNewLookCheckDetailsRequest,500);
  4874. }
  4875. else
  4876. {
  4877. showmarkerpos = thisurl.indexOf('&showpur=');
  4878. if((endmarkerpos != -1) && (showmarkerpos != -1))
  4879. {
  4880. showmarkerpos += 9;
  4881. uroAddLog('showPUR tab opened');
  4882. var urID = thisurl.substr(showmarkerpos,endmarkerpos-showmarkerpos);
  4883. uroAddLog(' PUR ID = '+urID);
  4884.  
  4885. try
  4886. {
  4887. W.map.placeUpdatesLayer.markers[urID].icon.imageDiv.click();
  4888. doRetry = false;
  4889. }
  4890. catch(err)
  4891. {
  4892. uroAddLog('PURs not fully loaded, retrying...');
  4893. }
  4894.  
  4895. if(doRetry) setTimeout(uroNewLookCheckDetailsRequest,500);
  4896. }
  4897. }
  4898. }
  4899.  
  4900.  
  4901. function uroUpdateMPSolverList()
  4902. {
  4903. if(Object.keys(W.model.problems.objects).length == 0)
  4904. {
  4905. return;
  4906. }
  4907.  
  4908. var resolverList = [];
  4909. var selector = document.getElementById('_selectMPUserID');
  4910. var selectedUser = null;
  4911. if(selector.selectedOptions[0] != undefined)
  4912. {
  4913. selectedUser = parseInt(selector.selectedOptions[0].value);
  4914. }
  4915. while(selector.options.length > 0)
  4916. {
  4917. selector.options.remove(0);
  4918. }
  4919. var selectedIdx = 0;
  4920. var idx = 0;
  4921. for (var mpobj in W.model.problems.objects)
  4922. {
  4923. var prob = W.model.problems.objects[mpobj];
  4924. if(prob.attributes.resolvedBy != null)
  4925. {
  4926. var userID = prob.attributes.resolvedBy;
  4927. var userName = W.model.users.objects[userID].userName;
  4928. if(resolverList.indexOf(userName) == -1)
  4929. {
  4930. resolverList.push(userName);
  4931. selector.options.add(new Option(userName, userID));
  4932. if(userID == selectedUser)
  4933. {
  4934. selectedIdx = idx;
  4935. }
  4936. idx++;
  4937. }
  4938. }
  4939. }
  4940. if(selectedIdx != null)
  4941. {
  4942. selector.selectedIndex = selectedIdx;
  4943. }
  4944. }
  4945.  
  4946.  
  4947. function uroUpdateResolverList()
  4948. {
  4949. if(Object.keys(W.model.mapUpdateRequests.objects).length == 0)
  4950. {
  4951. return;
  4952. }
  4953.  
  4954. var resolverList = [];
  4955. var selector = document.getElementById('_selectURResolverID');
  4956. var selectedUser = null;
  4957. if(selector.selectedOptions[0] != undefined)
  4958. {
  4959. selectedUser = parseInt(selector.selectedOptions[0].value);
  4960. }
  4961. while(selector.options.length > 0)
  4962. {
  4963. selector.options.remove(0);
  4964. }
  4965. var selectedIdx = 0;
  4966. var idx = 0;
  4967. for (var urobj in W.model.mapUpdateRequests.objects)
  4968. {
  4969. var ureq = W.model.mapUpdateRequests.objects[urobj];
  4970. if(ureq.attributes.resolvedBy != null)
  4971. {
  4972. var userID = ureq.attributes.resolvedBy;
  4973. var userName = W.model.users.objects[userID].userName;
  4974. if(resolverList.indexOf(userName) == -1)
  4975. {
  4976. resolverList.push(userName);
  4977. selector.options.add(new Option(userName, userID));
  4978. if(userID == selectedUser)
  4979. {
  4980. selectedIdx = idx;
  4981. }
  4982. idx++;
  4983. }
  4984. }
  4985. }
  4986. if(selectedIdx != null)
  4987. {
  4988. selector.selectedIndex = selectedIdx;
  4989. }
  4990. }
  4991.  
  4992. function uroUpdateUserList()
  4993. {
  4994. if(Object.keys(W.model.updateRequestSessions.objects).length == 0) return;
  4995. var selector = document.getElementById('_selectURUserID');
  4996.  
  4997. var selectedUser = null;
  4998. if(selector.selectedOptions[0] != undefined)
  4999. {
  5000. selectedUser = parseInt(selector.selectedOptions[0].value);
  5001. }
  5002. while(selector.options.length > 0)
  5003. {
  5004. selector.options.remove(0);
  5005. }
  5006. var selectedIdx = null;
  5007.  
  5008. var listedIDs = [];
  5009. for(var ursIdx in W.model.updateRequestSessions.objects)
  5010. {
  5011. var ursObj = W.model.updateRequestSessions.objects[ursIdx];
  5012. if(ursObj.comments.length > 0)
  5013. {
  5014. for(var cidx=0; cidx < ursObj.comments.length; cidx++)
  5015. {
  5016. var userID = ursObj.comments[cidx].userID;
  5017. if((listedIDs.indexOf(userID) == -1) && (userID != -1))
  5018. {
  5019. listedIDs.push(userID);
  5020. }
  5021. }
  5022. }
  5023. }
  5024.  
  5025. if(listedIDs.length > 0)
  5026. {
  5027. var users = W.model.users.getByIds(listedIDs);
  5028. for(var idx=0; idx<listedIDs.length; idx++)
  5029. {
  5030. selector.options.add(new Option(users[idx].userName, listedIDs[idx]));
  5031. if(listedIDs[idx] == selectedUser)
  5032. {
  5033. selectedIdx = idx;
  5034. }
  5035. }
  5036. }
  5037. if(selectedIdx != null)
  5038. {
  5039. selector.selectedIndex = selectedIdx;
  5040. }
  5041. }
  5042.  
  5043.  
  5044. function uroSetStyles(obj)
  5045. {
  5046. obj.style.fontSize = '12px';
  5047. obj.style.lineHeight = '100%';
  5048. obj.style.overflow = 'auto';
  5049. obj.style.height = (window.innerHeight * 0.55) + 'px';
  5050. }
  5051.  
  5052. function uroPopulatePlacesTab()
  5053. {
  5054. var tHTML = '';
  5055. tHTML += '<b>Filter PURs by category/status:</b><br>';
  5056. tHTML += '<input type="checkbox" id="_cbFilterUneditablePlaceUpdates">Ones I can\'t edit</input><br>';
  5057. tHTML += '<input type="checkbox" id="_cbFilterLockRankedPlaceUpdates">Ones with non-zero lockRanks</input><br>';
  5058. tHTML += '<input type="checkbox" id="_cbFilterNewPlacePUR">Ones for new places</input><br>';
  5059. tHTML += '<input type="checkbox" id="_cbFilterUpdatedDetailsPUR">Ones for updated place details</input><br>';
  5060. tHTML += '<input type="checkbox" id="_cbFilterNewPhotoPUR">Ones for new photos</input><br>';
  5061. tHTML += '<input type="checkbox" id="_cbFilterFlaggedPUR">Ones flagged for attention</input><br>';
  5062. tHTML += '<br><input type="checkbox" id="_cbLeavePURGeos">Don\'t hide place polygons/points</input><br>';
  5063. tHTML += '<br><input type="checkbox" id="_cbInvertPURFilters">Invert PUR filters</input><br>';
  5064.  
  5065. tHTML += '<br><b>Filter PURs by severity:</b><br>';
  5066. tHTML += '<input type="checkbox" id="_cbPURFilterLowSeverity">Low</input>&nbsp;&nbsp;';
  5067. tHTML += '<input type="checkbox" id="_cbPURFilterMediumSeverity">Medium</input>&nbsp;&nbsp;';
  5068. tHTML += '<input type="checkbox" id="_cbPURFilterHighSeverity">High</input>';
  5069. tHTML += '<br><b>Filter PURs by age of submission:</b><br>';
  5070. tHTML += '<input type="checkbox" id="_cbEnablePURMinAgeFilter">Hide PURs less than </input>';
  5071. tHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputPURFilterMinDays"> days old<br>';
  5072. tHTML += '<input type="checkbox" id="_cbEnablePURMaxAgeFilter">Hide PURs more than </input>';
  5073. tHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputPURFilterMaxDays"> days old<br>';
  5074. tHTML += '<hr>';
  5075. tHTML += '<br><b>Filter Places by state:</b><br>';
  5076. tHTML += 'Hide if last edited<br>';
  5077. tHTML += '<input type="checkbox" id="_cbPlaceFilterEditedLessThan"> less than </input>';
  5078. tHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterPlaceEditMinDays"> days ago<br>';
  5079. tHTML += '<input type="checkbox" id="_cbPlaceFilterEditedMoreThan"> more than </input>';
  5080. tHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterPlaceEditMaxDays"> days ago<br>';
  5081. tHTML += '<br>Hide if locked at level:<br>';
  5082. tHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHidePlacesL0">1</input>';
  5083. tHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHidePlacesL1">2</input>';
  5084. tHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHidePlacesL2">3</input>';
  5085. tHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHidePlacesL3">4</input>';
  5086. tHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHidePlacesL4">5</input>';
  5087. tHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHidePlacesL5">6</input>';
  5088. tHTML += '<br><br><input type="checkbox" id="_cbHidePhotoPlaces">Hide or </input>';
  5089. tHTML += '<input type="checkbox" id="_cbHideNoPhotoPlaces">show ones with photos</input><br>';
  5090. tHTML += '<br><br><b>Filter Places by category:</b><br>';
  5091. for(var i=0; i<W.Config.venues.categories.length; i++)
  5092. {
  5093. parentCategory = W.Config.venues.categories[i];
  5094. localisedName = I18n.translations[I18n.locale].venues.categories[parentCategory];
  5095. tHTML += '<input type="checkbox" id="_cbPlacesFilter-'+parentCategory+'"><b>'+localisedName+'</b></input><br>';
  5096. for(var ii=0; ii<W.Config.venues.subcategories[parentCategory].length; ii++)
  5097. {
  5098. subCategory = W.Config.venues.subcategories[parentCategory][ii];
  5099. localisedName = I18n.translations[I18n.locale].venues.categories[subCategory];
  5100. tHTML += '&nbsp;&nbsp;<input type="checkbox" id="_cbPlacesFilter-'+subCategory+'">'+localisedName+'</input><br>';
  5101. }
  5102. }
  5103. tHTML += '<input type="checkbox" id="_cbFilterPrivatePlaces"><b>Private Places</b></input><br>';
  5104. tHTML += '<br><input type="checkbox" id="_cbInvertPlacesFilter">Invert Place filters?</input>';
  5105. uroCtrlPlaces.innerHTML = tHTML;
  5106. }
  5107.  
  5108. function uroWazeBits()
  5109. {
  5110. // "fake" uroWazeBits() function which only performs layer scan, to stop the uroWazeBits() call in WMETB from
  5111. // messing around with other stuff in the actual uroWazeBits() function (now renamed uroRealWazeBits...) that
  5112. // really only ought to be called once.
  5113. for(i=0;i<W.map.layers.length;i++)
  5114. {
  5115. if(W.map.layers[i].name == 'Spotlight') uroMaskLayer = i;
  5116. if(W.map.layers[i].name.indexOf('Waze.Control.SelectHighlightFeature') != -1) uroRootContainer = W.map.layers[i].div.id;
  5117. if(W.map.layers[i].name == 'Node Connections') uroTurnsLayerIdx = i;
  5118. }
  5119. uroPlacesRoot = W.map.landmarkLayer.id + '_vroot';
  5120.  
  5121. for(i=0;i<W.map.controls.length;i++)
  5122. {
  5123. if(W.map.controls[i].CLASS_NAME == 'Waze.View.ArchivePanel') dteControlsIdx = i;
  5124. else if(W.map.controls[i].CLASS_NAME == 'Waze.Control.Archive') dteControlsIdx = i;
  5125.  
  5126. if(W.map.controls[i].id != null)
  5127. {
  5128. if(W.map.controls[i].id.indexOf('UpdateRequests') != -1) uroURControlsIdx = i;
  5129. if(W.map.controls[i].id.indexOf('MapProblems') != -1) uroProblemControlsIdx = i;
  5130. }
  5131. }
  5132. uroAddLog('uroMaskLayer at idx '+uroMaskLayer);
  5133. uroAddLog('Turns layer at idx '+uroTurnsLayerIdx);
  5134. uroAddLog('uroRootContainer = '+uroRootContainer);
  5135. uroAddLog('Places root layer = '+uroPlacesRoot);
  5136. }
  5137.  
  5138.  
  5139. function uroRealWazeBits()
  5140. {
  5141. if(document.getElementsByClassName("sandbox").length > 0)
  5142. {
  5143. uroPracticeMode = true;
  5144. }
  5145. else
  5146. {
  5147. uroPracticeMode = false;
  5148. }
  5149. uroAddLog('adding WazeBits...'+uroToHex(uroWazeBitsPresent,4));
  5150. if((uroWazeBitsPresent & 0x0001) == 0)
  5151. {
  5152. if(typeof unsafeWindow.W != "undefined")
  5153. {
  5154. if(typeof unsafeWindow.W.controller != "undefined")
  5155. {
  5156. if(typeof unsafeWindow.W.controller.map != "undefined")
  5157. {
  5158. uroAddLog(' W.map OK');
  5159. W.map = unsafeWindow.W.controller.map;
  5160. uroWazeBitsPresent |= 0x0001;
  5161. }
  5162. }
  5163. }
  5164. }
  5165. if((uroWazeBitsPresent & 0x0002) == 0)
  5166. {
  5167. if(typeof unsafeWindow.W != "undefined")
  5168. {
  5169. if(typeof unsafeWindow.W.controller != "undefined")
  5170. {
  5171. if(typeof unsafeWindow.W.controller.model != "undefined")
  5172. {
  5173. uroAddLog(' W.model OK');
  5174. W.model = unsafeWindow.W.controller.model;
  5175. uroWazeBitsPresent |= 0x0002;
  5176. }
  5177. }
  5178. }
  5179. }
  5180. if((uroWazeBitsPresent & 0x0004) == 0)
  5181. {
  5182. if(typeof unsafeWindow.W != "undefined")
  5183. {
  5184. if(typeof unsafeWindow.W.app != "undefined")
  5185. {
  5186. if(typeof unsafeWindow.W.app.loginManager != "undefined")
  5187. {
  5188. uroAddLog(' loginManager OK');
  5189. loginManager = unsafeWindow.W.app.loginManager;
  5190. uroWazeBitsPresent |= 0x0004;
  5191. }
  5192. }
  5193. }
  5194. }
  5195. if((uroWazeBitsPresent & 0x0008) == 0)
  5196. {
  5197. if(typeof unsafeWindow.W != "undefined")
  5198. {
  5199. if(typeof unsafeWindow.W.geometryEditing != "undefined")
  5200. {
  5201. if(typeof unsafeWindow.W.geometryEditing.selectionManager != "undefined")
  5202. {
  5203. uroAddLog(' selectionManager OK');
  5204. selectionManager = unsafeWindow.W.geometryEditing.selectionManager;
  5205. uroWazeBitsPresent |= 0x0008;
  5206. }
  5207. }
  5208. }
  5209. }
  5210. if((uroWazeBitsPresent & 0x0010) == 0)
  5211. {
  5212. if(typeof unsafeWindow.OpenLayers != "undefined")
  5213. {
  5214. uroAddLog(' OpenLayers OK');
  5215. OpenLayers = unsafeWindow.OpenLayers;
  5216. uroWazeBitsPresent |= 0x0010;
  5217. }
  5218. }
  5219. if((uroWazeBitsPresent & 0x0020) == 0)
  5220. {
  5221. if(typeof unsafeWindow.Waze != "undefined")
  5222. {
  5223. uroAddLog(' Waze OK');
  5224. Waze = unsafeWindow.Waze;
  5225. uroWazeBitsPresent |= 0x0020;
  5226. }
  5227. }
  5228. if((uroWazeBitsPresent & 0x0040) == 0)
  5229. {
  5230. if(document.getElementById('user-tabs') != null)
  5231. {
  5232. uroUserTabId = 'user-tabs';
  5233. uroAddLog(' user-tabs OK');
  5234. uroWazeBitsPresent |= 0x0040;
  5235. }
  5236. else if(document.getElementById('user-info') != null)
  5237. {
  5238. uroUserTabId = 'user-info';
  5239. uroAddLog(' user-info OK');
  5240. uroWazeBitsPresent |= 0x0040;
  5241. }
  5242. }
  5243. if((uroWazeBitsPresent & 0x0080) == 0)
  5244. {
  5245. if(uroPracticeMode == true)
  5246. {
  5247. uroAddLog(' sidepanel-drives ignored in practice mode');
  5248. uroWazeBitsPresent |= 0x0080;
  5249. }
  5250. else
  5251. {
  5252. if(document.getElementById('sidepanel-drives') != null)
  5253. {
  5254. uroAddLog(' sidepanel-drives OK');
  5255. uroWazeBitsPresent |= 0x0080;
  5256. }
  5257. }
  5258. }
  5259. if((uroWazeBitsPresent & 0x0100) == 0)
  5260. {
  5261. if(typeof unsafeWindow.I18n != "undefined")
  5262. {
  5263. uroAddLog(' I18n OK');
  5264. uroWazeBitsPresent |= 0x0100;
  5265. }
  5266. }
  5267.  
  5268. if(uroWazeBitsPresent != 0x01FF) setTimeout(uroRealWazeBits,250);
  5269. else if((loginManager.isLoggedIn() == false) && (uroPracticeMode == false))
  5270. {
  5271. uroAddLog('Waiting for user log-in...');
  5272. setTimeout(uroRealWazeBits,1000);
  5273. }
  5274. else
  5275. {
  5276. uroAddLog('All WazeBits present and correct...');
  5277. uroDOMHasTurnProblems = (W.model.turnProblems != undefined);
  5278. uroPopulatePlacesTab();
  5279. uroControls.appendChild(uroCtrlURs);
  5280. uroControls.appendChild(uroCtrlMPs);
  5281. uroControls.appendChild(uroCtrlPlaces);
  5282. uroControls.appendChild(uroCtrlCameras);
  5283. uroControls.appendChild(uroOWL);
  5284. uroControls.appendChild(uroCtrlMisc);
  5285. uroControls.appendChild(uroCtrlHides);
  5286. uroControls.appendChild(uroAMList);
  5287.  
  5288. uroCtrlURs.onclick = uroFilterItems_URTabClick;
  5289. uroCtrlMPs.onclick = uroFilterItems_MPTabClick;
  5290. uroCtrlPlaces.onclick = uroFilterItems_PlacesTabClick;
  5291. uroCtrlCameras.onclick = uroFilterItems_CamerasTabClick;
  5292. uroCtrlMisc.onclick = uroFilterItems_MiscTabClick;
  5293.  
  5294. uroWazeBits();
  5295.  
  5296. uroDiv.addEventListener("mouseover", uroEnterPopup, false);
  5297. uroDiv.addEventListener("mouseout", uroExitPopup, false);
  5298.  
  5299. if(sessionStorage.UROverview_FID_IgnoreList == null) sessionStorage.UROverview_FID_IgnoreList = '';
  5300. if(sessionStorage.UROverview_FID_WatchList == null) sessionStorage.UROverview_FID_WatchList = '';
  5301. if(uroConfirmIntercepted == false) uroAddInterceptor();
  5302.  
  5303. setInterval(uroTenthSecondTick,100);
  5304. }
  5305. }
  5306.  
  5307.  
  5308. function uroAddInterceptor()
  5309. {
  5310. uroAddLog('Adding interceptor function...');
  5311. // add interceptor function for confirm(), so that we can auto-select the "OK" option when solving URs
  5312. // which have pending question...
  5313. _confirm = unsafeWindow.confirm;
  5314. unsafeWindow.confirm = function(msg)
  5315. {
  5316. if((I18n.translations[I18n.locale].update_requests.panel.confirm == msg) && (uroGetCBChecked('_cbDisablePendingQuestions') == true))
  5317. {
  5318. uroAddLog('Intercepted pending comments confirmation...');
  5319. return true;
  5320. }
  5321. else if(typeof(msg) == 'undefined')
  5322. {
  5323. uroAddLog('Intercepted blank confirmation...');
  5324. return true;
  5325. }
  5326. else
  5327. {
  5328. return _confirm(msg);
  5329. }
  5330. };
  5331. uroConfirmIntercepted = true;
  5332. }
  5333.  
  5334.  
  5335. function uroEnterPopup()
  5336. {
  5337. uroMouseInPopup = true;
  5338. }
  5339.  
  5340. function uroExitPopup()
  5341. {
  5342. uroMouseInPopup = false;
  5343. }
  5344.  
  5345. function uroToggleDebug()
  5346. {
  5347. uroShowDebugOutput = !uroShowDebugOutput;
  5348. var dbgMode = "none";
  5349. if(uroShowDebugOutput)
  5350. {
  5351. dbgMode = "inline";
  5352. }
  5353. document.getElementById('_uroDebugMode').style.display = dbgMode;
  5354. }
  5355.  
  5356. function uroInitialise()
  5357. {
  5358. uroGlobals();
  5359. if(document.URL.indexOf('editor-beta') != -1) uroBetaEditor = true;
  5360.  
  5361. // create a new div to display the UR details floaty-box
  5362. uroDiv = document.createElement('div');
  5363. uroDiv.id = "uroDiv";
  5364. uroDiv.style.position = 'absolute';
  5365. uroDiv.style.visibility = 'hidden';
  5366. uroDiv.style.top = '0';
  5367. uroDiv.style.left = '0';
  5368. uroDiv.style.zIndex = 100;
  5369. uroDiv.style.backgroundColor = 'aliceblue';
  5370. uroDiv.style.borderWidth = '3px';
  5371. uroDiv.style.borderStyle = 'ridge';
  5372. uroDiv.style.borderRadius = '10px';
  5373. uroDiv.style.boxShadow = '5px 5px 10px Silver';
  5374. uroDiv.style.padding = '4px';
  5375. document.body.appendChild(uroDiv);
  5376.  
  5377.  
  5378. uroControls = document.createElement('section');
  5379. uroControls.style.fontSize = '12px';
  5380. uroControls.id = 'uroControls';
  5381. if(navigator.userAgent.indexOf('Chrome') == -1)
  5382. {
  5383. var updateURL = 'https://greasyfork.org/scripts/1952-uroverview-plus-uro';
  5384. }
  5385. else
  5386. {
  5387. var updateURL = 'https://chrome.google.com/webstore/detail/uroverview/amdamgkgchnbaopmphhjapmjcdghdphi';
  5388. }
  5389. //tabbyHTML = '<input type="checkbox" id="_cbUROMasterEnable" /> ';
  5390. tabbyHTML = '<b><a href="'+updateURL+'" target="_blank">UROverview Plus</a></b> <label id="_uroVersion">'+uroVersion+'</label>';
  5391. tabbyHTML += '<label id="_uroDebugMode">(dbg)</label>';
  5392. tabbyHTML += '<p><table border=0 width="100%"><tr>';
  5393. tabbyHTML += '<td valign="center" align="center" id="_tabSelectUserRequests"><a href="#" id="_linkSelectUserRequests" style="text-decoration:none;font-size:12px">URs</a></td>';
  5394. tabbyHTML += '<td valign="center" align="center" id="_tabSelectMapProblems"><a href="#" id="_linkSelectMapProblems" style="text-decoration:none;font-size:12px">MPs</a></td>';
  5395. tabbyHTML += '<td valign="center" align="center" id="_tabSelectPlaces"><a href="#" id="_linkSelectPlaces" style="text-decoration:none;font-size:12px">Places</a></td>';
  5396. tabbyHTML += '<td valign="center" align="center" id="_tabSelectCameras"><a href="#" id="_linkSelectCameras" style="text-decoration:none;font-size:12px">Cams</a></td>';
  5397. tabbyHTML += '<td valign="center" align="center" id="_tabSelectCWL"><a href="#" id="_linkSelectOWL" style="text-decoration:none;font-size:12px">OWL</a></td>';
  5398. tabbyHTML += '<td valign="center" align="center" id="_tabSelectMisc"><a href="#" id="_linkSelectMisc" style="text-decoration:none;font-size:12px">Misc</a></td>';
  5399. tabbyHTML += '</tr></table>';
  5400. uroControls.innerHTML = tabbyHTML;
  5401.  
  5402.  
  5403. uroCtrlURs = document.createElement('p');
  5404. uroCtrlMPs = document.createElement('p');
  5405. uroCtrlCameras = document.createElement('p');
  5406. uroOWL = document.createElement('p');
  5407. uroCtrlMisc = document.createElement('p');
  5408. uroAMList = document.createElement('div');
  5409. uroCtrlHides = document.createElement('div');
  5410. uroCtrlPlaces = document.createElement('p');
  5411.  
  5412. // UR controls tab
  5413. uroCtrlURs.id = "uroCtrlURs";
  5414. uroCtrlURs.innerHTML = '<br>';
  5415.  
  5416. uroCtrlURs.innerHTML += '<b>Hide URs by type:</b><br>';
  5417. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterWazeAuto">Waze Automatic</input><br>';
  5418. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterIncorrectTurn">Incorrect turn</input><br>';
  5419. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterIncorrectAddress">Incorrect address</input><br>';
  5420. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterIncorrectRoute">Incorrect route</input><br>';
  5421. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterMissingRoundabout">Missing roundabout</input><br>';
  5422. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterGeneralError">General error</input><br>';
  5423. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterTurnNotAllowed">Turn not allowed</input><br>';
  5424. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterIncorrectJunction">Incorrect junction</input><br>';
  5425. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterMissingBridgeOverpass">Missing bridge overpass</input><br>';
  5426. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterWrongDrivingDirection">Wrong driving direction</input><br>';
  5427. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterMissingExit">Missing exit</input><br>';
  5428. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterMissingRoad">Missing road</input><br>';
  5429. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterBlockedRoad">Blocked road</input><br>';
  5430. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterMissingLandmark">Missing Landmark</input><br>';
  5431. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterUndefined">Undefined</input><br>';
  5432.  
  5433. uroCtrlURs.innerHTML += '&nbsp;&nbsp;<i>Specially tagged types</i><br>';
  5434. uroCtrlURs.innerHTML += '&nbsp;&nbsp;<input type="checkbox" id="_cbFilterRoadworks">[ROADWORKS]</input><br>';
  5435. uroCtrlURs.innerHTML += '&nbsp;&nbsp;<input type="checkbox" id="_cbFilterConstruction">[CONSTRUCTION]</input><br>';
  5436. uroCtrlURs.innerHTML += '&nbsp;&nbsp;<input type="checkbox" id="_cbFilterClosure">[CLOSURE]</input><br>';
  5437. uroCtrlURs.innerHTML += '&nbsp;&nbsp;<input type="checkbox" id="_cbFilterEvent">[EVENT]</input><br>';
  5438. uroCtrlURs.innerHTML += '&nbsp;&nbsp;<input type="checkbox" id="_cbFilterNote">[NOTE]</input><br><br>';
  5439. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbInvertURFilter">Invert operation of type filters?</input><br>';
  5440. uroCtrlURs.innerHTML += '<hr>';
  5441. uroCtrlURs.innerHTML += '<br><b>Hide by state:</b><br>';
  5442. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterOpenUR">Open</input><br>';
  5443. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterClosedUR">Closed</input><br>';
  5444. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterSolved">Solved</input><br>';
  5445. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterUnidentified">Not identified</input><br><br>';
  5446.  
  5447.  
  5448. uroCtrlURs.innerHTML += '<br><b>Filter URs by age of submission:</b><br>';
  5449. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableMinAgeFilter">Hide URs less than </input>';
  5450. 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>';
  5451. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableMaxAgeFilter">Hide URs more than </input>';
  5452. 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>';
  5453.  
  5454. uroCtrlURs.innerHTML += '<br><b>Filter URs by description text:</b><br>';
  5455. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbURDescriptionMustBePresent">Hide</input> or ';
  5456. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbURDescriptionMustBeAbsent">show</input> URs with no description<br>';
  5457. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableKeywordMustBePresent">Hide URs not including </input>';
  5458. uroCtrlURs.innerHTML += '<input type="text" style="font-size:14px; line-height:16px; height:22px; margin-bottom:4px;" id="_textKeywordPresent"><br>';
  5459. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableKeywordMustBeAbsent">Hide URs including </input>';
  5460. uroCtrlURs.innerHTML += '<input type="text" style="font-size:14px; line-height:16px; height:22px; margin-bottom:4px;" id="_textKeywordAbsent"><br>';
  5461. uroCtrlURs.innerHTML += '&nbsp;&nbsp;<input type="checkbox" id="_cbCaseInsensitive">Case-insensitive matches?</input><br>';
  5462. uroCtrlURs.innerHTML += '<br><b>Hide URs by comments/following:</b><br>';
  5463. uroCtrlURs.innerHTML += '<i>With comments from me?</i><br>';
  5464. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideMyComments">Yes </input>';
  5465. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideAnyComments">No</input><br>';
  5466. uroCtrlURs.innerHTML += '<i>If last comment made by me?</i><br>';
  5467. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideIfLastCommenter">Yes </input>';
  5468. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideIfNotLastCommenter">No </input><br>';
  5469. uroCtrlURs.innerHTML += '<i>If last comment made by UR reporter?</i><br>';
  5470. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideIfReporterLastCommenter">Yes </input>';
  5471. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideIfReporterNotLastCommenter">No</input><br>';
  5472.  
  5473. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableMinCommentsFilter">With less than </input>';
  5474. uroCtrlURs.innerHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterMinComments"> comments<br>';
  5475. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableMaxCommentsFilter">With more than </input>';
  5476. uroCtrlURs.innerHTML += '<input type="number" min="0" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterMaxComments"> comments<br>';
  5477. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideMyFollowed">Ones I am or </input>';
  5478. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideMyUnfollowed">am not following</input><br>';
  5479.  
  5480. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableCommentAgeFilter2">Last comment less than </input>';
  5481. 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>';
  5482. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableCommentAgeFilter">Last comment more than </input>';
  5483. 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>';
  5484. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbURUserIDFilter">Without comments from user</input>';
  5485. uroCtrlURs.innerHTML += '<select id="_selectURUserID" style="width:80%; height:22px;"></select><br>';
  5486. uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbURResolverIDFilter">Not resolved by user</input>';
  5487. uroCtrlURs.innerHTML += '<select id="_selectURResolverID" style="width:80%; height:22px;"></select>';
  5488. uroCtrlURs.innerHTML += '<br><br><input type="checkbox" id="_cbNoFilterForTaggedURs"><b>Don\'t apply state/age filters to tagged URs</b></input><br>';
  5489.  
  5490.  
  5491. // Map problems controls tab
  5492. uroCtrlMPs.id = "uroCtrlMPs";
  5493. uroCtrlMPs.innerHTML = '<br>';
  5494.  
  5495. uroCtrlMPs.innerHTML += '<b>Filter MPs by type:</b><br>';
  5496. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterMissingJunction">Missing junction</input><br>';
  5497. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterMissingRoad">Missing road</input><br>';
  5498. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterCrossroadsJunctionMissing">Missing crossroads</input><br>';
  5499. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterDrivingDirectionMismatch">Driving direction mismatch</input><br>';
  5500. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterRoadTypeMismatch">Road type mismatch</input><br>';
  5501. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterRestrictedTurn">Restricted turn might be allowed</input><br>';
  5502. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterUnknownProblem">Unknown problem type</input><br><br>';
  5503. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterTurnProblem">Turn Problems</input><br><br>';
  5504.  
  5505. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterReopenedProblem">Reopened Problems</input><br><br>';
  5506. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbInvertMPFilter">Invert operation of type filters?</input><br>';
  5507.  
  5508. uroCtrlMPs.innerHTML += '<br><b>Hide closed/solved/unidentified Problems:</b><br>';
  5509. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterClosed">Closed</input><br>';
  5510. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterSolved">Solved</input><br>';
  5511. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterUnidentified">Not identified</input><br><br>';
  5512. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPClosedUserIDFilter">Closed</input> or ';
  5513. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPNotClosedUserIDFilter">Not Closed</input> by user';
  5514. uroCtrlMPs.innerHTML += '<select id="_selectMPUserID" style="width:80%; height:22px;"></select><br>';
  5515.  
  5516. uroCtrlMPs.innerHTML += '<br><b>Hide problems (not turn) by severity:</b><br>';
  5517. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterLowSeverity">Low</input>&nbsp;&nbsp;';
  5518. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterMediumSeverity">Medium</input>&nbsp;&nbsp;';
  5519. uroCtrlMPs.innerHTML += '<input type="checkbox" id="_cbMPFilterHighSeverity">High</input><br>';
  5520. // Places filtering tab
  5521. uroCtrlPlaces.id = "uroCtrlPlaces";
  5522. uroCtrlPlaces.innerHTML = 'Places filter list being populated, please wait...';
  5523.  
  5524.  
  5525. // Camera controls tab
  5526. uroCtrlCameras.id = "uroCtrlCameras";
  5527. uroCtrlCameras.innerHTML = '<br><b>Show Cameras by creator:</b><br>';
  5528. uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowWorldCams" checked>world_* users</input><br>';
  5529. uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowUSACams" checked>usa_* users</input><br>';
  5530. uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowNonWorldCams" checked>other users</input><br>';
  5531. uroCtrlCameras.innerHTML += '<br><input type="checkbox" id="_cbShowOnlyMyCams">Show ONLY cameras created/edited by me</input><br>';
  5532.  
  5533.  
  5534. uroCtrlCameras.innerHTML += '<br><b>Show Cameras by approval status:</b><br>';
  5535. uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowApprovedCams" checked>approved</input><br>';
  5536. uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowNonApprovedCams" checked>non-approved</input><br>';
  5537. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbShowOlderCreatedNonApproved"> if created more than </input>';
  5538. 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>';
  5539. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbShowOlderUpdatedNonApproved"> if updated more than </input>';
  5540. 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>';
  5541.  
  5542. uroCtrlCameras.innerHTML += '<br><b>Show Cameras by type:</b><br>';
  5543. uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowSpeedCams" checked>Speed</input><br>';
  5544. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbShowIfMPHSpeedSet" checked> with MPH speeds</input><br>';
  5545. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbShowIfKPHSpeedSet" checked> with KM/H speeds</input><br>';
  5546. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbShowIfNoSpeedSet" checked> with no speed</input><br>';
  5547. uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowRedLightCams" checked>Red Light</input><br>';
  5548. uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowDummyCams" checked>Dummy</input><br>';
  5549.  
  5550. uroCtrlCameras.innerHTML += '<br><b>Hide Cameras by creator:</b><br>';
  5551. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideCreatedByMe">me</input>';
  5552. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideCreatedByRank0">L1</input>';
  5553. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideCreatedByRank1">L2</input>';
  5554. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideCreatedByRank2">L3</input>';
  5555. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideCreatedByRank3">L4</input>';
  5556. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideCreatedByRank4">L5</input>';
  5557. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideCreatedByRank5">L6</input>';
  5558.  
  5559. uroCtrlCameras.innerHTML += '<br><b>Hide Cameras by updater:</b><br>';
  5560. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideUpdatedByMe">me</input>';
  5561. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideUpdatedByRank0">L1</input>';
  5562. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideUpdatedByRank1">L2</input>';
  5563. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideUpdatedByRank2">L3</input>';
  5564. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideUpdatedByRank3">L4</input>';
  5565. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideUpdatedByRank4">L5</input>';
  5566. uroCtrlCameras.innerHTML += '&nbsp;&nbsp;&nbsp;<input type="checkbox" id="_cbHideUpdatedByRank5">L6</input>';
  5567.  
  5568. uroCtrlCameras.innerHTML += '<br><br><b><input type="checkbox" id="_cbHideCWLCams">Hide cameras on watchlist</input></b><br>';
  5569.  
  5570. // Object watchlist tab
  5571. uroOWL.id = "uroOWL";
  5572. uroOWLUpdateHTML();
  5573. // Misc controls tab
  5574. uroCtrlMisc.id = "uroCtrlMisc";
  5575. uroCtrlMisc.innerHTML = '<br><b>Use default conversation markers:</b><br>';
  5576. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbNativeConvoMarkers" checked>in public WME</input><br>';
  5577. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbNativeBetaConvoMarkers" checked>in beta WME</input><br>';
  5578. uroCtrlMisc.innerHTML += '<br><br><b><input type="checkbox" id="_cbCommentCount">Show comment count on UR markers</input></b><br>';
  5579.  
  5580. uroCtrlMisc.innerHTML += '<br><br><b><input type="checkbox" id="_cbURBackfill">Backfill UR data</input></b><br>';
  5581. uroCtrlMisc.innerHTML += '<br><br><b>Marker Unstacking:</b><br>';
  5582. 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>';
  5583. 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>';
  5584.  
  5585. uroCtrlMisc.innerHTML += '<br><br><b>Use custom marker for URs tagged as:</b><br>';
  5586. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomRoadworksMarkers">[ROADWORKS]</input><br>';
  5587. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomConstructionMarkers">[CONSTRUCTION]</input><br>';
  5588. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomClosuresMarkers">[CLOSURE]</input><br>';
  5589. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomEventsMarkers">[EVENT]</input><br>';
  5590. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomNotesMarkers">[NOTE]</input><br>';
  5591. uroCtrlMisc.innerHTML += '<br><br><b>Disable popup for:</b><br>';
  5592. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitURPopup">URs</input><br>';
  5593. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitMPPopup">MPs</input><br>';
  5594. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitCamPopup">Cameras</input><br>';
  5595. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitSegPopup">Segments</input><br>';
  5596. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitLandmarkPopup">Landmarks</input><br>';
  5597. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitPUPopup">Place Updates</input><br>';
  5598.  
  5599. uroCtrlMisc.innerHTML += '<br><br><b><input type="checkbox" id="_cbWhiteBackground">Use custom background colour</input></b><br>';
  5600. 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">';
  5601. 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">';
  5602. 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>';
  5603.  
  5604. uroCtrlMisc.innerHTML += '<br><br><b><input type="checkbox" id="_cbHideAMLayer">Hide Area Manager polygons</input></b><br>';
  5605.  
  5606. uroCtrlMisc.innerHTML += '<br><br><b><input type="checkbox" id="_cbDisablePlacesFiltering">Disable Places filtering</input></b><br>';
  5607.  
  5608. uroCtrlMisc.innerHTML += '<br><br><b><input type="checkbox" id="_cbDisablePendingQuestions">Disable UR Pending Questions confirmation</input></b><br>';
  5609. uroCtrlMisc.innerHTML += '<br><b>Enable integrated scripts:</b><br>';
  5610. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbEnableDTE">Drive Tab Enhancement</input><br>';
  5611. uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbEnableSRS">Select Roundabout Segments</input><br>';
  5612.  
  5613. uroCtrlMisc.innerHTML += '<br><br><b>Settings backup/restore:</b><br>';
  5614. uroCtrlMisc.innerHTML += '<input type="button" id="_btnSettingsToText" value="Backup">&nbsp;&nbsp;&nbsp;';
  5615. uroCtrlMisc.innerHTML += '<input type="button" id="_btnTextToSettings" value="Restore">&nbsp;&nbsp;|&nbsp;&nbsp;';
  5616. uroCtrlMisc.innerHTML += '<input type="button" id="_btnClearSettingsText" value="Clear"><br>';
  5617. uroCtrlMisc.innerHTML += '<textarea id="_txtSettings" value="">';
  5618. // footer for tabs container
  5619. uroCtrlHides.id = 'uroCtrlHides';
  5620. uroCtrlHides.innerHTML = '<input type="button" id="_btnUndoLastHide" value="Undo last hide">&nbsp;&nbsp;&nbsp;';
  5621. uroCtrlHides.innerHTML += '<input type="button" id="_btnClearSessionHides" value="Undo all hides"><p>';
  5622.  
  5623. // footer for AM list
  5624. uroAMList.id = 'uroAMList';
  5625.  
  5626. window.addEventListener("beforeunload", uroSaveSettings, false);
  5627. uroRealWazeBits();
  5628. }
  5629.  
  5630.  
  5631. function dteAddHeader()
  5632. {
  5633. rlcObj = document.getElementsByClassName("result-list-container");
  5634. if(typeof rlcObj == "undefined") return;
  5635. if(typeof rlcObj[0].children[0] == "undefined") return;
  5636. if(typeof rlcObj[0].children[0].innerHTML == "undefined") return;
  5637. var thtml = rlcObj[0].children[0].innerHTML;
  5638. if(thtml.indexOf('Full drive history') == -1)
  5639. {
  5640. thtml += '<br><br><i><small>Full drive history goes back to '+dteOldestFullDrive.toDateString()+'</small></i>';
  5641. rlcObj[0].children[0].innerHTML = thtml;
  5642. }
  5643. }
  5644.  
  5645.  
  5646. function dteSetNewTabLength()
  5647. {
  5648. uroAddLog('altering ResultsPerPage parameter...');
  5649.  
  5650. var t = document.getElementById('sidepanel-drives');
  5651. t.style.overflow = 'auto';
  5652. t.style.height = (window.innerHeight * 0.6) + 'px';
  5653.  
  5654. baseloc = 'https://'+window.location.hostname+Waze.Config.api_base+'/Archive/MyList?minDistance=1000';
  5655.  
  5656. var a = new XMLHttpRequest();
  5657. var idxCheckFullDrive = 0;
  5658. var fullDrives = 0;
  5659. var foundMissingDrive = false;
  5660.  
  5661. while(!foundMissingDrive)
  5662. {
  5663. uroSetStyleDisplay(uroUserTabId,'none');
  5664. var loc = baseloc+'&offset='+fullDrives+'&count=5';
  5665. uroAddLog('requesting '+loc);
  5666. a.open('GET',loc,false);
  5667. a.send();
  5668. var b = JSON.parse(a.responseText);
  5669. var loadedDrives = b.archives.objects.length;
  5670. uroAddLog('received '+loadedDrives+' drives');
  5671. if(loadedDrives != 5) foundMissingDrive = true;
  5672.  
  5673. for(var loop=0; loop < loadedDrives; loop++)
  5674. {
  5675. if(b.archives.objects[loop].hasFullSession == false) foundMissingDrive = true;
  5676. else
  5677. {
  5678. fullDrives++;
  5679. dteOldestFullDrive = new Date(b.archives.objects[loop].startTime);
  5680. }
  5681. }
  5682. }
  5683.  
  5684. uroAddLog(fullDrives+' full drives in history');
  5685. uroAddLog('oldest drives are on '+dteOldestFullDrive.toDateString());
  5686. if(fullDrives < 5)
  5687. {
  5688. fullDrives = 5;
  5689. uroAddLog('insufficient full drives, using standard drives tab');
  5690. }
  5691. else if(fullDrives > 50)
  5692. {
  5693. uroAddLog('too many full drives for a single tab page, splitting over multiple pages...');
  5694. fullDrives = Math.ceil(fullDrives/Math.ceil(fullDrives/50));
  5695. }
  5696. uroSetStyleDisplay(uroUserTabId,'');
  5697. if((dteOldestFullDrive - dteEpoch) > 0)
  5698. {
  5699. uroAddLog('updating drives tab...');
  5700. W.map.controls[dteControlsIdx].sidePanelView.ResultsPerPage = fullDrives;
  5701. setInterval(dteAddHeader,250);
  5702. setInterval(dteCheckDriveListChanges,250);
  5703. }
  5704. }
  5705.  
  5706. function dteCheckDriveListChanges()
  5707. {
  5708. var drivesShown = document.getElementById('sidepanel-drives').getElementsByClassName('result session').length;
  5709. if(drivesShown > 0)
  5710. {
  5711. var topID = document.getElementById('sidepanel-drives').getElementsByClassName('result session')[0].getAttribute('data-id');
  5712. if(topID != dteTopID)
  5713. {
  5714. dteTopID = topID;
  5715. for(var loop = 0;loop < drivesShown; loop++)
  5716. {
  5717. var driveID = document.getElementById('sidepanel-drives').getElementsByClassName('result session')[loop].getAttribute('data-id');
  5718. var driveObj = W.model.archives.objects[driveID];
  5719. var driveDistance = driveObj.totalRoadMeters;
  5720. var driveSecs = Math.floor((driveObj.endTime - driveObj.startTime) / 1000);
  5721. var driveHours = Math.floor(driveSecs / 3600);
  5722. driveSecs -= (driveHours * 3600);
  5723. var driveMins = Math.floor(driveSecs / 60);
  5724. driveSecs -= (driveMins * 60);
  5725. var trueTime = (driveHours+':'+("0"+driveMins).slice(-2)+'.'+("0"+driveSecs).slice(-2));
  5726. document.getElementById('sidepanel-drives').getElementsByClassName('result')[loop].getElementsByTagName('span')[1].innerHTML = trueTime;
  5727. }
  5728. }
  5729. }
  5730. }
  5731.  
  5732. function srsSelect()
  5733. {
  5734. rbtID = selectionManager.selectedItems[0].model.attributes.junctionID;
  5735. uroAddLog('selecting roundabout ID '+rbtID);
  5736. selectionManager.selectControl.unselectAll();
  5737.  
  5738. for(var slIdx=0; slIdx < W.map.segmentLayer.features.length; slIdx++)
  5739. {
  5740. if(W.map.segmentLayer.features[slIdx].fid == null)
  5741. {
  5742. junctionID = W.map.segmentLayer.features[slIdx].model.attributes.junctionID;
  5743. segID = W.map.segmentLayer.features[slIdx].model.attributes.id;
  5744. }
  5745. else
  5746. {
  5747. junctionID = W.map.segmentLayer.features[slIdx].attributes.junctionID;
  5748. segID = W.map.segmentLayer.features[slIdx].fid;
  5749. }
  5750. if(junctionID == rbtID)
  5751. {
  5752. uroAddLog('...adding segment '+segID);
  5753. selectionManager.selectControl.select(W.map.segmentLayer.features[slIdx]);
  5754. }
  5755. }
  5756. }
  5757.  
  5758.  
  5759. function srsCheckSidePanel()
  5760. {
  5761. if(selectionManager.selectedItems.length == 0) return;
  5762. if(document.getElementById('srsCtrl') != null) return;
  5763. var junctionID = selectionManager.selectedItems[0].model.attributes.junctionID;
  5764. if(junctionID == null) return;
  5765. srsCtrl = document.createElement('section');
  5766. srsCtrl.id = 'srsCtrl';
  5767. srsCtrl.innerHTML = '<button id="srsButton" class="btn btn-default">Select roundabout</button>';
  5768. if(uroBetaEditor)
  5769. {
  5770. document.getElementById('edit-panel').getElementsByClassName('segment')[0].appendChild(srsCtrl);
  5771. }
  5772. else
  5773. {
  5774. document.getElementById('segment-edit-general').appendChild(srsCtrl);
  5775. }
  5776. uroSetOnClick('srsButton',srsSelect);
  5777. }
  5778.  
  5779. uroBootstrap();