WME WazeMY

WME script for WazeMY editing moderation

当前为 2022-08-04 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name WME WazeMY
  3. // @namespace https://greasyfork.org/en/scripts/404584-wazemy
  4. // @version 2022.08.05.02
  5. // @description WME script for WazeMY editing moderation
  6. // @author junyianl
  7. // @match https://beta.waze.com/*
  8. // @match https://www.waze.com/forum/*
  9. // @match https://www.waze.com/editor*
  10. // @match https://www.waze.com/*/editor*
  11. // @match https://www.waze.com/user/editor*
  12. // @require https://greasyfork.org/scripts/24851-wazewrap/code/WazeWrap.js
  13. // @grant GM_xmlhttpRequest
  14. // @license MIT
  15. // ==/UserScript==
  16.  
  17. // @connect p4.fgies.com
  18. // @connect www.jalanow.com
  19. // @connect odis.sgp1.digitaloceanspaces.com
  20.  
  21. /* global W */
  22. /* global WazeWrap */
  23. /* global $ */
  24. /* global OL */
  25. /* global OpenLayers */
  26.  
  27. /**
  28. * All mentions of script names and links in this script is my way of giving credit to where it's due.
  29. * Without those scripts, I would have no place to start.
  30. * Big thanks to the original script authors.
  31. *
  32. * Huge thanks to Epailxi and dckj for getting the lat/lons for all the cams.
  33. */
  34.  
  35. const updateMessage = "► Add traffic camera layer for Malaysia.";
  36. var staticUpdateID;
  37.  
  38. var trafficCamsData = [
  39. { desc:'Jalan Sultan Ismail / Jalan Imbi near Berjaya Times Square KL', lat:3.14369, lon:101.71245, url:'https://p4.fgies.com/kl8/img/K012W.jpg' },
  40. { desc:'Jalan Bukit Bintang / Jalan Raja Chulan near Pavilion KL', lat:3.14833, lon:101.71609, url:'https://p4.fgies.com/kl8/img/K004W.jpg' },
  41. { desc:'Jalan Sultan Ismail near Sime Darby', lat:3.16102, lon:101.69522, url:'https://p4.fgies.com/kl8/img/K011W.jpg' },
  42. { desc:'Jalan Sultan Ismail / Jalan P. Ramlee near Shangri-La Hotel', lat:3.15389, lon:101.70761, url:'https://p4.fgies.com/kl8/img/K013W.jpg' },
  43. { desc:'Jalan Sultan Ismail near Renaissance Hotel', lat:3.15929307072728, lon:101.700892565152, url:'https://p4.fgies.com/kl8/img/K029W.jpg' },
  44. { desc:'Jalan Raja Laut near KWSP', lat:3.15314, lon:101.69473, url:'https://p4.fgies.com/kl8/img/K037W.jpg' },
  45. { desc:'Jalan Raja near Stesen LRT Bandaraya', lat:3.15076, lon:101.69461, url:'https://p4.fgies.com/kl8/img/K016W.jpg' },
  46. { desc:'Bulatan Dato\' Onn near Bank Negara', lat:3.151524, lon:101.693394, url:'https://p4.fgies.com/kl8/img/K036W.jpg' },
  47. { desc:'Jalan Raja near Dataran Merdeka', lat:3.15130467327156, lon:101.693128740951, url:'https://p4.fgies.com/kl8/img/K028W.jpg' },
  48. { desc:'Jalan Kuching / Jalan Raja Laut near Bangunan DBKL', lat:3.15328733409485, lon:101.693719456795, url:'https://p4.fgies.com/kl8/img/K001W.jpg' },
  49. { desc:'Jalan Maharajalela near Maharajalela Monorail Station', lat:3.13992, lon:101.69709, url:'https://p4.fgies.com/kl8/img/K038W.jpg' },
  50. { desc:'Jalan Kinabalu near Perpustakaan KL', lat:3.14741, lon:101.69247, url:'https://p4.fgies.com/kl8/img/K008W.jpg' },
  51. { desc:'Jalan Kinabalu near Masjid Negara', lat:3.14325, lon:101.69287, url:'https://p4.fgies.com/kl8/img/K007W.jpg' },
  52. { desc:'Jalan Kuching near Jalan Sultan Ismail', lat:3.16173, lon:101.69247, url:'https://p4.fgies.com/kl8/img/K047W.jpg' },
  53. { desc:'Jalan Kuching near Bulatan Kepong', lat:3.20168, lon:101.67037, url:'https://p4.fgies.com/kl8/img/K002W.jpg' },
  54. { desc:'Jalan Kuching near Hentian Putra / PWTC', lat:3.16693332927155, lon:101.689706476829, url:'https://p4.fgies.com/kl8/img/K046W.jpg' },
  55. { desc:'Jalan Kuching near Jalan Sultan Ismail', lat:3.16343529038211, lon:101.692232025972, url:'https://p4.fgies.com/kl8/img/K023W.jpg' },
  56. { desc:'Jalan Tun Razak near Hospital Kuala Lumpur (HKL)', lat:3.17284962099842, lon:101.704733072188, url:'https://p4.fgies.com/kl8/img/K003W.jpg' },
  57. { desc:'Jalan Tun Razak near U.S Embassy KL', lat:3.15365, lon:101.72267, url:'https://p4.fgies.com/kl8/img/K017W.jpg' },
  58. { desc:'Jalan Tun Razak near Lembaga Tabung Haji', lat:3.15779, lon:101.72083, url:'https://p4.fgies.com/kl8/img/K024W.jpg' },
  59. { desc:'Jalan Tuanku Abdul Halim near Taman Duta', lat:3.15073, lon:101.6746, url:'https://p4.fgies.com/kl8/img/K044W.jpg' },
  60. { desc:'Jalan Tuanku Abdul Halim near Jalan Semantan', lat:3.15269, lon:101.67293, url:'https://p4.fgies.com/kl8/img/K045W.jpg' },
  61. { desc:'Jalan Damansara near Jalan Istana Lama', lat:3.13603, lon:101.69204, url:'https://p4.fgies.com/kl8/img/K043W.jpg' },
  62. { desc:'Jalan Syed Putra near Sekolah Kuen Cheng', lat:3.13179, lon:101.69184, url:'https://p4.fgies.com/kl8/img/K034W.jpg' },
  63. { desc:'Jalan Syed Putra near Kampung Attap', lat:3.13863, lon:101.69531, url:'https://p4.fgies.com/kl8/img/K015W.jpg' },
  64. { desc:'Jalan Damansara near Carcosa Seri Negara', lat:3.13843, lon:101.68482, url:'https://p4.fgies.com/kl8/img/K005W.jpg' },
  65. { desc:'Timur–Barat Highway near Bandar Tun Razak', lat:3.09385, lon:101.71095, url:'https://p4.fgies.com/kl8/img/K041W.jpg' },
  66. { desc:'Timur–Barat Highway near Salak Selatan', lat:3.09785, lon:101.70352, url:'https://p4.fgies.com/kl8/img/K042W.jpg' },
  67. { desc:'Jalan Cheras near Bulatan Cheras', lat:3.1136, lon:101.72816, url:'https://p4.fgies.com/kl8/img/K031W.jpg' },
  68. { desc:'Jalan Cheras near Jalan Ikan Ayu', lat:3.11799, lon:101.72806, url:'https://p4.fgies.com/kl8/img/K025W.jpg' },
  69. { desc:'Bulatan Cheras near Lotus\'s Cheras', lat:3.09925, lon:101.73784, url:'https://p4.fgies.com/kl8/img/K026W.jpg' },
  70. { desc:'Jalan Sungai Besi Near Lapangan Terbang TUDM', lat:3.12146, lon:101.70823, url:'https://p4.fgies.com/kl8/img/K039W.jpg' },
  71. { desc:'Jalan Loke Yew near Tsun Jin High School', lat:3.13407, lon:101.70685, url:'https://p4.fgies.com/kl8/img/K035W.jpg' },
  72. { desc:'Jalan Loke Yew near Viva Shopping Mall', lat:3.11887, lon:101.72196, url:'https://p4.fgies.com/kl8/img/K009W.jpg' },
  73. { desc:'KL-Seremban Highway near Jalan Sungai Besi (BHP)', lat:3.12252, lon:101.70843, url:'https://p4.fgies.com/kl8/img/K010W.jpg' },
  74. { desc:'KL-Seremban Highway near Nirvana Memorial Center', lat:3.08873, lon:101.69675, url:'https://p4.fgies.com/kl8/img/K019W.jpg' },
  75. { desc:'KL-Seremban Highway near Petronas TPM', lat:3.05429, lon:101.70517, url:'https://p4.fgies.com/kl8/img/K040W.jpg' },
  76. ];
  77.  
  78. (function() {
  79. 'use strict';
  80. var settings = {};
  81.  
  82. function bootstrap(tries = 1) {
  83. if (W && W.map && W.model && W.loginManager.user &&
  84. $ && WazeWrap.Ready) {
  85. init();
  86. } else if (tries < 1000) {
  87. setTimeout(function () {bootstrap(++tries);}, 200);
  88. } else {
  89. WazeWrap.Alerts.error(GM_info.script.name, "Bootstrap timeout.")
  90. }
  91. }
  92.  
  93. async function init() {
  94. let $section = $('<div>');
  95. $section.html([
  96. '<div>',
  97. 'Version: <span id="wazemyVersion"></span><br>',
  98. '<span id="wazemyUsername"></span> (<span id="wazemyRank"></span>)',
  99. '</div><br>',
  100. '<div id="wazemySettings">',
  101. '<b>Settings</b><br>',
  102. '<input type="checkbox" id="wazemySettings_tooltip"><label for="wazemySettings_tooltip">Map tooltip</label><br>',
  103. '<input type="checkbox" id="wazemySettings_trafcam"><label for="wazemySettings_trafcam">Traffic cameras</label><br>',
  104. '</div><br>',
  105. '<div>',
  106. '<b>Shortcuts</b><br>',
  107. 'Ctrl+Alt+C: Copy lat/lon of mouse position to clipboard.<br>',
  108. '</div>'
  109. ].join(' '));
  110. // Initialize features of WME WazeMY
  111. wazemyTooltip_init();
  112. wazemyTrafcam_init();
  113.  
  114. new WazeWrap.Interface.Tab('WazeMY', $section.html(), initializeSettings);
  115. WazeWrap.Interface.ShowScriptUpdate("WME WazeMY", GM_info.script.version,
  116. updateMessage,
  117. "https://greasyfork.org/en/scripts/404584-wazemy", null);
  118.  
  119.  
  120. // Initialize keyboard shortcuts
  121. new WazeWrap.Interface.Shortcut('WazeMY_latloncopy', 'Copies lat/lon of mouse position', 'wazemy', 'WazeMY', 'CA+c', wazemyCopyLatLon, null).add();
  122. }
  123.  
  124. /* ******* */
  125. /* Tooltip */
  126. /* ******* */
  127. function wazemyTooltip_init() {
  128. let $tooltip = $('<div/>');
  129. $tooltip.attr('id', 'wazemyTooltip');
  130. $tooltip.css({
  131. 'height':'auto',
  132. 'width':'auto',
  133. 'background':'rgba(0,0,0,0.5)',
  134. 'color':'white',
  135. 'borderRadius':'5px',
  136. 'padding':'5px',
  137. 'position':'absolute',
  138. 'top':'0px',
  139. 'left':'0px',
  140. 'visibility':'hidden',
  141. 'zIndex':'10000'
  142. })
  143. $tooltip.appendTo('body');
  144. }
  145.  
  146. function wazemyTooltip_initSettings() {
  147. setChecked('wazemySettings_tooltip', settings.tooltip);
  148. if (settings.tooltip) {
  149. WazeWrap.Events.register('mousemove', null, wazemyTooltip_show);
  150. }
  151. $('#wazemySettings_tooltip').change(function () {
  152. var settingName = $(this)[0].id.substr(15); // strip off the "wazemySettings_" prefix
  153. settings[settingName] = this.checked;
  154. saveSettings();
  155. if (this.checked) {
  156. WazeWrap.Events.register('mousemove', null, wazemyTooltip_show);
  157. }
  158. else {
  159. WazeWrap.Events.unregister('mousemove', null, wazemyTooltip_show);
  160. }
  161. });
  162. }
  163.  
  164. function wazemyTooltip_show(e) { // from URO+
  165. var result = '';
  166. var showTooltip = false;
  167.  
  168. let landmark = W.map.venueLayer.getFeatureBy('renderIntent', 'highlight');
  169. let segment = W.map.segmentLayer.getFeatureBy('renderIntent', 'highlight');
  170.  
  171. if (landmark != null) {
  172. result = '<b>' + landmark.model.attributes.name + '</b><br>';
  173. let address = landmark.model.getAddress();
  174. try {
  175. result += address.attributes.houseNumber ? (address.attributes.houseNumber + ', ') : ''
  176. result += (address.attributes.street.name ? address.attributes.street.name : 'No street') + '<br>';
  177. result += address.attributes.city.attributes.name + ', ';
  178. result += address.attributes.state.name + '<br>';
  179. }
  180. catch {
  181. result += 'No address<br>';
  182. }
  183. result += '<b>Lock:</b> ' + (landmark.model.getLockRank() + 1);
  184. showTooltip = true;
  185. } else if (segment != null) {
  186. let segmentId = segment.model.attributes.id;
  187. // let primaryStreetId = WazeWrap.Model.getPrimaryStreetId(segmentId);
  188. let address = segment.model.getAddress();
  189. result = '<b>' + (address.attributes.street.name ? address.attributes.street.name : 'No street') + '</b><br>';
  190. result += address.attributes.city.attributes.name + ', ' + address.attributes.state.name + '<br>';
  191. result += '<b>ID:</b> ' + segmentId + '<br>';
  192. result += '<b>Lock:</b> ' + (segment.model.getLockRank() + 1);
  193. showTooltip = true;
  194. }
  195.  
  196. if (showTooltip == true) {
  197. let tw = $('#wazemyTooltip').width();
  198. let th = $('#wazemyTooltip').height();
  199. var tooltipX = e.clientX + window.scrollX + 15;
  200. var tooltipY = e.clientY + window.scrollY + 15;
  201. if ((tooltipX + tw) > W.map.$map.innerWidth()) {
  202. tooltipX -= tw + 20; // 20 = scroll bar size
  203. if (tooltipX < 0) tooltipX = 0;
  204. }
  205. if ((tooltipY + th) > W.map.$map.innerHeight()) {
  206. tooltipY -= th + 20;
  207. if (tooltipY < 0) tooltipY = 0;
  208. }
  209. $('#wazemyTooltip').html(result);
  210. $('#wazemyTooltip').css({
  211. 'top':tooltipY + 'px',
  212. 'left':tooltipX + 'px',
  213. 'visibility':'visible'
  214. });
  215. } else {
  216. $('#wazemyTooltip').css('visibility', 'hidden');
  217. }
  218. }
  219.  
  220. /* *************** */
  221. /* Traffic cameras */
  222. /* *************** */
  223. // Adapted from WME DOT Cameras
  224. var wazemyTrafcamLayer;
  225.  
  226. function wazemyTrafcam_init() {
  227. if (!OpenLayers.Icon) {
  228. wazemyTrafcam_installIconClass();
  229. }
  230. wazemyTrafcamLayer = new OpenLayers.Layer.Markers("wazemyTrafcamLayer");
  231. W.map.addLayer(wazemyTrafcamLayer);
  232. wazemyTrafcam_show();
  233. wazemyTrafcamLayer.setVisibility(false);
  234. }
  235.  
  236. function wazemyTrafcam_initSettings() {
  237. setChecked('wazemySettings_trafcam', settings.trafcam);
  238. if (settings.trafcam) {
  239. wazemyTrafcamLayer.setVisibility(true);
  240. // WazeWrap.Events.register('moveend', null, wazemyTrafcam_show);
  241. }
  242. $('#wazemySettings_trafcam').change(function () {
  243. var settingName = $(this)[0].id.substr(15); // strip off the "wazemySettings_" prefix
  244. settings[settingName] = this.checked;
  245. saveSettings();
  246. if (this.checked) {
  247. wazemyTrafcamLayer.setVisibility(true);
  248. // WazeWrap.Events.register('moveend', null, wazemyTrafcam_show);
  249. } else {
  250. // WazeWrap.Events.unregister('moveend', null, wazemyTrafcam_show);
  251. wazemyTrafcamLayer.setVisibility(false);
  252. }
  253. });
  254. }
  255.  
  256. function wazemyTrafcam_show(e) {
  257. trafficCamsData.forEach(e => {
  258. wazemyTrafcam_drawCam({
  259. desc:e.desc,
  260. src:e.url,
  261. width:20,
  262. height:20,
  263. lat:e.lat,
  264. lon:e.lon
  265. });
  266. });
  267. }
  268.  
  269. function wazemyTrafcam_drawCam(spec) {
  270. const camIcon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAAGXcA1uAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpBRDNGNTkwRTYzQThFMzExQTc4MDhDNjAwODdEMzdEQSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo2OUI0RUEyN0IwRjcxMUUzOERFM0E1OTJCRUY3NTFBOCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo2OUI0RUEyNkIwRjcxMUUzOERFM0E1OTJCRUY3NTFBOCIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1LjEgV2luZG93cyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjZGOEJBMzExNkZCMEUzMTFCOEY5QTU3QUQxM0M2MjI5IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkFEM0Y1OTBFNjNBOEUzMTFBNzgwOEM2MDA4N0QzN0RBIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+TV0cjwAABbhJREFUeNpiYIAAXiZGCIMPiP//f8DwnwnI+PT/HZD8y8AAEEBQVQzTwOSfuwz/u6qAyh4y/Gf8f4/hPwMnUJSZgQEggMCyzpZAmbsILMTHcAokPhPEWT8dqJoBgvetAtMMDBIiDCf/P4bqeMXwf+t8BiOAAGJAAqVA7A1iPH/+goFBT4OB8f9LJDueAzFQgOHGLoTZYEGgpJgww0+G/68ZQArAEsryEHpRN5BuK4FIcHMhjJORVTvBYG3MwPD2CkKwKAVI/3nBABBAYOcY6zKAjGSQEmP4cGkXxMlgK4BeaCll+B/lzzDh/yegmr8vIO4HGv/l/0eG/w4WDP9fnUM4Dhl/uMzwf/6CFQ4g9RUgE3ctRvgGGSvJMfw/tw3i7sY8hv8sQMGrQE8yuFoBZe8CeRwMDIKaDAyWRgwM2xYD+exA/AuIvwAV3kaE6sSPQCuBHv2vqczwf0YL0MR7SE4CsgsTGP5///aSCZQSGDRVGPJfv2dgNDNkcP30heHbB6BpyzYyMCRVMjCwqDIcOX+LgTEtioGRhfn/P4AAbJTfK0NhGMe/Z+ecpVkrScnIlCiWkoulpFyhxgXKXCGK3XGBG/4BJcoNN665tqsxo6XshiKtyQybn82vMZPF63nPOXKYi+fieU7P8z59P9/n6NlBVNrRRDFPMUlRIGhmM0gWzk5NSCFMuDE2MqAaUJGUhDgOgNmKkXmLwMRudA11diynI9lSKhEHG+oBu9q1mHkDf9AWWkM0dgHEb4H+PqqkKD51uxpJuSoDHpIfAowyohyUveJH+9pqUjigav/9UnIfzO/frkRvBxUuwcpK/gc3PkzfzynuwRoanYuStZDKaeAkwA8QEPJ/CYfpBUCmqxp1E7uXJ6u0tUNVQbvIR+DIBzgHgQMvrZ5LZWIiSuowh6N+nQ9ZYgnNcLTzdRBsz5Ot1socWCr1KipYulrJVDIQjqjwgqsESvcPQB5QWmP2nsWem5X80IeizhaadPfHQwTxnXJTDk5ZQgeOOCC0ScY0wtPdRrc4AzY7BVZuQ8bVDhcXJLyhNnwJUFj5hTQVhmH8mQ7H5nYYkRxJw8hqBWYsLIr+gisKYobdjKguClOKLiQvgrrwqogiIr1wECHdRCCjIopNiCKZIGkthysrrWSklg36M6O5fT3fzmk7C8kDL4zt2/neP8/ze01/b6XuceWsVmAJJR56gurObjSn0/DWrEY152SmIyFBNk1sxZhBZAQTyVmEDjeiy9eAQdm4FK1gLlHg8Y3CYlXzZW12A1+GYd1Yi1u1LogXQSYgmxdnjM8jsTFNZvLMxADE3h0QS8vxNNqLJWKa2ZMXBRXwaaNmL/XdoUct+hhtjF+MFBZ+zJq5Gw6ywoRyI/xs/JjJtCj38+XWo3rGdM6pI3nlqYshmmiGx7fJpLE8rAqGZQy+49o5CNeauoeplJZZPbWfztqSWurvmV/ixrCXQjRSFQE/xI8R/dK44VJae99OorWt/Xh2tZxp0Q+903zynX/q6YLwevgy28IXyiBYxCY3cXYeIvGGRL0Isc697Z5k0NRMQj8Grd92zuDALuAuIRm8CVSohe1uYZ+T74FwADjdBFBh6GgH+mm3ZuLDSb9Ocg9YLNYZOeSyUitevupFeWWVTlzjQ0dNfQJW1fOybulPWlmyZ85wpshQC43/m+9YsR2ZTn9wg5z955+z2FO3H0PRIIqcHHzgPpAgNukwOJzAwCB3NiFQxsyyjJ37J4lMXklpfnaRyidaO3xe7+6h3JmVy2CjkcInD3EO3/T1xsFn3mobX0z+RzkfNAxcpXrIjo+RkFKp0VLkk1hfwwqJr69RODxbcH05gem/wIEN62TV13XuMxNIvqYYqCT6R6x14UHsEarkwhBxJbtnC4wmS9fXDuT2stFkxIDsp4tfbZU5MCr0jnMbIMLoKy7Gc8WunU3rxHMoCmKxUaiqij/5alOWhMPoGAAAAABJRU5ErkJggg==';
  271. let size = new OpenLayers.Size(20,20);
  272. let icon = new OpenLayers.Icon(camIcon, size);
  273. // let offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
  274. let epsg4326 = new OpenLayers.Projection("EPSG:4326"); // WGS 1984 projection. Malaysia uses EPSG:900913
  275. let projectTo = W.map.getProjectionObject();
  276. let lonLat = new OpenLayers.LonLat(spec.lon, spec.lat).transform(epsg4326, projectTo);
  277. var newMarker = new OpenLayers.Marker(lonLat, icon);
  278. newMarker.title = spec.desc;
  279. newMarker.url = spec.src;
  280. newMarker.width = spec.width;
  281. newMarker.height = spec.height;
  282. newMarker.location = lonLat;
  283. newMarker.events.register('click', newMarker, wazemyTrafcam_popupCam);
  284. wazemyTrafcamLayer.addMarker(newMarker);
  285. }
  286.  
  287. function wazemyTrafcam_popupCam(e) {
  288. console.log("wazemyTrafcam_popupCam");
  289.  
  290. clearInterval(staticUpdateID);
  291. $("#gmPopupContainerCam").remove();
  292. $("#gmPopupContainerCam").hide();
  293.  
  294. var popupHTML = (['<div id="gmPopupContainerCam" style="margin: 1;text-align: center;padding: 5px;z-index: 1100; position: absolute; color: white; background: rgba(0,0,0,0.5)">' +
  295. '<a href="#close" id="gmCloseCamDlgBtn" title="Close" style="color:red">X</a>' +
  296. '<table border=0><tr><td><div id="mycamdivheader" style="min-height: 20px;">' + this.title + '</div></td></tr>' +
  297. '<tr><td><img style="width:400px" id="staticimage"></td></tr>' +
  298. '</table></div>'
  299. ]);
  300. $("body").append(popupHTML);
  301. GM_xmlhttpRequest({
  302. method: 'GET',
  303. responseType: 'blob',
  304. headers: {
  305. "authority":"p4.fgies.com",
  306. "referer":'https://www.jalanow.com/',
  307. 'accept':'image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8'
  308. },
  309. url: this.url,
  310. onload: function (response) {
  311. document.getElementById('staticimage').src = URL.createObjectURL(response.response);
  312. }
  313. });
  314. $("#gmPopupContainerCam").css({ left: e.clientX + window.scrollX + 15 });
  315. $("#gmPopupContainerCam").css({ top: e.clientY + window.scrollY + 15 });
  316.  
  317. //Add listener for popup's "Close" button
  318. $("#gmCloseCamDlgBtn").click(function () {
  319. clearInterval(staticUpdateID);
  320. $("#gmPopupContainerCam").remove();
  321. $("#gmPopupContainerCam").hide();
  322. });
  323. wazemyTrafcam_dragElement(document.getElementById("gmPopupContainerCam"));
  324. }
  325.  
  326. function wazemyTrafcam_installIconClass() {
  327. OpenLayers.Icon = OpenLayers.Class({
  328. url: null,
  329. size: null,
  330. offset: null,
  331. calculateOffset: null,
  332. imageDiv: null,
  333. px: null,
  334. initialize: function (a, b, c, d) {
  335. this.url = a;
  336. this.size = b || {
  337. w: 20,
  338. h: 20
  339. };
  340. this.offset = c || {
  341. x: -(this.size.w / 2),
  342. y: -(this.size.h / 2)
  343. };
  344. this.calculateOffset = d;
  345. a = OpenLayers.Util.createUniqueID("OL_Icon_");
  346. let div = this.imageDiv = OpenLayers.Util.createAlphaImageDiv(a);
  347. $(div.firstChild).removeClass('olAlphaImg'); // LEAVE THIS LINE TO PREVENT WME-HARDHATS SCRIPT FROM TURNING ALL ICONS INTO HARDHAT WAZERS --MAPOMATIC
  348. },
  349. destroy: function () {
  350. this.erase();
  351. OpenLayers.Event.stopObservingElement(this.imageDiv.firstChild);
  352. this.imageDiv.innerHTML = "";
  353. this.imageDiv = null;
  354. },
  355. clone: function () {
  356. return new OpenLayers.Icon(this.url, this.size, this.offset, this.calculateOffset);
  357. },
  358. setSize: function (a) {
  359. null !== a && (this.size = a);
  360. this.draw();
  361. },
  362. setUrl: function (a) {
  363. null !== a && (this.url = a);
  364. this.draw();
  365. },
  366. draw: function (a) {
  367. OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, null, this.size, this.url, "absolute");
  368. this.moveTo(a);
  369. return this.imageDiv;
  370. },
  371. erase: function () {
  372. null !== this.imageDiv && null !== this.imageDiv.parentNode && OpenLayers.Element.remove(this.imageDiv);
  373. },
  374. setOpacity: function (a) {
  375. OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, null, null, null, null, null, null, a);
  376. },
  377. moveTo: function (a) {
  378. null !== a && (this.px = a);
  379. null !== this.imageDiv && (null === this.px ? this.display(!1) : (
  380. this.calculateOffset && (this.offset = this.calculateOffset(this.size)),
  381. OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, {
  382. x: this.px.x + this.offset.x,
  383. y: this.px.y + this.offset.y
  384. })
  385. ));
  386. },
  387. display: function (a) {
  388. this.imageDiv.style.display = a ? "" : "none";
  389. },
  390. isDrawn: function () {
  391. return this.imageDiv && this.imageDiv.parentNode && 11 != this.imageDiv.parentNode.nodeType;
  392. },
  393. CLASS_NAME: "OpenLayers.Icon"
  394. });
  395. }
  396.  
  397. // Make the DIV element draggable:
  398. function wazemyTrafcam_dragElement(elmnt) {
  399. var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
  400. if (document.getElementById("mycamdivheader")) {
  401. // if present, the header is where you move the DIV from:
  402. document.getElementById("mycamdivheader").onmousedown = dragMouseDown;
  403. } else {
  404. // otherwise, move the DIV from anywhere inside the DIV:
  405. elmnt.onmousedown = dragMouseDown;
  406. }
  407.  
  408. function dragMouseDown(e) {
  409. e = e || window.event;
  410. e.preventDefault();
  411. // get the mouse cursor position at startup:
  412. pos3 = e.clientX;
  413. pos4 = e.clientY;
  414. document.onmouseup = closeDragElement;
  415. // call a function whenever the cursor moves:
  416. document.onmousemove = elementDrag;
  417. }
  418.  
  419. function elementDrag(e) {
  420. e = e || window.event;
  421. e.preventDefault();
  422. // calculate the new cursor position:
  423. pos1 = pos3 - e.clientX;
  424. pos2 = pos4 - e.clientY;
  425. pos3 = e.clientX;
  426. pos4 = e.clientY;
  427. // set the element's new position:
  428. elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
  429. elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
  430. }
  431.  
  432. function closeDragElement() {
  433. // stop moving when mouse button is released:
  434. document.onmouseup = null;
  435. document.onmousemove = null;
  436. }
  437. }
  438.  
  439. /* ************ */
  440. /* Copy lat/lon */
  441. /* ************ */
  442. function wazemyCopyLatLon(){
  443. copyToClipboard($('.mouse-position').text());
  444. }
  445.  
  446. function initializeSettings() {
  447. loadSettings();
  448.  
  449. $('#wazemyVersion').text(GM_info.script.version);
  450. $('#wazemyUsername').text(WazeWrap.User.Username());
  451. $('#wazemyRank').text(WazeWrap.User.Rank());
  452.  
  453. wazemyTooltip_initSettings();
  454. wazemyTrafcam_initSettings();
  455. }
  456.  
  457. function saveSettings() {
  458. if (localStorage) {
  459. var localsettings = {
  460. tooltip: settings.tooltip,
  461. trafcam: settings.trafcam
  462. };
  463.  
  464. localStorage.setItem('WME_wazemySettings', JSON.stringify(localsettings));
  465. }
  466. }
  467.  
  468. function loadSettings() {
  469. var loadedSettings = $.parseJSON(localStorage.getItem("WME_wazemySettings"));
  470. var defaultSettings = {
  471. tooltip: false,
  472. };
  473. settings = loadedSettings ? loadedSettings : defaultSettings;
  474. for (var prop in defaultSettings) {
  475. if (!settings.hasOwnProperty(prop)) {
  476. settings[prop] = defaultSettings[prop];
  477. }
  478. }
  479. }
  480.  
  481. function setChecked(checkboxId, checked) {
  482. $('#' + checkboxId).prop('checked', checked);
  483. }
  484.  
  485. // utility functions
  486. var copyToClipboard = function(str) { // from PIE
  487. var $temp = $('<input>');
  488. $('body').append($temp);
  489. $temp.val(str).select();
  490. document.execCommand('copy');
  491. $temp.remove();
  492. };
  493.  
  494. bootstrap();
  495. })();