WME WazeMY

WME script for WazeMY editing moderation

当前为 2022-09-24 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name WME WazeMY
  3. // @namespace https://greasyfork.org/en/scripts/404584-wazemy
  4. // @version 2022.09.24.01
  5. // @description WME script for WazeMY editing moderation
  6. // @author junyianl
  7. // @match https://beta.waze.com/*
  8. // @match https://www.waze.com/editor*
  9. // @match https://www.waze.com/*/editor*
  10. // @exclude https://www.waze.com/user/editor*
  11. // @require https://greasyfork.org/scripts/24851-wazewrap/code/WazeWrap.js
  12. // @require https://greasyfork.org/scripts/449165-wme-wazemy-trafcamlist/code/wme-wazemy-trafcamlist.js
  13. // @grant GM_xmlhttpRequest
  14. // @license MIT
  15. // ==/UserScript==
  16.  
  17. // @connect p3.fgies.com
  18. // @connect p4.fgies.com
  19. // @connect t2.fgies.com
  20. // @connect jalanow.com
  21. // @connect llm.gov.my
  22.  
  23. /* global W */
  24. /* global WazeWrap */
  25. /* global $ */
  26. /* global OL */
  27. /* global OpenLayers */
  28.  
  29. /**
  30. * All mentions of script names and links in this script is my way of giving
  31. * credit to where it's due.
  32. * Without those scripts, I would have no place to start.
  33. * Big thanks to the original script authors.
  34. *
  35. * Huge thanks to the following contributors for cam locations around Malaysia.
  36. * :: epailxi | dckj | firman_bakti | rickylo103 | kweeheng ::
  37. */
  38.  
  39. // var trafficCamsData = [
  40. // { desc: 'Jalan Sultan Ismail / Jalan Imbi near Berjaya Times Square KL', lat: 3.14369, lon: 101.71245, url: { Jalanow: 'https://p4.fgies.com/kl8/img/K012W.jpg' } },
  41. // { desc: 'PLS CAM C2 SLIM RIVER IC KM372.6 NB', lat: 3.84943, lon: 101.39765, url: {LLM: 'https://www.llm.gov.my/assets/ajax.vigroot.php?h=PLS|PLS CAM C2 SLIM RIVER IC KM372.6 NB'} },
  42. // { desc: 'PLUS-Utara near Tapah KM324.4 SB', lat: 4.236409, lon: 101.255623, url: {Jalanow: 'https://p3.fgies.com/bucket-e1e2/E1E2-22.jpg',LLM: 'https://www.llm.gov.my/assets/ajax.vigroot.php?h=PLS|PLS CAM C1 TAPAH KM324.4 SB'} },
  43. // { desc: 'DUKE CAM 10 SENTUL PASAR KM0.7 NB', lat: 3.19891, lon: 101.69867, url: {Jalanow: 'https://p3.fgies.com/bucket-duke/DUKE-10.jpg',LLM: 'https://www.llm.gov.my/assets/ajax.vigroot.php?h=DUKE'} },
  44. // { desc: 'PLUS-Utara near Slim River KM373.9 NB', lat: 3.841385, lon: 101.407039, url: {Jalanow: 'https://p3.fgies.com/bucket-e1e2/E1E2-06.jpg',LLM: 'https://www.llm.gov.my/assets/ajax.vigroot.php?h=PLS|PLS CAM C2 SLIM RIVER KM373.9 NB'} },
  45. // ];
  46.  
  47. const updateMessage = `
  48. ► Updates to existing cam list.
  49. `;
  50.  
  51. var staticUpdateID;
  52.  
  53. (function () {
  54. 'use strict';
  55. var settings = {};
  56.  
  57. function bootstrap(tries = 1) {
  58. if (W && W.map && W.model && W.loginManager.user &&
  59. $ && WazeWrap.Ready) {
  60. init();
  61. } else if (tries < 1000) {
  62. setTimeout(function () { bootstrap(++tries); }, 200);
  63. } else {
  64. WazeWrap.Alerts.error(GM_info.script.name, "Bootstrap timeout.")
  65. }
  66. }
  67.  
  68. async function init() {
  69. let $section = $('<div>');
  70. $section.html([
  71. '<div>',
  72. 'Version: <span id="wazemyVersion"></span><br>',
  73. '<span id="wazemyUsername"></span> (<span id="wazemyRank"></span>)',
  74. '</div><br>',
  75. '<div id="wazemySettings">',
  76. '<b>Settings</b><br>',
  77. '<input type="checkbox" id="wazemySettings_tooltip">',
  78. '<label for="wazemySettings_tooltip">Map tooltip</label><br>',
  79. '<input type="checkbox" id="wazemySettings_trafcam">',
  80. '<label for="wazemySettings_trafcam">Traffic cameras</label><br>',
  81. '</div><br>',
  82. '<div>',
  83. '<b>Shortcuts</b><br>',
  84. 'Ctrl+Alt+C: Copy lat/lon of mouse position to clipboard.<br>',
  85. '</div>'
  86. ].join(' '));
  87.  
  88. // Initialize features of WME WazeMY
  89. wazemyTooltip_init();
  90. wazemyTrafcam_init();
  91.  
  92. new WazeWrap.Interface.Tab('WazeMY', $section.html(), initializeSettings);
  93. WazeWrap.Interface.ShowScriptUpdate("WME WazeMY", GM_info.script.version,
  94. updateMessage, "https://greasyfork.org/en/scripts/404584-wazemy", null);
  95.  
  96. // Initialize keyboard shortcuts
  97. new WazeWrap.Interface.Shortcut('WazeMY_latloncopy',
  98. 'Copies lat/lon of mouse position', 'wazemy', 'WazeMY', 'CA+c',
  99. wazemyCopyLatLon, null).add();
  100. }
  101.  
  102. /* ******* */
  103. /* Tooltip */
  104. /* ******* */
  105. function wazemyTooltip_init() {
  106. let $tooltip = $('<div/>');
  107. $tooltip.attr('id', 'wazemyTooltip');
  108. $tooltip.css({
  109. 'height': 'auto',
  110. 'width': 'auto',
  111. 'background': 'rgba(0,0,0,0.5)',
  112. 'color': 'white',
  113. 'borderRadius': '5px',
  114. 'padding': '5px',
  115. 'position': 'absolute',
  116. 'top': '0px',
  117. 'left': '0px',
  118. 'visibility': 'hidden',
  119. 'zIndex': '10000'
  120. })
  121. $tooltip.appendTo('body');
  122. }
  123.  
  124. function wazemyTooltip_initSettings() {
  125. setChecked('wazemySettings_tooltip', settings.tooltip);
  126. if (settings.tooltip) {
  127. WazeWrap.Events.register('mousemove', null, wazemyTooltip_show);
  128. }
  129. $('#wazemySettings_tooltip').change(function () {
  130. var settingName = $(this)[0].id.substr(15); // strip off the "wazemySettings_" prefix
  131. settings[settingName] = this.checked;
  132. saveSettings();
  133. if (this.checked) {
  134. WazeWrap.Events.register('mousemove', null, wazemyTooltip_show);
  135. }
  136. else {
  137. $('#wazemyTooltip').css('visibility', 'hidden');
  138. WazeWrap.Events.unregister('mousemove', null, wazemyTooltip_show);
  139. }
  140. });
  141. }
  142.  
  143. function wazemyTooltip_show(e) { // from URO+
  144. var result = '';
  145. var showTooltip = false;
  146.  
  147. let landmark = W.map.venueLayer.getFeatureBy('renderIntent', 'highlight');
  148. let segment = W.map.segmentLayer.getFeatureBy('renderIntent', 'highlight');
  149.  
  150. if (landmark != null) {
  151. result = '<b>' + landmark.model.attributes.name + '</b><br>';
  152. let address = landmark.model.getAddress();
  153. try {
  154. result += address.attributes.houseNumber ? (address.attributes.houseNumber + ', ') : ''
  155. result += (address.attributes.street.name ? address.attributes.street.name : 'No street') + '<br>';
  156. result += address.attributes.city.attributes.name + ', ';
  157. result += address.attributes.state.name + '<br>';
  158. }
  159. catch {
  160. result += 'No address<br>';
  161. }
  162. result += '<b>Lock:</b> ' + (landmark.model.getLockRank() + 1);
  163. showTooltip = true;
  164. } else if (segment != null) {
  165. let segmentId = segment.model.attributes.id;
  166. // let primaryStreetId = WazeWrap.Model.getPrimaryStreetId(segmentId);
  167. let address = segment.model.getAddress();
  168. result = '<b>';
  169. result += address.attributes.street.name ? address.attributes.street.name : 'No street';
  170. result += '</b><br>';
  171. result += address.attributes.city.attributes.name + ', ' + address.attributes.state.name;
  172. result += '<br>';
  173. result += '<b>ID:</b> ' + segmentId + '<br>';
  174. result += '<b>Lock:</b> ' + (segment.model.getLockRank() + 1);
  175. showTooltip = true;
  176. }
  177.  
  178. if (showTooltip == true) {
  179. let tw = $('#wazemyTooltip').width();
  180. let th = $('#wazemyTooltip').height();
  181. var tooltipX = e.clientX + window.scrollX + 15;
  182. var tooltipY = e.clientY + window.scrollY + 15;
  183. // Handle cases where tooltip is too near the edge.
  184. if ((tooltipX + tw) > W.map.$map.innerWidth()) {
  185. tooltipX -= tw + 20; // 20 = scroll bar size
  186. if (tooltipX < 0) tooltipX = 0;
  187. }
  188. if ((tooltipY + th) > W.map.$map.innerHeight()) {
  189. tooltipY -= th + 20;
  190. if (tooltipY < 0) tooltipY = 0;
  191. }
  192. $('#wazemyTooltip').html(result);
  193. $('#wazemyTooltip').css({
  194. 'top': tooltipY + 'px',
  195. 'left': tooltipX + 'px',
  196. 'visibility': 'visible'
  197. });
  198. } else {
  199. $('#wazemyTooltip').css('visibility', 'hidden');
  200. }
  201. }
  202.  
  203. /* *************** */
  204. /* Traffic cameras */
  205. /* *************** */
  206. // Adapted from WME DOT Cameras
  207. var wazemyTrafcamLayer;
  208.  
  209. function wazemyTrafcam_init() {
  210. if (!OpenLayers.Icon) {
  211. wazemyTrafcam_installIconClass();
  212. }
  213. wazemyTrafcamLayer = new OpenLayers.Layer.Markers("wazemyTrafcamLayer");
  214. W.map.addLayer(wazemyTrafcamLayer);
  215. wazemyTrafcam_showIcons();
  216. wazemyTrafcamLayer.setVisibility(false);
  217. }
  218.  
  219. function wazemyTrafcam_initSettings() {
  220. setChecked('wazemySettings_trafcam', settings.trafcam);
  221. if (settings.trafcam) {
  222. wazemyTrafcamLayer.setVisibility(true);
  223. // WazeWrap.Events.register('moveend', null, wazemyTrafcam_show);
  224. }
  225. $('#wazemySettings_trafcam').change(function () {
  226. var settingName = $(this)[0].id.substr(15); // strip off the "wazemySettings_" prefix
  227. settings[settingName] = this.checked;
  228. saveSettings();
  229. if (this.checked) {
  230. wazemyTrafcamLayer.setVisibility(true);
  231. // WazeWrap.Events.register('moveend', null, wazemyTrafcam_show);
  232. } else {
  233. // WazeWrap.Events.unregister('moveend', null, wazemyTrafcam_show);
  234. wazemyTrafcamLayer.setVisibility(false);
  235. }
  236. });
  237. }
  238.  
  239. function wazemyTrafcam_showIcons() {
  240. trafficCamsData.forEach((e, idx) => {
  241. wazemyTrafcam_drawCamIcon({
  242. idx: idx,
  243. desc: e.desc,
  244. src: e.url,
  245. width: 20,
  246. height: 20,
  247. lat: e.lat,
  248. lon: e.lon
  249. });
  250. });
  251. }
  252.  
  253. function wazemyTrafcam_drawCamIcon(spec) {
  254. const camIcon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAAGXcA1uAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpBRDNGNTkwRTYzQThFMzExQTc4MDhDNjAwODdEMzdEQSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo2OUI0RUEyN0IwRjcxMUUzOERFM0E1OTJCRUY3NTFBOCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo2OUI0RUEyNkIwRjcxMUUzOERFM0E1OTJCRUY3NTFBOCIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1LjEgV2luZG93cyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjZGOEJBMzExNkZCMEUzMTFCOEY5QTU3QUQxM0M2MjI5IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkFEM0Y1OTBFNjNBOEUzMTFBNzgwOEM2MDA4N0QzN0RBIi8+IDwvcmRmOkRlc2NyaXB0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';
  255. let size = new OpenLayers.Size(20, 20);
  256. let icon = new OpenLayers.Icon(camIcon, size);
  257. let epsg4326 = new OpenLayers.Projection("EPSG:4326"); // WGS 1984 projection. Malaysia uses EPSG:900913
  258. let projectTo = W.map.getProjectionObject();
  259. let lonLat = new OpenLayers.LonLat(spec.lon, spec.lat).transform(epsg4326, projectTo);
  260. var newMarker = new OpenLayers.Marker(lonLat, icon);
  261. newMarker.idx = spec.idx;
  262. newMarker.title = spec.desc;
  263. newMarker.url = spec.src;
  264. newMarker.width = spec.width;
  265. newMarker.height = spec.height;
  266. newMarker.location = lonLat;
  267. newMarker.events.register('click', newMarker, wazemyTrafcam_popupCam);
  268. wazemyTrafcamLayer.addMarker(newMarker);
  269. }
  270.  
  271. function wazemyTrafcam_popupCam(e) {
  272. // console.log("wazemyTrafcam_popupCam");
  273.  
  274. clearInterval(staticUpdateID);
  275. $("#gmPopupContainerCam").remove();
  276. $("#gmPopupContainerCam").hide();
  277.  
  278. var popupHTML = ([`
  279. <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)">
  280. <table border=0>
  281. <tr>
  282. <td><div id="mycamdivheader" style="min-height: 20px;white-space: pre-wrap;white-space: -moz-pre-wrap; white-space: -pre-wrap;white-space: -o-pre-wrap;word-wrap: break-word;width:380px">${this.title}</div></td>
  283. <td align="right"><a href="#close" id="gmCloseCamDlgBtn" title="Close" style="color:red">X</a></td>
  284. </tr>
  285. <tr><td colspan=2>Select source:
  286. <select id="wazemy_camSource">
  287. </select>
  288. <div hidden id="mycamid">${this.idx}</div>
  289. </td></tr>
  290. <tr><td colspan=2><img style="width:400px" id="staticimage"></td></tr>
  291. </table></div>
  292. `]);
  293. $("body").append(popupHTML);
  294.  
  295. for (var urlsrc in this.url) {
  296. if (urlsrc == 'LLM') {
  297. let sp = this.url['LLM'].split('|');
  298. if (sp.length == 2) {
  299. $('#wazemy_camSource').append($('<option>').val(urlsrc).text(urlsrc));
  300. }
  301. } else {
  302. $('#wazemy_camSource').append($('<option>').val(urlsrc).text(urlsrc));
  303. }
  304. }
  305.  
  306. $("#wazemy_camSource").change(function (e) {
  307. switch (this.value) {
  308. case 'Jalanow':
  309. wazemyTrafcam_getJalanowImage(trafficCamsData[$('#mycamid').text()]['url']['Jalanow']);
  310. break;
  311. case 'LLM':
  312. wazemyTrafcam_getLLMImage(trafficCamsData[$('#mycamid').text()]['url']['LLM']);
  313. break;
  314. }
  315. });
  316.  
  317. // Get image for the first time when popup is displayed.
  318. switch (Object.keys(this.url)[0]) {
  319. case 'Jalanow':
  320. wazemyTrafcam_getJalanowImage(this.url['Jalanow']);
  321. break;
  322. case 'LLM':
  323. wazemyTrafcam_getLLMImage(this.url['LLM']);
  324. break;
  325. }
  326.  
  327. // Handle cases where popup is too near the edge.
  328. let tw = $('#gmPopupContainerCam').width();
  329. let th = $('#gmPopupContainerCam').height() + 200;
  330. var tooltipX = e.clientX + window.scrollX + 15;
  331. var tooltipY = e.clientY + window.scrollY + 15;
  332. if ((tooltipX + tw) > W.map.$map.innerWidth()) {
  333. tooltipX -= tw + 20; // 20 = scroll bar size
  334. if (tooltipX < 0) tooltipX = 0;
  335. }
  336. if ((tooltipY + th) > W.map.$map.innerHeight()) {
  337. tooltipY -= th + 20;
  338. if (tooltipY < 0) tooltipY = 0;
  339. }
  340.  
  341. $("#gmPopupContainerCam").css({ left: tooltipX });
  342. $("#gmPopupContainerCam").css({ top: tooltipY });
  343.  
  344. //Add listener for popup's "Close" button
  345. $("#gmCloseCamDlgBtn").click(function () {
  346. clearInterval(staticUpdateID);
  347. $("#gmPopupContainerCam").remove();
  348. $("#gmPopupContainerCam").hide();
  349. });
  350. wazemyTrafcam_dragElement(document.getElementById("gmPopupContainerCam"));
  351.  
  352. }
  353.  
  354. function wazemyTrafcam_getJalanowImage(url) {
  355. GM_xmlhttpRequest({
  356. method: 'GET',
  357. responseType: 'blob',
  358. headers: {
  359. "authority": "p4.fgies.com",
  360. "referer": 'https://www.jalanow.com/',
  361. 'accept': 'image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8'
  362. },
  363. url: url,
  364. onload: function (response) {
  365. document.getElementById('staticimage').src = URL.createObjectURL(response.response);
  366. }
  367. });
  368. }
  369.  
  370. function wazemyTrafcam_getLLMImage(url) {
  371. let camImg = url.split("|");
  372.  
  373. GM_xmlhttpRequest({
  374. method: 'GET',
  375. responseType: 'document',
  376. url: camImg[0],
  377. onload: function (response) {
  378. const re = new RegExp('src="data:image\/png;base64, ([A-Za-z0-9/+=]*)" title="' + camImg[1] + '"');
  379. const m = response.responseText.match(re);
  380. document.getElementById('staticimage').src = "data:image/png;base64," + m[1];
  381. }
  382. })
  383. }
  384.  
  385. function wazemyTrafcam_installIconClass() {
  386. OpenLayers.Icon = OpenLayers.Class({
  387. url: null,
  388. size: null,
  389. offset: null,
  390. calculateOffset: null,
  391. imageDiv: null,
  392. px: null,
  393. initialize: function (a, b, c, d) {
  394. this.url = a;
  395. this.size = b || {
  396. w: 20,
  397. h: 20
  398. };
  399. this.offset = c || {
  400. x: -(this.size.w / 2),
  401. y: -(this.size.h / 2)
  402. };
  403. this.calculateOffset = d;
  404. a = OpenLayers.Util.createUniqueID("OL_Icon_");
  405. let div = this.imageDiv = OpenLayers.Util.createAlphaImageDiv(a);
  406. $(div.firstChild).removeClass('olAlphaImg'); // LEAVE THIS LINE TO PREVENT WME-HARDHATS SCRIPT FROM TURNING ALL ICONS INTO HARDHAT WAZERS --MAPOMATIC
  407. },
  408. destroy: function () {
  409. this.erase();
  410. OpenLayers.Event.stopObservingElement(this.imageDiv.firstChild);
  411. this.imageDiv.innerHTML = "";
  412. this.imageDiv = null;
  413. },
  414. clone: function () {
  415. return new OpenLayers.Icon(this.url, this.size, this.offset, this.calculateOffset);
  416. },
  417. setSize: function (a) {
  418. null !== a && (this.size = a);
  419. this.draw();
  420. },
  421. setUrl: function (a) {
  422. null !== a && (this.url = a);
  423. this.draw();
  424. },
  425. draw: function (a) {
  426. OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, null, this.size, this.url, "absolute");
  427. this.moveTo(a);
  428. return this.imageDiv;
  429. },
  430. erase: function () {
  431. null !== this.imageDiv && null !== this.imageDiv.parentNode && OpenLayers.Element.remove(this.imageDiv);
  432. },
  433. setOpacity: function (a) {
  434. OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, null, null, null, null, null, null, a);
  435. },
  436. moveTo: function (a) {
  437. null !== a && (this.px = a);
  438. null !== this.imageDiv && (null === this.px ? this.display(!1) : (
  439. this.calculateOffset && (this.offset = this.calculateOffset(this.size)),
  440. OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, {
  441. x: this.px.x + this.offset.x,
  442. y: this.px.y + this.offset.y
  443. })
  444. ));
  445. },
  446. display: function (a) {
  447. this.imageDiv.style.display = a ? "" : "none";
  448. },
  449. isDrawn: function () {
  450. return this.imageDiv && this.imageDiv.parentNode && 11 != this.imageDiv.parentNode.nodeType;
  451. },
  452. CLASS_NAME: "OpenLayers.Icon"
  453. });
  454. }
  455.  
  456. // Make the DIV element draggable:
  457. function wazemyTrafcam_dragElement(elmnt) {
  458. var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
  459. if (document.getElementById("mycamdivheader")) {
  460. // if present, the header is where you move the DIV from:
  461. document.getElementById("mycamdivheader").onmousedown = dragMouseDown;
  462. } else {
  463. // otherwise, move the DIV from anywhere inside the DIV:
  464. elmnt.onmousedown = dragMouseDown;
  465. }
  466.  
  467. function dragMouseDown(e) {
  468. e = e || window.event;
  469. e.preventDefault();
  470. // get the mouse cursor position at startup:
  471. pos3 = e.clientX;
  472. pos4 = e.clientY;
  473. document.onmouseup = closeDragElement;
  474. // call a function whenever the cursor moves:
  475. document.onmousemove = elementDrag;
  476. }
  477.  
  478. function elementDrag(e) {
  479. e = e || window.event;
  480. e.preventDefault();
  481. // calculate the new cursor position:
  482. pos1 = pos3 - e.clientX;
  483. pos2 = pos4 - e.clientY;
  484. pos3 = e.clientX;
  485. pos4 = e.clientY;
  486. // set the element's new position:
  487. elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
  488. elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
  489. }
  490.  
  491. function closeDragElement() {
  492. // stop moving when mouse button is released:
  493. document.onmouseup = null;
  494. document.onmousemove = null;
  495. }
  496. }
  497.  
  498. /* ************ */
  499. /* Copy lat/lon */
  500. /* ************ */
  501. function wazemyCopyLatLon() {
  502. copyToClipboard($('.mouse-position').text());
  503. }
  504.  
  505. function initializeSettings() {
  506. loadSettings();
  507.  
  508. $('#wazemyVersion').text(GM_info.script.version);
  509. $('#wazemyUsername').text(WazeWrap.User.Username());
  510. $('#wazemyRank').text(WazeWrap.User.Rank());
  511.  
  512. wazemyTooltip_initSettings();
  513. wazemyTrafcam_initSettings();
  514. }
  515.  
  516. function saveSettings() {
  517. if (localStorage) {
  518. var localsettings = {
  519. tooltip: settings.tooltip,
  520. trafcam: settings.trafcam
  521. };
  522.  
  523. localStorage.setItem('WME_wazemySettings', JSON.stringify(localsettings));
  524. }
  525. }
  526.  
  527. function loadSettings() {
  528. var loadedSettings = $.parseJSON(localStorage.getItem("WME_wazemySettings"));
  529. var defaultSettings = {
  530. tooltip: false,
  531. };
  532. settings = loadedSettings ? loadedSettings : defaultSettings;
  533. for (var prop in defaultSettings) {
  534. if (!settings.hasOwnProperty(prop)) {
  535. settings[prop] = defaultSettings[prop];
  536. }
  537. }
  538. }
  539.  
  540. function setChecked(checkboxId, checked) {
  541. $('#' + checkboxId).prop('checked', checked);
  542. }
  543.  
  544. // utility functions
  545. var copyToClipboard = function (str) { // from PIE
  546. var $temp = $('<input>');
  547. $('body').append($temp);
  548. $temp.val(str).select();
  549. document.execCommand('copy');
  550. $temp.remove();
  551. };
  552.  
  553. bootstrap();
  554. })();