Greasy Fork镜像 支持简体中文。

WME E58 Map's previews

Create small previews for chosen map providers

  1. // ==UserScript==
  2. // @name WME E58 Map's previews
  3. // @name:uk WME 🇺🇦 E58 Map's previews
  4. // @version 0.6.3
  5. // @description Create small previews for chosen map providers
  6. // @description:uk Створює невеличку карту для перегляду
  7. // @license MIT License
  8. // @author Anton Shevchuk
  9. // @namespace https://gf.qytechs.cn/users/227648-anton-shevchuk
  10. // @supportURL https://github.com/AntonShevchuk/wme-e58/issues
  11. // @match https://*.waze.com/editor*
  12. // @match https://*.waze.com/*/editor*
  13. // @exclude https://*.waze.com/user/editor*
  14. // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4wkRCQAIuLsiugAACEFJREFUeNrtmntMVFcexz/3zjDMDAMCg4Diq/WBwUXXrWjVrkkVny1od3201AdNrMa6KbZbQ1I3orY11S1rxUhaY2LQFmwr1qhVtFrtplgxbHBXlEJ1rSvqDKAVmBePmbt/oBfuDI8RsSrON5mEc+4595zf7/y+v8e5gA8++OCDDz744IMPPvjwJEJQtFaziHoWGwINz+jUOp2E1E2EFLA32u2WWsu/0LCddWQpBqjWqvxZTVl8Vrxktpil7ooKa4UUnxUvsZoy1VqVttkCVlO6ecbmIW+OeRMAl+Si0dXYrUxdLaoRBRGAjIIMUg6llLGOaIHVLJw8aHLW0QVHAdhcsJm3Dr9FdzH/ljTYNH0TKWNSAJiyawrfXvx2oYpnychfmt/foDGw5cwWUg6luHuGboO8n/MwBhgZEzWG+IHxpJ9INwoBHwRYLe9a9C7JhSpNBWI3d/sucK51Igoihg8MNlHvp9cD1Dvr6WZW3zqkO7ICeo1er27Jkcf1ROWDE/GKvi1lVXuzhlFvJCowqlP7q62v5fKty/LGjDojUUHevUsURC5UXpBPrOUpGvwNjOw1kucHPE9UUBT2BjtFN4o4XX6a0spSr6ms9sZkkmKTyJie0SkFHP/vceJ3xIOqqb1k1BLWT1rv9fxBmwdx6ddLiv28GP0iB5IOtDnnp6qfGLVtFNZ6a8dK9oo2Uuedg1NyKtoRARH3SFnl2gtGLGhXeIChYUOxvGuR4/59K6ArEWG4NwUo+Cqq2TFrh8eY/Kv5mCwmj/4Nkzc0+Yj7okAryP9fPqfKT3ml4bKqMoVjijREKp7HbI1p8z2iIHK15qps+i8MeQGVqJKfl1SWMCxzGFJjk5XMGDqDb179Rn6+4tkVrNy/ErRdrIBDPx9i/Yn13iVMgtLO3C2g5GpJuxtsicUjFyva7/3zvSZ63tFJ3sU86p31aFQa2WLCQsOoslV1LQVEQWyaqfLi57ZCL0OvTtPn6dCnFe0rt68oI6LkwiW57olyv7kP8Ff7y39X11XfU9ptspo8D6INfyGv4ah+dBQgCIJik7ftt2WlRBgi6B3YG6POiCC0rpWss8oyfnDoYI/3uyulvKL8EVIAgkK4W45bJAxPwPE3B6Z3TFz76zWqUqtwpbkYGjbUw5fsPrcbp6s5rH445UNoUbU/1+85mf8A6afSQfMAosC0QdMI1ga3eVJyFlhXy5pja+RV3C0gNjyW/a/sb3VuyV9KSMpNIudcjtxX76wneV8yu/60C4BwfTi2NBuVtkr0fnrC9GHy2DpnHSuPruzwiDulgPH9xjO+3/gOx1VaK1lzpIUCEDzienvI/nM2313+DrPFLPd99u/PMFvMfDn3S4K1wej8dPTr0U8x75PCT3g7722v7jQeKAXcPbI7Be7i08JPSTuRRtGNIo9nGydvVFapDRA/MJ6aupo2M8/hEcOJ6RnTYRLUaQvwFi35eJcC7qc+OGMwFysvggjrjq1j9yu7mfe7efLzhOgEqEPOFQqWFzA6arQiFJ65fgajzsjEpyaiElSM6zuOwqWFTN01laOXjna9Ar4o/oKvLnyFSlC1O87R6AA/FBwWUgWFYxO0gpzI4AcvZ7/MzHUz0aqbJA7RhqAL1GGvt/NSzEsK4XMv5DI7azb4N5XFvYJ7cf2d6/LzIwuOIKwW2rXzTimguKKY3OJc7wjkPkbXfrGDX5Pv6Nujr9w1ImIEp8tPs3feXsXQpQeXNr9PhBuWG+wv3U9idKI85rVnXmNH0Y5HJxHyJnV2r/+D/IMI0YYo+mwNNm7evukx3V3YCf0ntHvT9XAUILnd5LihZcEDUFNXg0at8YgwrWWRFdYKRTtUF9quAtS/pdCpf0wlMTqRQE0gIboQ5u+dz/e/fO9xxWXQGBRdZ01nCfQPVPRFBka2KlifoD6Ktsdt0sO0AEejg3F9xxEbEUufoD4sH70c3PY3ovcIRUJzy34Lh8WBvcGurClU/vQI6uGxxsLfL1QWTNVXut4JxkXFsSRuiVf3ASpBxZ6SPZgtZrYVbmPT1E1yLjAnZg7vT3uf9B/TsdZbmfjURA7PP6yYf6D0APiDpc5CtaOaHtpmoT+a8hGv73m9KYpIEBkcyYzBMxTzD5Ye7PowmBidqPC0HaHIVITZYsbR6KC8tpy+Qc0eftWEVayasKrNuanHUmWuz9o9ixPJJ5rvB/6wmIToBHIv5BIeEM7smNnK6tFi4mTpyaYw+ShQQEKi/z/6d8jLu1j09SLMtc1p8MlfTlJsLva4Y3wj7g0P4QESshPaFf6hRAEJCeMGY5up7F3E74xn59mdHp4+NjOWg2UHO1xnyJYhFF4v7IJUWIB9pfsoqSrplMCiIHK+8ryiz1JvIXRDKNHGaFaMXcHYPmPRqDScrzjP1jNb+eHqD9Q11rV+WSJAwucJBPgHkBSbxNxhcxkQPABbg42CawV8/OPHlN0s8/rrttBzY0+pYmUFjkYHurW65rS0tdh9H8lN2xVTi3cLLX7e5hN3f4KXNu0Ee5odrVpL+N/DUdsabDZAr1Fp2hfyQX05E+9TscI9c1Au0mwNNptorbEWmiwmREEkc2amVyXkYwsXZM7MRBRETBYT1hproRp/tifvS56QNz+PZXHLKK8tJ/s/2R6Jx+MOnZ+OpNgklsUtAyD562TwZ/udYMzlnHM50pOCnHM5Equ43MzsNPyQME8aOCnk8KuHUYmqx/dzeTvh1+lyMv3z6Ry/dPxXBCJYS4MspbBGECSXNFUQhT1atTbAmzT3saK/5MLR6LBKLmmOIAp50hrpSfh3EB988MEHH3zwwQcffPChDfwfw9+O2zXuDfAAAAAASUVORK5CYII=
  15. // @grant none
  16. // @require https://update.gf.qytechs.cn/scripts/389765/1090053/CommonUtils.js
  17. // @require https://update.gf.qytechs.cn/scripts/450160/1218867/WME-Bootstrap.js
  18. // @require https://update.gf.qytechs.cn/scripts/450221/1137043/WME-Base.js
  19. // @require https://update.gf.qytechs.cn/scripts/450320/1555446/WME-UI.js
  20. // ==/UserScript==
  21.  
  22. /* jshint esversion: 8 */
  23. /* global require */
  24. /* global $, jQuery */
  25. /* global W */
  26. /* global I18n */
  27. /* global WME, WMEBase, WMEUI, WMEUIHelper */
  28. /* global Container, Settings, SimpleCache, Tools */
  29. /* global H, google */
  30.  
  31. (function () {
  32. 'use strict'
  33.  
  34. const NAME = 'E58'
  35.  
  36. // Translation
  37. const TRANSLATION = {
  38. 'en': {
  39. // Tab title
  40. title: 'Map preview',
  41. // Tab description
  42. description: 'Open a small preview modal window with the map',
  43. // Tab help
  44. help: 'You can use the <a href="#keyboard-dialog" target="_blank" rel="noopener noreferrer" data-toggle="modal">Keyboard shortcuts</a> to open the map preview window. It\'s more convenient than clicking on the button.',
  45. maps: {
  46. // Fieldset's legend
  47. title: 'Sources',
  48. // Fieldset's description
  49. description: 'Choose a map provider',
  50. // Description for option `Google`
  51. google: 'Google',
  52. // Description for option `OSM`
  53. osm: 'Open Street Map',
  54. },
  55. options: {
  56. title: 'Options',
  57. description: 'Choose a map provider in the settings',
  58. controls: 'Controls on the map',
  59. interactive: 'Interaction with the map',
  60. },
  61. },
  62. 'uk': {
  63. title: 'Карта',
  64. description: 'Відкрити маленьку карту',
  65. help: 'Використовуйте <a href="#keyboard-dialog" target="_blank" rel="noopener noreferrer" data-toggle="modal">гарячі клавіши</a>, це значно швидше ніж використовувати кнопку',
  66. maps: {
  67. title: 'Джерела',
  68. description: 'Оберіть карту для відображення',
  69. google: 'Google',
  70. osm: 'Open Street Map',
  71. },
  72. options: {
  73. title: 'Налаштування',
  74. description: 'Оберіть у налаштуваннях карту для відображення',
  75. controls: 'Елементи управління',
  76. interactive: 'Можливість взаємодіяти с картою',
  77. },
  78. },
  79. 'ru': {
  80. title: 'Карта',
  81. description: 'Открыть маленькую карту',
  82. help: 'Используйте <a href="#keyboard-dialog" target="_blank" rel="noopener noreferrer" data-toggle="modal">комбинации клавиш</a>, и не надо будет клацать кнопку',
  83. maps: {
  84. title: 'Источники',
  85. description: 'Выберите карту для отображения',
  86. google: 'Google',
  87. osm: 'Open Street Map',
  88. },
  89. options: {
  90. title: 'Настройки',
  91. description: 'Выберите в настройках карту для отображения',
  92. controls: 'Элементи управления карты',
  93. interactive: 'Возможность взаимодествия с картой',
  94. },
  95. }
  96. }
  97.  
  98. const STYLE =
  99. '.e58 .header h5 { padding: 16px 16px 0; font-size: 16px }' +
  100. '.e58 legend { cursor:pointer; font-size: 12px; font-weight: bold; width: auto; text-align: right; border: 0; margin: 0; padding: 0 8px; }' +
  101. '.e58 fieldset { border: 1px solid #ddd; padding: 4px; }' +
  102. '.e58 fieldset p { padding: 0; margin: 0 8px !important; }' +
  103. '.e58 fieldset.e58 div.controls label { white-space: normal; font-weight: 400; }' +
  104. 'div.e58.e58-text { margin: 15px 0; }' +
  105. 'p.e58-info { border-top: 1px solid #ccc; color: #777; font-size: x-small; margin-top: 15px; padding-top: 10px; text-align: center; }'
  106.  
  107. WMEUI.addTranslation(NAME, TRANSLATION)
  108. WMEUI.addStyle(STYLE)
  109.  
  110. // Default settings
  111. const SETTINGS = {
  112. map: 'google',
  113. maps: [
  114. 'google', 'osm'
  115. ],
  116. options: {
  117. controls: false,
  118. interactive: false,
  119. }
  120. }
  121.  
  122. /**
  123. * Basic Map class
  124. */
  125. class MapPreview {
  126. constructor (uid, container, settings) {
  127. this.uid = uid
  128. this.map = null
  129. this.wrapper = this._wrapper()
  130.  
  131. container.append(this.wrapper)
  132. container.style.height = '256px'
  133.  
  134. this.settings = settings
  135. this.controls = settings.get('options', 'controls')
  136. this.interactive = settings.get('options', 'interactive')
  137. }
  138.  
  139. /**
  140. * Load external JS Map library
  141. * @param {String} url
  142. * @return {Promise<*>}
  143. */
  144. async script (url) {
  145. return $.ajax({
  146. url: url,
  147. cache: true,
  148. dataType: 'script',
  149. success: () => console.log(NAME, this.uid, 'loaded')
  150. })
  151. }
  152.  
  153. /**
  154. * Build div for map
  155. * @return {HTMLDivElement}
  156. * @protected
  157. */
  158. _wrapper () {
  159. let div = document.createElement('div')
  160. div.id = this._uid()
  161. div.style.height = '256px'
  162. return div
  163. }
  164.  
  165. _uid () {
  166. return NAME + '-map-' + this.uid
  167. }
  168.  
  169. _center () {
  170. let center = new OpenLayers.Geometry.Point(W.map.getCenter().lon, W.map.getCenter().lat).transform('EPSG:900913', 'EPSG:4326')
  171.  
  172. return {
  173. lon: center.x,
  174. lat: center.y,
  175. }
  176. }
  177.  
  178. _zoom () {
  179. return W.map.getZoom() - 1
  180. }
  181.  
  182. update () {
  183. let center = this._center()
  184. this._update(center.lat, center.lon, this._zoom())
  185. }
  186.  
  187. _update (lat, lon, zoom) {
  188. throw new Error('Abstract method')
  189. }
  190. }
  191.  
  192. /**
  193. * Google Maps
  194. */
  195. class GooglePreview extends MapPreview {
  196. constructor (container, settings) {
  197. super('Google', container, settings)
  198. }
  199.  
  200. async render () {
  201. let pos = this._center()
  202. this.map = new google.maps.Map(this.wrapper, {
  203. center: new google.maps.LatLng(pos.lat, pos.lon),
  204. zoom: this._zoom(),
  205. mapTypeId: 'roadmap',
  206. mapTypeControl: false,
  207. streetViewControl: false,
  208. disableDefaultUI: !this.controls,
  209. gestureHandling: this.interactive ? 'cooperative ' : 'none',
  210. zoomControl: this.controls,
  211. })
  212.  
  213. // Setup handler
  214. W.map.events.register('moveend', null, () => this.update())
  215. }
  216.  
  217. _update (lat, lon, zoom) {
  218. this.map.setZoom(zoom)
  219. this.map.setCenter(new google.maps.LatLng(lat, lon))
  220. }
  221. }
  222.  
  223. /**
  224. * Open Street Maps
  225. */
  226. class OSMPreview extends MapPreview {
  227. constructor (container, settings) {
  228. super('OSM', container, settings)
  229. }
  230.  
  231. async render () {
  232. let pos = this._center()
  233. this.map = new google.maps.Map(this.wrapper, {
  234. center: new google.maps.LatLng(pos.lat, pos.lon),
  235. zoom: this._zoom(),
  236. mapTypeId: 'OSM',
  237. mapTypeControl: false,
  238. streetViewControl: false,
  239. disableDefaultUI: !this.controls,
  240. gestureHandling: this.interactive ? 'cooperative ' : 'none',
  241. zoomControl: this.controls,
  242. })
  243.  
  244. // Define OSM map type pointing at the OpenStreetMap tile server
  245. this.map.mapTypes.set('OSM', new google.maps.ImageMapType({
  246. getTileUrl: function (coord, zoom) {
  247. return 'https://tile.openstreetmap.org/' + zoom + '/' + coord.x + '/' + coord.y + '.png'
  248. },
  249. tileSize: new google.maps.Size(256, 256),
  250. name: 'OpenStreetMap',
  251. maxZoom: 18
  252. }))
  253.  
  254. // Setup handler
  255. W.map.events.register('moveend', null, () => this.update())
  256. }
  257.  
  258. _update (lat, lon, zoom) {
  259. this.map.setZoom(zoom)
  260. this.map.setCenter(new google.maps.LatLng(lat, lon))
  261. }
  262. }
  263.  
  264. /**
  265. * E58 Map Preview class
  266. */
  267. class E58 extends WMEBase {
  268. constructor (name, settings) {
  269. super(name, settings)
  270.  
  271. this.helper = new WMEUIHelper(name)
  272.  
  273. let tab = this.helper.createTab(
  274. I18n.t(name).title,
  275. {
  276. image: GM_info.script.icon
  277. }
  278. )
  279. tab.addText('description', I18n.t(name).description)
  280. let button = tab.addButton('preview', I18n.t(name).title, '', () => this.toggleMap())
  281. button.html().className += ' waze-btn-blue'
  282.  
  283. // Setup providers map settings
  284. let fsMap = this.helper.createFieldset(I18n.t(name).maps.title)
  285.  
  286. for (let i = 0; i < settings.maps.length; i++) {
  287. let map = settings.maps[i]
  288. fsMap.addRadio(
  289. 'maps-' + map,
  290. I18n.t(name).maps[map],
  291. () => this.settings.set(['map'], map),
  292. 'maps',
  293. map,
  294. this.settings.get('map') === map
  295. )
  296. }
  297. tab.addElement(fsMap)
  298.  
  299. // Setup options for maps
  300. let fsOptions = this.helper.createFieldset(I18n.t(name).options.title)
  301. for (let item in settings.options) {
  302. if (settings.options.hasOwnProperty(item)) {
  303. fsOptions.addCheckbox(
  304. 'options-' + item,
  305. I18n.t(name).options[item],
  306. (event) => this.settings.set(['options', item], event.target.checked),
  307. this.settings.get('options', item))
  308. }
  309. }
  310. tab.addElement(fsOptions)
  311.  
  312. tab.addDiv('text', I18n.t(name).help)
  313. tab.addText(
  314. 'info',
  315. '<a href="' + GM_info.scriptUpdateURL + '">' + GM_info.script.name + '</a> ' + GM_info.script.version
  316. )
  317. tab.inject()
  318. }
  319.  
  320. /**
  321. * Show modal with map preview
  322. */
  323. toggleMap () {
  324. if (document.getElementById('e58-map-preview')) {
  325. this.log('hide preview map')
  326. $('#panel-container a.close-panel').click()
  327. return
  328. }
  329.  
  330. /** @type {WMEUIHelperModal} */
  331. let modal = this.helper.createModal(
  332. I18n.t(this.name).title
  333. )
  334. // Setup Preview Map element
  335. let map = modal.addDiv('map-preview').html()
  336. modal.inject()
  337.  
  338. this.log('show preview map', this.settings.get('map'))
  339.  
  340. if (this.settings.get('map') === 'google') {
  341. let Google = new GooglePreview(map, this.settings)
  342. Google.render()
  343. } else if (this.settings.get('map') === 'osm') {
  344. let OSM = new OSMPreview(map, this.settings)
  345. OSM.render()
  346. } else {
  347. // disabled
  348. map.innerText = I18n.t(this.name).maps.description
  349. }
  350. }
  351. }
  352.  
  353. // Main handler
  354. $(document).on('bootstrap.wme', () => {
  355. // Create E58 Instance
  356. let Instance = new E58(NAME, SETTINGS)
  357.  
  358. // Bind shortcut
  359. WMEUI.addShortcut(
  360. NAME,
  361. I18n.t(NAME).description,
  362. NAME,
  363. I18n.t(NAME).title + ' 🗺️',
  364. 'A+M',
  365. () => Instance.toggleMap(),
  366. )
  367. })
  368. })()

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址